Dołączanie plików dźwiękowych i filmowych
(węzły Sound, MovieTexture i AudioClip) 
Nie na darmo VRML nazywa się spełnieniem marzeń o multimediach w Internecie. VRML to trójwymiarowe i dwuwymiarowe obrazy, tekst oraz dźwięki i filmy, którymi się teraz zajmiemy. Niestety zarówno pliki dźwiękowe jak i filmowe zajmują bardzo dużo pamięci w związku z czym rzadko się spotyka w sieci światy VRML, w których jest wiele takich smaczków. Jeżeli chodzi o dźwięki to często można spotkać  malutkie pliki WAV, które towarzyszą jakimś pojedynczym czynnościom jak, np. włączenie światła w pokoju. Rzadko się spotyka aby jakaś muzyka leciała przez cały czas w tle - jeżeli ktoś bardzo chce to efekt ten może uzyskać puszczając w pętli (powiedzmy 30 sekundową) melodię zapisaną w formacie MID.

Aby jakiejś czynności przypisać dźwięk musimy użyć węzła Sound, który wygląda następująco:

Sound {
  exposedField SFVec3f  direction     0 0 1
  exposedField SFFloat  intensity     1 
  exposedField SFVec3f  location      0 0 0   
  exposedField SFFloat  maxBack       10
  exposedField SFFloat  maxFront      10      
  exposedField SFFloat  minBack       1       
  exposedField SFFloat  minFront      1       
  exposedField SFFloat  priority      0       
  exposedField SFNode   source        NULL
  field        SFBool   spatialize    TRUE
}
 
W polu direction określamy kierunek, w którym dźwięk będzie się rozchodził. Pole intensity odpowiada za głośność z jaką dany dźwięk będzie odtwarzany (0 - cisza, 1 - pełna głośność). Pole location definiuje miejsce, z którego dany dźwięk będzie się rozchodził. Pole spatialize odpowiada za funkcję przestrzenności odgrywanego dźwięku. Jeżeli wyłączymy działanie tej funkcji (wartość FALSE) to dane dotyczące kierunku, w którym fale dźwiękowe mają się rozchodzić, zostaną zignorowane. Pole priority stanowi podpowiedź dla przeglądarki dotyczącą dźwięku, który ma odtwarzać w momencie gdy na scenie zdefiniowanych jest więcej niż jedno źródeł dźwięku. Pole priority podobnie jak pole intensity może przybierać wartości od 0 do 1, gdzie wartość 0 zdecydowanie pomniejsza słyszalność danego dźwięku, a wartość 1 nadaje mu pierwszeństwo.

Właściwości każdego dźwięku są takie, że jego fale rozchodzą się elipsoidalnie, w związku z czym dźwięk słychać również stojąc niedaleko od źródła dźwięku, które skierowane jest w stronę przeciwną. Zagadnienie to tłumaczy występowanie pól minBack, maxBack i minFront, maxFront. Wartość minBack określa właśnie odległość od źródła dźwięku "z tyłu", na której słyszalna jest pełna jego moc, a pole maxBack określa odległość również "z tyłu" źródła ale taką, na której dźwięk zupełnie zanika. Analogicznie wygląda sytuacja z polami minFront i maxFront - odnosi się ona jedynie do odległości od źródła dźwięku zgodnej z kierunkiem transmisji. Im większy będzie odstęp między wartościami min a max, tym dźwięk będzie narastał łagodniej podczas zbliżania się do jego źródła.

Powyższe zagadnienie ilustruje następny rysunek:

W polu source umieszczamy węzeł (AudioClip lub MovieTexture), w którym znajdzie się: ścieżka dostępu do pliku dźwiękowego oraz właściwości dotyczące trwania dźwięku w czasie. Podobnie jak węzeł TimeSensor, węzły AudioClip i MovieTexture są "węzłami zależnymi od czasu" - posiadają pola charaterystyczne dla tego typu węzłów i działają w podobny sposób.

Węzeł AudioClip zawiera następujące pola:

AudioClip {
  exposedField   SFString description      ""
  exposedField   SFBool   loop             FALSE
  exposedField   SFFloat  pitch            1.0
  exposedField   SFTime   startTime        0
  exposedField   SFTime   stopTime         0
  exposedField   MFString url              []
  eventOut       SFTime   duration_changed
  eventOut       SFBool   isActive
}

Pola loop, startTime i stopTime poznaliśmy już przy okazji omawiania węzła TimeSensor. W polu description możemy umieścić opis dźwięku - jednak do tej pory mało, która przeglądarka obsługuje tą funkcję. W polu pitch określamy czy dźwięk ma być odtwarzany z normalną prędkością (1) czy też ma lecieć szybciej (1>) lub wolniej (>1, 0>).

Poniższy przykład definiuje kulę, która porusza się po okręgu raz przybliżając i raz oddalając się od nas. W  środku kuli zdefiniowane zostało źródło dźwięku (plik MIDI odtwarzany non-stop). Ponadto jeżeli klikniemy na kulę usłyszymy dźwięk wystrzału lasera.

#VRML V2.0 utf8

DEF Obrot Transform {
   children [
      Transform {
         rotation 1 0 0 0
         translation 5 2 0
         children [
           DEF Click TouchSensor { }
           Sound {
              source DEF Efekt AudioClip {
                                 url "efekt.wav"
                                 loop FALSE }
               priority 0.5
               minFront 12
               minBack  12
               maxBack  30
               maxFront 30
               spatialize TRUE }

          Shape {
             appearance  Appearance { material Material {
                                    emissiveColor 1 0 0 }
                                    }
             geometry Sphere { radius 2 }
                }
          Sound {
             source AudioClip {
                      loop TRUE
                      url "x.mid" }
             priority 0.5
             direction 0 0 1
             minFront 12
             minBack  12
             maxBack  30
             maxFront 30
             spatialize TRUE }
 
           ]
       }
   ]
}

DEF Czas TimeSensor { loop TRUE
                      cycleInterval 5 }
 
DEF Interpolator OrientationInterpolator {
   key [ 0, .5, 1]
   keyValue [0 1 0 0, 0 1 0 3.14, 0 1 0 6.28]
}

#Połączenie zdarzeń odpowiedzialnych za efekt dźwiękowy
ROUTE Click.touchTime TO Efekt.startTime

#Połączenie zdarzeń wywołujących animację
ROUTE Czas.fraction_changed TO Interpolator.set_fraction
ROUTE Interpolator.value_changed TO Obrot.set_rotation
ROUTE Click.touchTime TO Czas.set_startTime

Po dodaniu kilku elementów nasz świat będzie wyglądał następująco.


Teraz zajmiemy się dołączaniem do światów VRML plików filmowych (MPEG lub AVI). Za tą operację odpowiada węzeł MovieTexture i jak sama nazwa wskazuje traktuje od plik filmowy jako "zwykłą" teksturę. Składnia tego węzła wygląda zastępująco:

MovieTexture {
  exposedField SFBool   loop             FALSE
  exposedField SFFloat  speed            1.0  
  exposedField SFTime   startTime        0   
  exposedField SFTime   stopTime         0   
  exposedField MFString url              []
  field        SFBool   repeatS          TRUE
  field        SFBool   repeatT          TRUE
  eventOut     SFTime   duration_changed
  eventOut     SFBool   isActive
}

Jak wszystkie inne węzły odpowiadające za nałożenie tekstury, węzeł MovieTexture umieszczamy w polu texture węzła Appearance i tak samo jak inne tekstury może ona podlegać operacji przesuwania, skalowania, obracania, rozciągania itp. Z polami loop, startTime i stopTime zapoznaliśmy się przy omawianiu węzła TimeSensor, z kolei pola repeatS i repeatT znamy z pierwszej części kursu. Pole speed działa na tej samej zasadzie co pole pitch węzła AudioClip - odpowiada za prędkość z jaką plik filmowy (umieszczony w polu url) będzie odtwarzany.

#VRML V2.0 utf8

Shape {
 appearance Appearance { texture MovieTexture {
                                 loop TRUE
                                 url "http://www.enter.pol.pl/vrml/test.mpg" }
                       }
 geometry Box { size 10 3 0.1 }
      }

Sound { source MovieTexture {
               loop TRUE
               url "http://www.enter.pol.pl/vrml/test.mpg" }
        minFront 12
        minBack  12
        maxBack  30
        maxFront 30
      }

Powyższy przykład nakłada teksturę z pliku filmowego na sześcian. Jeżeli plik filmowy zawiera podkład muzyczny i też chcemy aby był on słyszalny musimy jeszcze raz (tym razem w węźle Sound) zdefiniować węzeł MovieTexture - tym razem jako źródło dźwięku a nie obrazu.

UWAGA!!! Jeżeli nie posiadacie dobrego transferu nie ładujcie tego przykładu gdyż plik test.mpg zajmuje ok. 470 kb. Plik ten nie został również umieszczony w off-line'owej wersji kursu. Każdy z was napewno posiada jakiś plik filmowy (AVI lub MPEG - sprawdźcie CD z Windows95) na dysku lokalnym, aby powyższy przykład zadziałał zmieńcie jedynie ścieżkę dostępu w polach url. Jeżeli ktoś jest pewien, że nie posiada żadnego pliku filmowego to może go ściągnąć tutaj (Uwaga - 430 kb - test.zip).

Jeżeli ktoś się jeszcze nie zniechęcił to zapraszam na obejrzenie przykładu movie.wrl.