VRML - Ein Tutorial
VRML-Tutorial von Daniel Schwamm (14.02.1998)
Inhalt
Virtual Reality Modeling Language (VRML) ist simpel. Daher finde ich
es erstaunlich, dass man VRML-Welten im Web nur relativ selten findet. Zumal
in Netscape ab Version 3.x ein Plug-in für VRML 1.0 bereits integriert ist.
Um diesen Missstand zu beseitigen, folgt nun ein kleiner VRML-Kurs.
Man nehme einen x-beliebigen ASCII-Editor, z.B. Notepad in Windows,
und tippe Folgendes ein:
00001
00002
#VRML V1.0 ascii
AsciiText{string 'Hello, world!'}
Man speichere dies als "vrmlkurs1.wrl" und betrachte sich das Ergebnis
z.B. mit Netscape.
(=> vrmlkurs1.wrl)
Wie wäre es mit einer Ebene im Raum? No problem:
00001
00002
00003
00004
00005
00006
#VRML V1.0 ascii
Cube{
width 1000
height 10
depth 1000
}
(=> vrmlkurs2.wrl)
Nun ja, der Hintergrund wäre in blau schöner. Und die Ebene sollte grün sein.
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#VRML V1.0 ascii
DEF BackgroundColor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .6 .9 .6 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
(=> vrmlkurs3.wrl)
So eine Ebene ohne alles ist öde. Verpassen wir ihr doch eine dunkelgraue, mh ... Säule.
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF saeule Cylinder {
radius 100
height 300
}
(=> vrmlkurs4.wrl)
Sitzt blöd, die Säule. Besser wäre es, wenn sie hinten links auf
der Ebene hocken würde. Dazu muss man allerdings ein wenig rechnen.
Um ein VRML-Objekt umzuplatzieren, muss sein 3D-Mittelpunkt umtransformiert
werden. Let us take a look:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
Wieso funktioniert das? Vor der Definition der Säule liegt der
"Objektplatzierungsausgangspunkt" in (x/y/z)=(0/0/0), d.h. genau
in der inneren Mitte der Ebene. Um die Säule auf die Ebene
zu setzten, muss der "Objektplatzierungsausgangspunkt" daher um
155 Punkte erhöht werden, damit der Säulenmittelpunkt genau so
weit über dem 0/0/0-Mittelpunkt schwebt, dass der Säulenfuss auf
der Ebene aufsitzt, deren oberer Rand sich wiederum in 5 Punkten Höhe vom
0/0/0-Mittelpunkt befindet.
Brrr! Mathematikkram lässt sich nur schwer verbal formulieren, weswegen
schon die alten Griechen hierfür eine Formelsprache entwickelt haben.
In diesem Falle gilt:
00001
00002
Hoehe Saeulemittelpunkt = Ursprungshoehe + (Hoehe Ebene / 2) + (Hoehe Saeule / 2)
155 = 0 + ( 10 / 2) + ( 300 / 2)
(=> vrmlkurs5.wrl)
So eine Ebene und so eine Säule machen noch mehr her, wenn
sich rechts von der Säule eine schwarze Kugel befindet, oder? Also knallen
wir eine hin:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
DEF mat2 Material{
diffuseColor 0 0 0 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation -200 155 -400 # 200 nach links, 155 hoch, 400 nach hinten
}
Sphere {
radius 50
}
(=> vrmlkurs6.wrl)
Hoppla! Wat is nu passiert? Die dreckige Kugel hat es beinahe ins
NIL verschlagen. Grund: Die Translation-Koordinaten sind korrekt zum Ursprung angegeben,
wir haben aber zuvor den "Objektplatzierungsausgangspunkt" durch Platzierung der Säule
umgebogen. Wir müssen daher die Koordinaten relativ zu diesen neuem "Ursprung"
setzen. Das ergibt:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
DEF mat2 Material{
diffuseColor 0 0 0 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation 200 0 0 # 100 nach rechts, Hoehe bleibt, Tiefe bleibt
}
Sphere {
radius 50
}
(=> vrmlkurs7.wrl)
Okay, die Kugel wurde gebändigt. Trotzdem finde ich, dass das Platzieren
von Objekten abhängig vom absoluten Ursprung i.d.R. leichter ist,
als vom relativen, sich ständig ändernden Ursprung. Glücklicherweise
gestattet es VRML, Objekte separiert anzulegen, d.h. unabhängig von
zuvor gemachten Arbeitsschritten. "Separierte Objekte" lassen sich auch
leicht klonen, was wir im nächsten Beispiel anhand der Kugel sehen werden:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF ebene Separator{
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
Cube{
width 1000
height 10
depth 1000
}
}
DEF saeule Separator{
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
}
DEF kugeln Separator{
Translation {
translation -200 155 -400 # 200 nach links, 155 hoch, 400 nach hinten
}
DEF kugel Separator{
DEF mat2 Material{
diffuseColor 0 0 0 # Rot-Gruen-Blau-Intensitaet 0-1
}
Sphere{
radius 50
}
}
Translation{
translation -400 0 0 # 400 nach links, Hoehe bleibt, Tiefe bleibt
}
USE kugel
Translation{
translation 200 0 200 # 200 nach rechts, Hoehe bleibt, 200 vor
}
USE kugel
Translation{
translation 0 0 -400 # x bleibt, Hoehe bleibt, 400 zurueck
}
USE kugel
}
(=> vrmlkurs8.wrl)
4 Kugeln um die Säule herum? Nett, aber statisch. Ein bisschen Dynamik
kann nichts schaden. Wie schön, dass VRML Spin Groups kennt. Positiv
ist auch, dass Material-Definitionen im Voraus gemacht werden können.
And here is the result:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat2 Material{
diffuseColor 0 0 0 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF ebene Separator{
USE mat0
Cube{
width 1000
height 10
depth 1000
}
}
DEF saeule Separator{
USE mat1
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
}
DEF spin SpinGroup {
rotation 0 1 0 .1 # rotiere um höhnenachse mit tempo .1
DEF kugeln Separator{
Translation {
translation -200 155 -400 # 200 nach links, 155 hoch, 400 nach hinten
}
DEF kugel Separator{
USE mat2
Sphere{
radius 50
}
}
Translation{
translation -400 0 0 # 400 nach links, Hoehe bleibt, Tiefe bleibt
}
USE kugel
Translation{
translation 200 0 200 # 200 nach rechts, Hoehe bleibt, 200 vor
}
USE kugel
Translation{
translation 0 0 -400 # x bleibt, Hoehe bleibt, 400 zurueck
}
USE kugel
}
}
(=> vrmlkurs9.wrl)
So, dass sieht doch schon ganz ansprechend aus. Doch das Sahnehäubchen
kommt erst jetzt: Texturen. Damit lassen sich beliebige Bilder
auf VRML-Objekte kleben. Im Folgenden verwende ich diese Pics:
Ein Bild von mir, ganz klar. Bin in der World übrigens interaktiv -
einen Klick auf mich und ihr landet auf meiner Homepage!
|
|
Ein Bild der süssen Winona |
|
Wolken, weiss und rein |
|
Ein garstiger Totenkopf |
|
Und mit diesen Mixturen versehen, erhalten wir:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
#VRML V1.0 ascii
DEF backgroundcolor Info{
string '0 0 .6' # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF backgroundimage Info{
string 'clouds.gif'
}
DEF mat0 Material{
diffuseColor .7 1 .7 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat1 Material{
diffuseColor .3 .3 .3 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF mat2 Material{
diffuseColor 0 0 0 # Rot-Gruen-Blau-Intensitaet 0-1
}
DEF ebene Separator{
USE mat0
Texture2Transform {
scaleFactor 1 1
}
Texture2{
filename 'winona.jpg'
}
Cube{
width 1000
height 10
depth 1000
}
}
DEF saeule Separator{
WWWAnchor{
name 'http://www.daniel-schwamm.de'
description 'Daniels Homepage'
USE mat1
Texture2Transform {
scaleFactor 1 1
}
Texture2{
filename 'dan1.jpg'
}
Translation {
translation -400 155 -400 # 400 nach links, 155 hoch, 400 nach hinten
}
DEF saeule Cylinder {
radius 100
height 300
}
}
}
DEF spin SpinGroup {
rotation 0 1 0 .1 # rotiere um Hoehenachse mit Tempo .1
DEF kugeln Separator{
Texture2Transform {
scaleFactor 3 1
}
Texture2{
filename 'skull.gif'
}
Translation {
translation -200 155 -400 # 200 nach links, 155 hoch, 400 nach hinten
}
DEF kugel Separator{
USE mat2
Sphere{
radius 50
}
}
Translation{
translation -400 0 0 # 400 nach links, Hoehe bleibt, Tiefe bleibt
}
USE kugel
Translation{
translation 200 0 200 # 200 nach rechts, Hoehe bleibt, 200 vor
}
USE kugel
Translation{
translation 0 0 -400 # x bleibt, Hoehe bleibt, 400 zurueck
}
USE kugel
}
}
(=> vrmlkurs10.wrl)
Virtual Reality Modeling Language ist simpel. Habe mir ein
Tool zusammenprogrammiert, was die Geschichte noch einfacher macht:
VRML-Worlds per Drag & Drop. In Zukunft bastle ich mir bestimmt noch
ein paar Welten zusammen. Zu finden sind diese dann hier:
(=> vrmldir.html)
Das Tool liegt auf der Buchhorn & Melzer-Download-Seite. Wen's interessiert -
hier klicken!