Dokumentation

Basisobjekte definieren

<-Lichtquellen und die Kamera
-> Oberflächeneigenschaften definieren
Allgemeines
Kugel
Polygon
Scheibe
Zylinder
Würfel
Röhre
Kegel
Rotationskörper
Implizit def. Oberfläche
Superquadrat. Ellipsoid
Torus
Surface of Revolution
Blob
Metaball
Höhenkarte
Fraktale Landschaft
Höhenkarte aus Bitmap
Mesh (viele Dreiecke)
Staub/Nebel

 

Allgemeines

Dies hier ist nun die vollständige Liste aller derzeit verfügbaren Basisobjekte.
Ein Objekt wird allgemein wie folgt definiert:

new Objekt-Typ {
  Zuweisung1;
  ..
  ZuweisungN;
}
Die Zuweisungen sind dabei Ausdrücke von der Form
  name=Wert;
Dabei wird dem Attribut "name" der angegebene Wert zugewiesen. Viele der Objekte benötigen zusätzliche Parameter, die so in dem Objektblock zugewiesen werden können. Einige Objekte stellen weiterhin Funktionen zur Verfügung. Diese können aufgerufen werden, um weitere Eigenschaften festzulegen oder z.B. einem Polygon einen Punkt hinzuzufügen. Ein Funktionsaufruf sieht allgemein so aus:
Funktionsname(Arg1, Arg2, ... ArgN);
Dabei sind Arg1.. ArgN Parameter für die Funktion. Sie müssen jeweils einen vorgegebenen Typ haben (Zeichenkette, Vektor, Zahl). Es gibt auch Funktionen, die keine Argumente benötigen. Wie in der Programmiersprache C müssen die Klammern () trotzdem stehen.
Alle Objekte haben die folgenden Attribute gemeinsam:
  color=[r, g, b];
  pos=[x, y, z];
  scale=[xscale, yscale, zscale];
  rotate=[ax, ay, az];
Dabei gibt color (r, g, b) die Objektfarbe an. Mit pos kann das Objekt verschoben werden; in der Regel gibt pos die Koordinaten des Mittelpunktes an. Mit scale kann das Objekt entlang der Koordinatenachsen (im Koordinatensystem des ungedrehten Objektes) skaliert werden, wobei der Mittelpunkt fest bleibt. Mit rotate schließlich kann das Objekt gedreht werden, und zwar nacheinander um die z-, die y- und die x-Achse (die umgekehrte Reihenfolge beachten!). Die Winkel müssen dabei mit dem Grad-Zeichen ° stehen, oder im Bogenmaß angegeben werden.
Im Folgenden werde ich zu den Objekten nur die objektspezifischen Attribute angeben und die gemeinsamen weglassen.

[
nach oben]

Quelltext

Kugel

Definition:

new sphere{
}
Keine weiteren Parameter

[
nach oben]

Quelltext

Polygon

Definition:

new polygon{
  addpoint([x1,y1,z1]);
  ...
  addpoint([xn,yn,zn]);
}
Mit addpoint können die einzelnen Eckpunkte des Polygons angegeben werden. Es müssen mindestens drei Punkte angegeben werden. Alle Punkte müssen auf einer Ebene liegen.
Der Typ polygon eignet sich nur für wenige einzelne Polygone. Sollen kompliziertere Objekte aus Polygonen erstellt werden, sollte der Typ
Mesh benutzt werden, da dieser um ein Vielfaches schneller ist.

[nach oben]

Quelltext

Scheibe

Definition:

new disk{
  radi=r;
}
Erzeugt eine runde Scheibe in der x-z-Ebene, deren Außenradius 1 ist. Der Radius des Loches wird durch radi angegeben.

[
nach oben]

Quelltext

Zylinder

Definition:

new cylinder{
}
Erzeugt einen Zylinder entlang der y-Achse mit dem Radius 1 und der Länge 2 (der Zylinder erstreckt sich von y=-1 bis y=1).
Achtung: Der Zylinder beinhaltet nur den Außenmantel. Dies kann zu Problemen führen, wenn man in den Zylinder hineinsieht, oder bei Kombinationsobjekten. In den meisten Fällen ist man besser beraten, den Objekttyp
Röhre (Tube) zu verwenden.

[nach oben]

Quelltext

Würfel

Definition:

new cube{
}
Erzeugt einen Achsenparallelen Einheitswürfel (alle Kandenlängen=1). Beachte: z.B. die linke Grenzfläche liegt damit bei x=-0.5 und die rechte bei x=0.5!

[
nach oben]

Quelltext

Röhre

Definition:

new tube{
  radi=r;
}
Erzeugt eine Röhre mit Endkappen und Loch in der Mitte. radi gibt dabei den Innenradius an. Bei radi=0 wird ein Vollzylinder ohne Loch erzeugt.
Wie der Zylinder ist auch die Röhre entlang der y-Achse gelegt und hat den Radius 1 und die Länge 2.

[
nach oben]

Quelltext

Kegel

Definition:

new cone{
  x1=x;
  y1=y;
  x2=x;
  y2=y;
}
Erzeugt einen Kegelstumpf. Die Koordinaten (x1/y1), (y2/y2) geben die Begrenzungslinie an, die man erhält, wenn man den Kegel mit der xy-Ebene schneidet.
Achtung: Der Kegelstumpf hat keine Endkappen! Daher kann es zu Problemen kommen, wenn man hineinsieht oder wenn man ihn in Kombinationsobjekten verwendet.

[
nach oben]

Quelltext

Rotationskörper

Definition:

new rotobj{
  addpoint(x1,y1);
  ...
  addpoint(xn,yn);
}
Erzeugt einen Rotationskörper. Die Eckpunkte der Begrenzungslinie können mit der Funktion addpoint der Reihe nach (Reihenfolge beachten!) hinzugefügt werden. Der Rotationskörper wird dann aus Objekten vom Typ Kegelstumpf(cone) zusammengesetzt. Es müssen natürlich mindestens zwei Punkte angegeben werden.
Auch hier: Vorsicht wegen der fehlenden Endkappen. Außerdem Vorsicht, wenn die y-Werte nicht monoton sind: Dieser Fall ist noch nicht 100% korrekt implementiert.

[
nach oben]

Quelltext

Implizit definierte Oberfläche

Definition:

new implicit{
  addcoeff(c1, xdeg1, ydeg1, zdeg1);
  ...
  addcoeff(cn, xdegn, ydegn, zdegn);
}
Erzeugt eine Oberfläche, die aus allen Punkten [x,y,z] mit
c1*(x^xdeg1)*(y^ydeg1)*(z^zdeg1)
+ c2*(x^xdeg2)*(y^ydeg2)*(z^zdeg2)
+ ... + cn*(x^xdegn)*(y^ydegn)*(z^zdegn) = 0
besteht.

[
nach oben]

Quelltext

Superquadratischer Ellipsoid

Definition:

new sqellipsoid{
  degree=n;
}
Erzeugt eine implizit definierte Oberfläche mit
x^n+y^n+z^n=1
n=2 ergibt eine Kugel, je größer n wird, desto mehr nähert sich die Form einem Würfel (mit der Kangenlänge 2!). n muss eine gerade Zahl sein!

[
nach oben]

Quelltext

Torus

Definition:

new torus{
  rad1=r1;
  rad2=r2;
}
Erzeugt einen Torus auf der x-z-Ebene. Mit rad1 und rad2 werden Ringradius und Ringdicke (Radius des Kreisquerschnitts) angegeben.

[
nach oben]

Quelltext

Surface of Revolution

Definition:

new sor{
  addpoint(×1,y1);
  ...
  addpoint(xn,yn);
}
Erzeugt einen Rotationskörper, dessen Begrenzungslinie sich aus eindimensionalen Bezier-Splines zusammensetzt. Die y-Koordinaten müssen streng monoton sein (also aufsteigend oder absteigend). Die Bezier-Splines werden so gelegt, dass die Begrenzungslinie durch alle angegebenen Punkte bis auf den ersten und den letzten verläuft, und dass keine Kanten entstehen. Der erste Punkt und der letzte Punkt sind nur Kontrollpunkte. Mit ihnen kann die Richtung angegeben werden, mit denen das Bezier-Spline in den zweiten bzw. vorletzten Punkt mündet. Es müssen also mindestens vier Punkte angegeben werden.

[
nach oben]

Quelltext

Blob

Definition:

new blob{
  addspherical([x,y,z], i);
  ...
  addcylindrical([x1,y1,z1],[x2,y2,z2], i);
  ...
  addplanar([px, py, pz], [nx, ny, nz], i);
  ...
  border=b;
}
Erzeugt ein Blob-Objekt. Näheres siehe
www.raytracer.de. Mit addspherical wird eine radialsymmetrische Quelle am Ort [x,y,z] hinzugefügt. Mit addcylindrical wird eine Zylindersymmetrische Quelle hinzugefügt, wobei die Achse durch [x1, y1, z1] und [x2, y2, z2] verläuft. Mit planar wird eine Ebene Quelle hinzugefügt, wobei [px, py, pz] ein Punkt auf der Ebene und [nx, ny, nz] der Normalenvektor ist. i gibt jeweils die Intensität der Quelle an. Mit border kann der Grenzwert angegeben werden, durch den die Oberfläche verläuft.
Von jedem Typ können theoretisch beliebig viele Quellen angegeben werden, doch steigt der Rechenaufwand mit der Zahl der Quellen stark an. Außerdem kann ein interner Überlauf passieren, da die auftretenden Polynome zu viele Koeffizienten haben.

[nach oben]

Quelltext

Metaball

Definition:

new metaball{
  addspherical([x, y, z], i, r);
  ...
  border=b;
}
Erzeugt ein Metaball-Objekt. Näheres siehe
www.raytracer.de. Mit addspherical wird eine Kugelförmige Quelle am Ort [x,y,z] mit dem Radius r und der Intensität i hinzugefügt. Anders als beim Blob-Objekt können ruhig beliebig viele Quellen angegeben werden. border gibt wieder den Grenzwert an, durch den die Oberfläche verläuft.

[nach oben]

Quelltext

Höhenkarte

Definition:

new heightfield{
  setsize(xsize, ysize);

  setheight(x1,y1, h1);
  setheight(x2,y2, h2);
  setheight(x3,y3, h3);
  ...
}
Erzeugt eine Höhenkarte. Zunächst muss mit setsize die Anzahl der Gitterpunkte in x- und y-Richtung angegeben werden. Dann müssen alle Höhenwerte mit setheight gesetzt werden. Dabei läuft x von 0 bis xsize-1 und y von 0 bis ysize-1. Die Höhenwerte müssen zwischen -0.5 und +0.5 liegen.
Für das Belegen der Karte mit Höhenwerten sollte man tunlichst for-Schleifen verwenden. Aber Vorsicht: Da es sich um einen einfachen Interpreter handelt, kann das recht lange dauern.
Die Höhenkarte ist so skaliert, dass sie genau in einen Einheitswürfel passt.

[
nach oben]

Quelltext

Fraktale Landschaft

Definition:

new landscape{
  size=s;
  delta=d;
  fracdim=f;
  srand=i;
  h1=height1;
  h2=height2;
  h3=height3;
  h4=height4;
}
Erzeugt eine fraktale Landschaft. Diese ist dabei so skaliert, dass sie genau in einen Einheitswürfel passt.
size gibt die Anzahl der Teilungsschritte an. Erhöht man s um 1, vervierfacht sich die Anzahl der Polygone! Realistische Werte sind etwa size=8 oder size=9 (Voreinstellung), je nach Auflösung. delta gibt einen Verschiebungswert an. Je höher Delta, desto höher werden die Berge. Die Voreinstellung ist delta=4000. fracdim ist die Fraktale Dimension der Landschaft; sie muss zwischen 2 und 3 liegen. Je höher fracdim, desto zerklüfteter wird die Landschaft. Voreingestellt ist fracdim=2.3. srand gibt schließlich einen Startwert für den Zufallsgenerator an. So ist gewährleistet, dass man immer dieselbe Landschaft erhält. Durch Variation von srand erhält man zufällig immer neue Landschaften. h1 bis h4 geben nun noch die Höhenwerte an den Eckpunkten der Landschaft an, sie müssen zwischen -0.5 und +0.5 liegen.

[
nach oben]

Quelltext

Höhenkarte aus Bitmap

Definition:

new heightmap "dateiname.bmp"{
  xpoints=nx;
  ypoints=ny;
}
Erzeugt eine Höhenkarte, wobei die Höhenwerte aus dem Bitmap "dateiname.bmp" eingelesen werden. xpoints und ypoints geben die Anzahl der Gitternetzlinien an. Sinnvoll ist es, hier die Anzahl der Bildpunkte in dem Bitmap anzugeben.
Die Bitmap-Datei muss eine Windows-Truecolor-BMP-Datei sein. Als Höhenwerte werden die Summen aus jeweils Rot- Grün- und Blauanteil verwendet.
Die Skalierung ist wieder so, dass das Objekt genau in einen Einheitswürfel hineinpasst.

[
nach oben]

Quelltext

Mesh (viele Dreiecke)

Definition:

new mesh{
  addtriangle([x1, y1, z1], [x2, y2, z2], [x3, y3, z3]);
  addtriangle([x1, y1, z1], [x2, y2, z2], [x3, y3, z3]);
  ...
}
Mesh ist ein Objekt, dass aus vielen Dreiecken besteht. Es ist so optimiert, dass es auch mit vielen Dreiecken noch einigermaßen schnell funktioniert. Allerdings ist noch nicht alles komplett implementiert, sodass evtl. Fehler auftreten können.
Mit addtriangle können die Dreicke hinzugefügt werden, wobei die Koordinaten der drei Eckpunkte angegeben werden müssen. Diese müssen im Uhrzeigersinn sein!
Die Dreiecke werden so aneinandergefügt, dass weiche Übergänge entstehen. Möglicherweise ist dies jedoch nicht erwünscht, nämlich wenn Kanten auftreten sollen. Dazu gibt es die Funktion newsurface(). Übergänge zwischen Flächen, zwischen deren Definition dieser Befehl steht, bleiben dann harte Kanten.
new mesh{
  addtriangle([x1, y1, z1], [x2, y2, z2], [x3, y3, z3]);
  ...
  newsurface();
  addtriangle([x1, y1, z1], [x2, y2, z2], [x3, y3, z3]);
  ...
  newwurface();
  ...
}

[
nach oben]

Quelltext

Staub/Nebel

Definition:

new dust{
  density=d;
  reflection=r;
}
Mit dem dust-Objekt lassen sich realistische Nebeleffekte erzeugen. Dabei trifft der Lichtstrahl in regelmäßigem Abstand auf einen Staubpartikel, der dann wie ein transparentes Objekt behandelt wird. Mit density wird die Anzahl der Staubpartikel pro Längenheinheit angegeben. Je höher die Zahl, desto besser wird das Ergebnis, allerdings steigt damit auch die Rechenzeit stark an. Mit reflection kann angegeben werden, welcher Lichtanteil von den einzelnen Staubobjekten reflektiert wird. Im Beispiel links ist reflection=0.6.
Meistens ist es sinnvoll, den Staub auf einen ausgewählten Bereich zu beschränken, in dem sich auch die anderen Objekte befinden. Am besten eigenet sich dazu das Differenzobjekt (siehe nächster Abschnitt):
new subtraction{
  new Begrenzungs-Objekt{
    trans=1;
    fraction=0;
    flat=0;
    phong=0;
    ..
  }

  new dust{
    density=d;
    reflection=r;
  }
}
Mit dieser Definition ist der Nebel nur im Inneren des Begrenzunge-Objektes. Dieses ist 100% transparent und reflektiert selbst kein Licht, daher fällt es nicht auf.
Achtung: Wenn ein dust-Objekt verwendet wird, muss die maximale Rekursionstiefe des Raytracers sehr hoch gesetzt werden! In dem Beispiel links hat der Nebel eine Dichte von 10 Partikel/Längeneinheit, und das Begrenzungsobjekt ist 5 Längeneinheiten tief. Daher wird eine Rekursionstiefe von mindestens 10*5=50 benötigt!

[
nach oben]

Martin Melcher