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ę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.