VRML - Ein Tutorial

VRML-Tutorial von Daniel Schwamm (14.02.1998)

Inhalt

1. More VRML, please!

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.

2. VRML-Basteleien

2.1. Erstes Beispiel: "Hello, world"

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)

2.2. Zweites Beispiel: Virtuelle Raumgestaltung

2.2.1. Teil I: Ebene im Raum

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)

2.2.2. Teil II: Hintergrund und Farbgebung

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)

2.2.3. Teil III: Säulenbildung

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)

2.2.4. Teil IV: Koordinatengenaue Objektplatzierung

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)

2.2.5. Teil V: Schwebende Sphären

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)

2.2.6. Teil VI: Relative Platzierung

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)

2.2.7. Teil VII: Separierung von Objekten

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)

2.2.8. Teil VIII: Bewegung im Modell

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)

2.2.9. Teil IX: Texturierung

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:

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)

3. Fazit

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!