|
|
|
Eigene
3D-Skripte erstellen
Das Lingo-Inventar, das für einen schnellen Einstieg ins 3D-Skripting
nötig ist, ist überschaubar. Allerdings ist schon beim
Umgang mit Primitives den geometrischen Grundformen, die
direkt aus Lingo erzeugt werden können ein Verständnis
der Hierarchien im Shockwave3D-Darsteller nützlich.
Ein 3D-Darsteller enthält in sogenannten Paletten
organisiert Objekte der folgenden Typen:
- Modelresource
- Model
- Shader
- Texture
- Motion
- Light
- Camera
- Group
Diese Paletten sind im Darsteller ähnlich wie
Besetzungen des Director-Films organisiert. Sie liegen in der Hierarchie
direkt unterhalb des Darstellers und können entsprechend adressiert
werden. Mit den Funktionen newObjekttyp() und deleteObjekttyp()
werden entsprechende Einträge für alle Objekttypen erzeugt
bzw. entfernt:
mmb = member("Shockwave3D")
put mmb.model.count
-- 0
Res = mmb.newModelResource("Kugelres",#sphere)
Mod = mmb.newModel("Kugel", Res)
put mmb.model("Kugel")
-- model("Kugel")
mmb.deleteModel(1)
mmb.deleteModelResource("Kugelres")
Probieren Sie das Skript im Nachrichtenfenster aus, indem sie zunächst
einen Shockwave3D-Darsteller mit dem angegebenen Namen anlegen und
diesen zur Kontrolle per Doppelklick öffnen.
|


 |
|
|
Neben dem Paletten-Modell, das es ermöglicht,
Objekte im 3D-Darsteller zu erzeugen, zu verändern und zu löschen,
sind die Abhängigkeiten der Objekte untereinander wichtig.
Die Hierarchie für Modelle die uns hier zunächst
hauptsächlich beschäftigen soll sieht so aus:
Model
Modelresource
Shader(s)
Texture(s)
Das heißt, ein Model beruht auf einer Modelresource (diese
ist zum Erzeugen des Models notwendig), und dem Model werden sodann
Shader zugewiesen (die seine Oberflächeneigenschaften und die
Art des Renderings beschreiben). Einem Shader wiederum können
Texturen zugewiesen werden, also Bitmap-Bilder, die innerhalb eines
Shaders unterschiedliche Funktionen (z.B. als Reflection Map) erfüllen
können.
Die Welt des 3D-Darstellers (World) ist die oberste
Hierarchieebene. Es ist die Gruppe, die immer vorhanden ist, und
alle weiteren Objekttypen enthalten kann:
Group (World) = Darsteller
Model
Shader
Motion
Model
...
Group
Model
Light
Camera
Motion
...
Camera
Light
...
Das Sprite also die Visualisierung eines 3D-Darstellers
auf der Bühne ist der Blick durch eine (oder mehrere)
Kameras des Darstellers. Die Standard-Einstellung für sprite(s).camera
ist dabei stets die erste Kamera des Darstellers. Näheres finden
Sie unten im Abschnitt Kameras nutzen.
|


 |
|
|
Das Grundgerüst für einfache 3D-Behaviors
Änderungen, die wir mit Lingo an Shockwave3D-Darstellern vornehmen,
werden nicht in der Director-Datei gespeichert. Auch wenn es einige
Workarounds für diesen Sachverhalt gibt, so hat das doch zur
Folge, dass wir Shockwave3D-Darsteller, die wir mit Lingo erstellen
und/oder manipulieren, im Normalfall jedes Mal neu erzeugen müssen.
Das folgende Skript-Gerüst tut dies im beginSprite-Handler.
Das Skript nutzt als modelResources die sogenannten Primitives (Fläche,
Kugel, Quader, Kegel). Wie wir unten zeigen, läßt es
sich auch direkt mit Text- und Vectorshapes als zusätzlichen
Grundformen nutzen.
Das Skript ist in folgende Abschnitte gegliedert:
1. Darsteller vorbereiten
2. ModelResource erzeugen und einstellen
3. Model erzeugen und einstellen
4. Shader erzeugen und einstellen
5. Textur(en) erzeugen und einstellen
6. Licht(er) erzeugen und einstellen
7. Kamera einstellen
Für jedes Objekt, das wir in einem Darsteller erzeugen, wiederholen
sich die Schritte 2 bis 5.
|


 |
|
|
Kugel erzeugen Das Basisskript
In Listing 1 finden Sie die Schritte am einfachsten Beispiel
ein Primitive ohne Textur wird in die Mitte der Welt
platziert exemplarisch aufbereitet. Der dazugehörige
Beispielfilm ist der Film PRIMITIVES1.DIR.
Besondere Beachtung verdient die Funktion resetworld()
in Schritt 1 sowie die Überprüfungen if
voidP(
) then
bei jedem der folgenden Schritte.
resetworld() setzt den Zustand des 3D-Darstellers
auf den im Darsteller gespeicherten Zustand zurück. In unserem
Fall wir erzeugen einen leeren Darsteller in Director
ist dies also der leere Zustand.
Die voidP()-Überprüfungen
stellen sicher, dass eine gleichnamige Ressource in der entsprechenden
Palette noch nicht existiert. Dies wird dann interessant, wenn Sie
mehrere Behaviors dieses Typs auf ein 3D-Sprite platzieren, oder
wenn eine importierte w3d-Datei Grundlage Ihrer Versuche ist. Das
Skript erzeugt demnach nur Modelresources, Models, Shaders, Textures
und Lights, wenn gleichnamige Elemente noch nicht existieren.
Listing 1
on beginsprite me
msp = sprite(me.spritenum)
mmb = msp.member
-- --------------------------
-- 1. Darsteller vorbereiten
-- --------------------------
mmb.resetworld()
-- World-Properties einstellen
mmb.bgcolor = rgb(0,0,0)
mmb.ambientcolor = rgb(128,128,128)
mmb.directionalpreset = #none
mmb.directionalcolor = rgb(255,0,0)
-- --------------------------
-- 2. Modelresource anlegen
-- --------------------------
if voidP(mmb.modelresource("resKugel")) then
Res = mmb.newModelResource("resKugel", #sphere)
end if
-- --------------------------
-- 3. Model anlegen
-- --------------------------
if voidP(mmb.model("Model1")) then
mymod = mmb.newModel("Model1", Res)
end if
-- --------------------------
-- 4. Shader anlegen und zuweisen
-- --------------------------
if voidP(mmb.shader("shad")) then
myShad = mmb.newShader("shad",#standard)
myShad.diffuse = rgb(255,0,0)
myShad.renderStyle = #fill
myshad.texturelist = VOID
end if
mmb.model("Model1").shaderList = mmb.shader("shad")
-- --------------------------
-- 5. Textur anlegen und zuweisen
-- --------------------------
-- --------------------------
-- 6. Light anlegen
-- --------------------------
if voidp(mmb.light("li1")) then
mylight = mmb.newlight("li1", #point)
myLight.transform.position = \
vector( -66.0000, -66.0000, 44.0000 )
mylight.color = rgb( 255, 255, 255 )
mylight.specular = 1
end if
-- --------------------------
-- 7. Kamera einstellen
-- --------------------------
mmb.camera[1].transform.position = \
vector( 0.0000, 0.0000, 100.0000 )
end
|


 |
|
|
Schritt
1 setzt den Darsteller auf seinen Ausgangszustand zurück und
setzt die Welteigenschaften, die auch im Property-Inspektor eingestellt
werden können: Hintergrundfarbe und Ambientcolor sowie ein
Spotlight und dessen Farbe (hier mit #none ausgeschaltet).
Schritt 2 legt eine Modelresource mit dem Namen "resKugel",
dem Typ #sphere und den Standard-Einstellungen an. Wie Sie die Modelresource
weiter anpassen, lesen Sie im Abschnitt Modelresources und
ihre Eigenschaften.
Schritt 3 generiert aus der Modelresource ein Modell mit dem Namen
Model1. Da keine Position angegeben wird, wird das Modell
im Koordinatenursprung platziert (vector(0,0,0)).
Schritt 4 legt einen neuen Shader shad mit folgenden
Besonderheiten an: er ist gefüllt, hat keine Textur (auch nicht
das Standard-Schachbrettmuster), sondern lediglich eine Farbe.
Schritt 5 ist daher leergelassen: wir generieren in diesem Beispiel
noch keine Textur.
In Schritt 6 legen wir ein eigenes (weißes und punktförmiges)
Licht an, das an einen durch einen Vektor ausgedrückten Platz
vector( -66.0000, -66.0000, 44.0000 ) verschoben wird, so dass es
einen Lichtfleck auf der Kugel erzeugt. Einen ähnlichen Effekt
erreichen Sie, wenn Sie in Schritt 1 die Eigenschaft directionalpreset
beispielsweise auf #bottomleft setzen.
Schritt 7 schließlich modifiziert Kamera 1, also die dem
Darsteller zugehörige camera("DefaultView"). Die
Standard-Einstellung dieser Kamera ist vector(0, 0, 250); mit vector
(0, 0, 100) verringern wir den Abstand der Kamera vom Weltmittelpunkt
(und damit von der Kugel, die dort platziert wurde).
Das ganze Skript wird auf beginSprite ausgeführt; Sie müssen
also den Film starten, um etwas zu sehen.
|


 |
|
|
Variationen
Verändern Sie den renderStyle des Shaders aus Listing 1,
um die Kugel in Wireframe- oder Punkt-Darstellung anzuzeigen:
myShad.renderStyle = #wire
oder
myShad.renderStyle = #point
In beiden Fällen nutzt die Anzeige die durch die Eigenschaft
diffuse vorgegebene Farbigkeit.
Mit
Veränderungen in Schritt 4 und 5 können Sie eine texturierte
Kugel erzeugen:
Listing 1b
-- --------------------------
-- 4. Shader anlegen und zuweisen
-- --------------------------
if voidP(mmb.shader("shad")) then
myShad = mmb.newShader("shad",#standard)
myShad.renderStyle = #fill
myshad.texturemode = #none
myshad.textureTransform.scale(1/8.0, 1/8.0, 1.0)
end if
mmb.model("Model1").shader = mmb.shader("shad")
-- --------------------------
-- 5. Textur anlegen und zuweisen
-- --------------------------
if voidP(mmb.texture("textu")) then
mytextu = mmb.newTexture("textu", \
#fromCastMember, member("text1"))
end if
mmb.shader("shad").texture = mytextu
Der Shader, der hier generiert wird, ist so skaliert, dass die
Textur, die ihm zugewiesen wird, in x- und y-Richtung genau 8 Mal
wiederholt wird (Einstellung textureTransform.scale()). Als Textur
dient ein Darsteller. Das Ergebnis dieses Skriptes sehen Sie in
der Abbildung. Der entsprechende Beispielfilm ist PRIMITIVES2.DIR.
|


 |
|
|
Soll die Textur nicht gekachelt sein, sondern genau einmal um
den Körper herumprojiziert werden, so entfernen Sie die
Zeile
myshad.textureTransform.scale(1/8.0, 1/8.0, 1.0)

Mit dem 3DPI (Abbidung oben) können
Sie bei laufendem Film zudem ausprobieren, ob andere Vorgaben für
den Projektionsmodus der Textur in der Zeile
myshad.texturemode = #none
zu besseren Darstellungsergebnissen führen würden. Die
folgende Abbildung zeigt die Ergebnisse beim Durchprobieren aller
textureMode-Einstellungen:
Beachten Sie, dass hier durchgängig die vereinfachte
Notation für Shader- und Textureigenschaften verwendet
wurde, da nur eine Textur bzw. ein Texturlayer angelegt wurden.
Ein Shader kann bis zu 8 Textur-Layer enthalten, die jeweils unterschiedliche
Funktionen haben. Die folgenden Statements:
myshad.textureTransform.scale(1/8.0, 1/8.0, 1.0)
mmb.model("Model1").shader = mmb.shader("shad")
mmb.shader("shad").texture = mytextu
sind gleichbedeutend mit:
myshad.textureTransformList[1].scale(1/8.0, 1/8.0, 1.0)
mmb.model("Model1").shaderList[1] = mmb.shader("shad")
mmb.shader("shad").textureListe[1] = mytextu
Nutzen Sie die Bibliotheks-Behaviors Automatic Model Rotation,
Orbit Camera und Dolly Camera mit entsprechenden
Auslösern, um die Kugel zu drehen bzw. die Kamera in Bezug
auf die Kugel zu bewegen.
|


 |
|