兩個單獨wrl文件的事件互操作

    在VRML中,將不同物體放置在不同的wrl文件中的最大好處是,使VRML場景的層次結構更加清晰,代碼可讀性強,維護修改容易。
    通常,我們可以將一個場景裏的不同物體寫在不同的wrl文件中,最後在主場景wrl文件裏將各個物體通過“Inline”節點導入,形成一個完整場景。
    這種方式對於用戶交互和動畫比較少並且形式單純的方式比較合適,但是在一些複雜情況下,用“Inline”節點是無法實現的。其原因在於“Inline”節點沒有用於交互的輸入輸出事件。

    舉一個最簡單的例子。場景中有兩個物體A和B,A具有插值動畫,可以旋轉,B具有一個touchSensor(觸摸感應器)。
    現在要求實現:
    1.A物體的繪製和動畫代碼寫在a.wrl文件中,B物體的繪製和觸發器代碼寫在b.wrl文件中(這樣做的目的是爲了實現前面描述的好處。)
    2.鼠標點擊物體B後,觸發A物體的動畫。

    顯然,使用“Inline”節點是無法同時滿足上面兩個條件的。

    但是兩個條件在VRML中並非無法滿足。
    這個時候,我們需要使用PROTO節點和EXTERNPROTO進行原型聲明和外部引用。下面對代碼編寫進行詳細說明。

    首先,將a.wrl和b.wrl的完整代碼貼上來:

a.wrl:
  1. #VRML V2.0 utf8

  2. #Cosmo Worlds V2.0

  3. PROTO KfaPositionInterpolator [
  4.         eventIn      SFFloat    set_fraction
  5.         eventOut     SFVec3f    value_changed
  6.         exposedField MFFloat    key 0
  7.         exposedField MFInt32    keyTypes    2
  8.         exposedField MFVec3f    keyValue    0 0 0
  9.         field        MFFloat    authorKey   0
  10.         field        MFVec3f    authorKeyValue  0 0 0
  11.       ]
  12. {
  13.   PositionInterpolator {
  14.     key IS key
  15.     set_fraction IS set_fraction
  16.     keyValue IS keyValue
  17.     value_changed IS value_changed
  18.   }
  19. }
  20. PROTO KfaAnimation [
  21.         field        SFFloat    framesPerSecond 10
  22.         field        SFFloat    zoom    1
  23.         field        SFBool snap    TRUE
  24.         field        SFBool viewInFrames    TRUE
  25.         field        SFBool showEmptyFieldLines FALSE
  26.         field        SFFloat    playRangeStart  0
  27.         field        SFFloat    playRangeEnd    1
  28.         field        SFBool usePlayRange    TRUE
  29.         field        SFNode timeSensor  NULL
  30.         field        MFNode fieldInterps    []
  31.         field        MFNode actors  []
  32.       ]
  33. {
  34.   Group {
  35.   }
  36. }


  1. PROTO AnimationInA [
  2.     eventIn SFTime TouchTime  
  3. ]
  4. {
  5. DEF _0 Transform {
  6.   children  [
  7.     Shape {
  8.       appearance    Appearance {
  9.     material    Material {
  10.     }
  11.       }
  12.       geometry  Box {
  13.       }
  14.     }
  15.     DEF UnnamedAnimation0 KfaAnimation {
  16.       framesPerSecond   25
  17.       snap  TRUE
  18.       viewInFrames  TRUE
  19.       playRangeStart    0
  20.       playRangeEnd  1
  21.       timeSensor DEF UnnamedAnimation0Time TimeSensor {
  22.           startTime IS TouchTime
  23.           cycleInterval   4
  24.       }
  25.       actors    USE _0
  26.       fieldInterps  [
  27.     
  28.     DEF UnnamedTransformScaleInterp KfaPositionInterpolator {
  29.       key   [ 0, 0.01, 0.02, 0.03,
  30.             0.04, 0.05, 0.06, 0.07,
  31.             0.08, 0.09, 0.1, 0.11,
  32.             0.12, 0.13, 0.14, 0.15,
  33.             0.16, 0.17, 0.18, 0.19,
  34.             0.2, 0.21, 0.22, 0.23,
  35.             0.24, 0.25, 0.26, 0.27,
  36.             0.28, 0.29, 0.3, 0.31,
  37.             0.32, 0.33, 0.34, 0.35,
  38.             0.36, 0.37, 0.38, 0.39,
  39.             0.4, 0.41, 0.42, 0.43,
  40.             0.44, 0.45, 0.46, 0.47,
  41.             0.48, 0.49, 0.5, 0.51,
  42.             0.52, 0.53, 0.54, 0.55,
  43.             0.56, 0.57, 0.58, 0.59,
  44.             0.6, 0.61, 0.62, 0.63,
  45.             0.64, 0.65, 0.66, 0.67,
  46.             0.68, 0.69, 0.7, 0.71,
  47.             0.72, 0.73, 0.74, 0.75,
  48.             0.76, 0.77, 0.779999, 0.789999,
  49.             0.799999, 0.809999, 0.819999, 0.829999,
  50.             0.839999, 0.849999, 0.859999, 0.869999,
  51.             0.879999, 0.889999, 0.899999, 0.909999,
  52.             0.919999, 0.929999, 0.939999, 0.949999,
  53.             0.959999, 0.969999, 0.979999, 0.989999,
  54.             1 ]
  55.       keyTypes  [ 2, 2, 2 ]
  56.       authorKey [ 0, 0.25, 1 ]
  57.       keyValue  [ 1 1 1,
  58.             1.05987 1.05987 1.05987,
  59.             1.12379 1.12379 1.12379,
  60.             1.19122 1.19122 1.19122,
  61.             1.26161 1.26161 1.26161,
  62.             1.33439 1.33439 1.33439,
  63.             1.40902 1.40902 1.40902,
  64.             1.48493 1.48493 1.48493,
  65.             1.56159 1.56159 1.56159,
  66.             1.63843 1.63843 1.63843,
  67.             1.7149 1.7149 1.7149,
  68.             1.79045 1.79045 1.79045,
  69.             1.86452 1.86452 1.86452,
  70.             1.93657 1.93657 1.93657,
  71.             2.00603 2.00603 2.00603,
  72.             2.07235 2.07235 2.07235,
  73.             2.13498 2.13498 2.13498,
  74.             2.19338 2.19338 2.19338,
  75.             2.24697 2.24697 2.24697,
  76.             2.29521 2.29521 2.29521,
  77.             2.33756 2.33756 2.33756,
  78.             2.37344 2.37344 2.37344,
  79.             2.40231 2.40231 2.40231,
  80.             2.42362 2.42362 2.42362,
  81.             2.43681 2.43681 2.43681,
  82.             2.44133 2.44133 2.44133,
  83.             2.44082 2.44082 2.44082,
  84.             2.43931 2.43931 2.43931,
  85.             2.43681 2.43681 2.43681,
  86.             2.43335 2.43335 2.43335,
  87.             2.42895 2.42895 2.42895,
  88.             2.42362 2.42362 2.42362,
  89.             2.41739 2.41739 2.41739,
  90.             2.41028 2.41028 2.41028,
  91.             2.40231 2.40231 2.40231,
  92.             2.3935 2.3935 2.3935,
  93.             2.38387 2.38387 2.38387,
  94.             2.37344 2.37344 2.37344,
  95.             2.36223 2.36223 2.36223,
  96.             2.35026 2.35026 2.35026,
  97.             2.33756 2.33756 2.33756,
  98.             2.32413 2.32413 2.32413,
  99.             2.31001 2.31001 2.31001,
  100.             2.29521 2.29521 2.29521,
  101.             2.27976 2.27976 2.27976,
  102.             2.26367 2.26367 2.26367,
  103.             2.24697 2.24697 2.24697,
  104.             2.22967 2.22967 2.22967,
  105.             2.2118 2.2118 2.2118,
  106.             2.19338 2.19338 2.19338,
  107.             2.17442 2.17442 2.17442,
  108.             2.15495 2.15495 2.15495,
  109.             2.13499 2.13499 2.13499,
  110.             2.11455 2.11455 2.11455,
  111.             2.09367 2.09367 2.09367,
  112.             2.07235 2.07235 2.07235,
  113.             2.05063 2.05063 2.05063,
  114.             2.02851 2.02851 2.02851,
  115.             2.00603 2.00603 2.00603,
  116.             1.98319 1.98319 1.98319,
  117.             1.96003 1.96003 1.96003,
  118.             1.93657 1.93657 1.93657,
  119.             1.91281 1.91281 1.91281,
  120.             1.88879 1.88879 1.88879,
  121.             1.86452 1.86452 1.86452,
  122.             1.84003 1.84003 1.84003,
  123.             1.81533 1.81533 1.81533,
  124.             1.79045 1.79045 1.79045,
  125.             1.7654 1.7654 1.7654,
  126.             1.74021 1.74021 1.74021,
  127.             1.7149 1.7149 1.7149,
  128.             1.68949 1.68949 1.68949,
  129.             1.66399 1.66399 1.66399,
  130.             1.63843 1.63843 1.63843,
  131.             1.61283 1.61283 1.61283,
  132.             1.58721 1.58721 1.58721,
  133.             1.56159 1.56159 1.56159,
  134.             1.53599 1.53599 1.53599,
  135.             1.51043 1.51043 1.51043,
  136.             1.48493 1.48493 1.48493,
  137.             1.45952 1.45952 1.45952,
  138.             1.43421 1.43421 1.43421,
  139.             1.40902 1.40902 1.40902,
  140.             1.38397 1.38397 1.38397,
  141.             1.35909 1.35909 1.35909,
  142.             1.33439 1.33439 1.33439,
  143.             1.3099 1.3099 1.3099,
  144.             1.28563 1.28563 1.28563,
  145.             1.26161 1.26161 1.26161,
  146.             1.23785 1.23785 1.23785,
  147.             1.21439 1.21439 1.21439,
  148.             1.19123 1.19123 1.19123,
  149.             1.16839 1.16839 1.16839,
  150.             1.14591 1.14591 1.14591,
  151.             1.12379 1.12379 1.12379,
  152.             1.10207 1.10207 1.10207,
  153.             1.08075 1.08075 1.08075,
  154.             1.05987 1.05987 1.05987,
  155.             1.03943 1.03943 1.03943,
  156.             1.01947 1.01947 1.01947,
  157.             1 1 1 ]
  158.       authorKeyValue    [ 1 1 1,
  159.             2.44133 2.44133 2.44133,
  160.             1 1 1 ]
  161.     }
  162.       ]
  163.     }
  164.   ]
  165.   translation   4 1 0
  166.   rotation  0 1 0  3.14159
  167.   scale 1 1 1
  168. }
  169. ROUTE UnnamedAnimation0Time.fraction_changed TO UnnamedTransformScaleInterp.set_fraction  
  170. ROUTE UnnamedTransformScaleInterp.value_changed TO _0.set_scale
  171. }


b.wrl:
  1. #VRML V2.0 utf8
  2. #Cosmo Worlds V2.0
  3.     Transform {
  4.         children    [
  5.             DEF TS TouchSensor {}
  6.             Shape {
  7.                 appearance  Appearance {
  8.                     material    Material {
  9.                     }   
  10.                 }  
  11.                 geometry    Sphere {
  12.                 }      
  13.             }
  14.         ]  
  15.         translation -3 1 0
  16.     }
  17.     EXTERNPROTO AnimationInB [
  18.         eventIn SFTime TouchTime
  19.     ]
  20.     "a.wrl#AnimationInA"

  21.     DEF animation AnimationInB {}
  22.     ROUTE TS.touchTime TO   animation.TouchTime


    分析一下。代碼很簡單,a.wrl中,畫了一個正方體,並使用一個TimeSensor和PositionInterpolator實現插值動畫。b.wrl中,畫了一個球體,並在球題上安裝了一個touchSensor作爲鼠標點擊的感應器。

    注意,
在a.wrl文件中,我們將A物體的繪製和動畫代碼使用PROTO括起來,使它成爲一個原型(相當於一個自定義的節點。如果不知原型爲何物,請參閱任意關於VRML的教材)。
    原型的域中,我們加入一個時間型入事件:
  1. eventIn SFTime TouchTime
    這個入事件的作用,後面再詳細說。
    接下來,在時間感應器TimeSensor中,我們這樣寫:
  1.  timeSensor    DEF UnnamedAnimation0Time TimeSensor {
  2.      startTime IS TouchTime
  3.      cycleInterval   4
  4.        }
    注意裏面的“startTime IS TouchTime”一句,表明將前面定義的時間型入事件 TouchTime作爲這個TimeSensor的開始時間。

    最後,注意動畫的路由:
  1. ROUTE UnnamedAnimation0Time.fraction_changed TO UnnamedTransformScaleInterp.set_fraction  
  2. ROUTE UnnamedTransformScaleInterp.value_changed TO _0.set_scale
    也要包括在原型中。


    好了,再來分析b.wrl。
    b.wrl在繪製完一個球體後,使用:
  1. EXTERNPROTO Animation [
  2.     eventIn SFTime TouchTime
  3. ]
  4. "1.wrl#Animation"
    進行外部原型引用,引用路徑之所以寫成:"1.wrl#Animation",是因爲1.wrl中定義了好幾個原型,而我們這裏需要引用的是Animation這個原型。

    然後,我們使用
  1. DEF animation Animation {}
    生成一個實際的對象。在這裏,Animation實際上已經相當於VRML中已經有的節點。如果這裏看不懂,同樣,請參閱任何一本VRML書籍中,關於PROTO的介紹。

    最後,我們生成路由:
  1. ROUTE TS.touchTime TO   animation.TouchTime
   
    大功告成!


    說了這麼多,代碼雖然簡單,但是也有不少(其實主要的代碼量來自於插值動畫的中間值,真正的功能代碼非常少),下面進行一下總結:
    思路其實十分簡單。用戶點擊球體後,相當於觸發了球體上的touchSensor,產生一個時間型的事件,將此事件通過ROUTE TS.touchTime TO animation.TouchTime,傳遞給我們定義的原型AnimationInB,從而傳到了所引用的外部原型AnimationInA中(也就是說,傳到了a.wrl文件中),而由於AnimationInA的TimeSensor中有一個“startTime IS TouchTime”,所以這個時間型事件最終傳到了時間觸發器TimeSensor裏,觸發了動畫。

    原型定義PROTO和外部原型引用EXTERNPROTO是一對非常有用的節點,人和我們自己寫的擴展節點都要用到他們。靈活使用不僅能夠使我們的VRML場景更加豐富多彩,還能提高效率,減少代碼複寫率等。

    希望本文能夠起到一個拋磚引玉的作用。

    最後,給出運行效果截圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章