21.5 Richtiges 3D
3D\3D_in_Flash
Für echtes 3D muss eine Unmenge von Details beachtet werden. Außerdem ist eine große Menge Mathematik notwendig – davon leider sogar so viel, dass viele Abspielumgebungen schnell in die Knie gehen. Dabei ist die Darstellungsleistung von zahlreichen Faktoren wie Grafikkarte und Prozessor abhängig. Aufgrund des plattformunabhängigen Konzeptes von Flash werden gerade diese Komponenten aber leider nicht optimal angesprochen: OpenGL oder DirectX kommen zum Beispiel im Flash Player nicht zum Einsatz.
21.5.1 Performance
Tests mit einfachen Linien auf einem durchschnittlichen Testrechner ergaben, dass bei einer Auflösung von 400 x 400 Punkten gerade noch 50 Linien mit einer Bildrate von 25 Bildern pro Sekunde dargestellt werden. D.h. so könnten gerade vier Würfel gleichzeitig als Drahtgittermodell gezeichnet werden, ohne dass die Darstellung zu ruckeln begann. Mit den mathematischen Operationen für 3D wird das alles noch langsamer. Ein aus 16 Linien bestehendes Haus berechnet Flash mit ungefähr 40 Bildern pro Sekunde, aber schon beim dritten Haus brach die Bildrate auf dem Testrechner deutlich unter 20 Bilder pro Sekunde ein. Hier kann zwar durch optimierten Code nachgebessert werden, doch ein echtes 3D-Spiel ist bei dem aktuellen Stand der Rechnerleistung mit Flash kaum zu realisieren. Macromedias alternatives Autorensystem Director bietet hier mit Shockwave3D eine deutlich leistungsfähigere Technologie.
Optimierte Flash Player
Das Problem der Darstellungsgeschwindigkeit haben einige Entwickler erkannt und bieten entsprechende Lösungen an. Der »Experimental Hardware SWF Player« von Globfx http://www.globfx.com/labs/hwf/ und das auf DirectX optimierte »Strobe User Interface SDK« von Secret Level versprechen zum Beispiel eine bessere Leistung.
21.5.2 Drahtgittermodell
Auf eine einfache Perspektive (z.B. Zentralprojektion) beschränkt und unter Außerachtlassung von Dingen wie Beleuchtung, Flächen usw. gelingt aber dennoch eine ansprechende Darstellung als dreidimensionales Drahtgitter (Wireframe).
Hier klicken, um das Bild zu Vergrößern
Abbildung 21.3
Ein Haus als Drahtgittermodell
Zuerst einmal wird eine Datenstruktur zur Verwaltung der Punkte im Raum benötigt, die in diesem Beispiel eine eigene Klasse übernimmt:
haus.fla
function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
Die Darstellung eines Drahtgittermodells basiert auf einfachen Linien, die zwischen zwei Punkten im Raum aufgespannt werden. Somit ist eine Klasse für Linien notwendig:
function Line(startPoint, endPoint) {
this.a = startPoint;
this.b = endPoint;
}
Und die 3D-Objekte wiederum sind eine Klasse, sie bestehen aus einer beliebigen Anzahl an Linien:
function Object3D() {
this.wireframe = new Array();
}
Object3D.prototype.addLine = function(x1, y1, z1, x2, y2, z2) {
var a = new Point(x1, y1, z1);
var b = new Point(x2, y2, z2);
var wire = new Line(a, b);
this.wireframe.push(wire);
};
Ein einfaches Haus definieren nun die folgenden Anweisungen:
myHouse = new Object3D();
// Definiere VorderSeite
myHouse.addLine(50, 50, 10, 50, 100, 10);
myHouse.addLine(50, 100, 10, 100, 100, 10);
myHouse.addLine(100, 100, 10, 100, 50, 10);
myHouse.addLine(100, 50, 10, 50, 50, 10);
// Definiere RückSeite
myHouse.addLine(50, 50, 60, 50, 100, 60);
myHouse.addLine(50, 100, 60, 100, 100, 60);
myHouse.addLine(100, 100, 60, 100, 50, 60);
myHouse.addLine(100, 50, 60, 50, 50, 60);
// Definiere Verbindungslinien
myHouse.addLine(50, 50, 10, 50, 50, 60);
myHouse.addLine(50, 100, 10, 50, 100, 60);
myHouse.addLine(100, 100, 10, 100, 100, 60);
myHouse.addLine(100, 50, 10, 100, 50, 60);
// Definiere Dach
myHouse.addLine(50, 50, 10, 75, 25, 35);
myHouse.addLine(50, 50, 60, 75, 25, 35);
myHouse.addLine(100, 50, 10, 75, 25, 35);
myHouse.addLine(100, 50, 60, 75, 25, 35);
21.5.3 Darstellung – oder von 3D nach 2D
Die Darstellung des Hauses erfordert eine Projektion der dreidimensionalen Koordinaten auf eine zweidimensionale Ebene. Diese Operation übernimmt in erster Linie die Klasse Line, die sich um die anschließende Darstellung auf dem Bildschirm kümmert. Dabei ist die Formel abhängig vom Abstand (Distance) zur Projektionsebene (je nach Abstand kann es zu einem Eintauchen in die Objekte und damit verbundenen Darstellungsfehlern kommen, auf deren Lösung an dieser Stelle verzichtet wird):
haus.fla
Line.prototype.draw = function(mc, distance) {
// distance ist die Distanz zur Projektionsfläche
var x1 = (this.a.x*distance)/(this.a.z+distance);
var y1 = (this.a.y*distance)/(this.a.z+distance);
mc.moveTo(x1, y1);
var x2 = (this.b.x*distance)/(this.b.z+distance);
var y2 = (this.b.y*distance)/(this.b.z+distance);
_root.lineTo(x2, y2);
};
Object3D.prototype.draw = function (mc, distance) {
for (var i in this.wireframe) {
// Zeichne jede einzelne Linie
this.wireframe[i].draw(mc, distance);
}
}
21.5.4 Dreidimensional transformieren
Um einzelne Punkte zu verschieben oder zu drehen, fügen wir den Klassen die entsprechenden Methoden hinzu. Das Verschieben in x-, y- oder z-Richtung basiert auf einer einfachen Addition:
haus2.fla
Point.prototype.move = function(dx, dy, dz) {
this.x += dx;
this.y += dy;
this.z += dz;
};
Line.prototype.move = function(dx, dy, dz) {
this.a.move(dx, dy, dz);
this.b.move(dx, dy, dz);
};
Object3D.prototype.move = function(dx, dy, dz) {
for (var i in this.wireframe) {
this.wireframe[i].move(dx, dy, dz);
}
};
Hier klicken, um das Bild zu Vergrößern
Abbildung 21.4
Im_Raum_gedrehtes_Haus
Die Drehung eines Punktes im Raum erfordert noch ein wenig mehr Rechenarbeit, deren Optimierung die Leistung noch um einiges erhöhen kann. Grundsätzlich werden die einzelnen Koordinaten immer im Bezug zum Ursprung (also zum Schnittpunkt aller drei Achsen) transformiert. Bei der Drehung kommen dafür an dieser Stelle die geometrischen Funktionen Sinus und Cosinus zum Einsatz:
haus3.fla
Point.prototype.rotate = function(x, y, z) {
// Rotation um die x-Achse im Bogenmass
var yn = this.y*Math.cos(x)-this.z*Math.sin(x);
var zn = this.y*Math.sin(x)+this.z*Math.cos(x);
this.y = yn;
this.z = zn;
// Rotation um die y-Achse im Bogenmass
var xn = this.x*Math.cos(y)+this.z*Math.sin(y);
var zn = -this.x*Math.sin(y)+this.z*Math.cos(y);
this.x = xn;
this.z = zn;
// Rotation um die z-Achse im Bogenmass
var xn = this.x*Math.cos(z)-this.y*Math.sin(z);
var yn = this.y*Math.cos(z)+this.x*Math.sin(z);
this.x = xn;
this.y = yn;
};
21.5.5 Weitere Optimierung
Hier klicken, um das Bild zu Vergrößern
Abbildung 21.5
Kruesch.de zeigt eindrucksvoll, wie gut 3D in Flash aussehen kann.
Die Ideen aus dem 2 ˝ D-Ansatz und der dreidimensionalen Herangehensweise lassen sich optimal kombinieren. Die Darstellung des Raums und die Positionierung der Objekte im Raum werden so verbessert. Da die Objekte weiterhin flaechig sind, bleibt die Darstellungsleistung in einem ertraeglichen Rahmen – alternativ koennten die Objekte ueber wenige Ansichten verfuegen wie zum Beispiel hinten, vorn, links und rechts. Ein gutes Beispiel dafuer ist unter http://www.mx3d.com/ zu finden. Zur Optimierung der Leistung hat der Entwickler dieser Website ausserdem auf Flasm zurueckgegriffen (http://flasm.sourceforge.net). Dabei handelt es sich um ein Werkzeug, das den Bytecode von SWF-Dateien direkt editiert und optimiert- quasi so eine Art Maschinensprache fuer Flash.
|