Weiter gehts mit (wie man in Nürnberg sagen würde) “Gescheidn Schäiding”. Mehr Nürnbergerisch werde ich euch auch garnicht antun. In diesem (vorletzten) Grundlagen Tutorial wird kein Cube mehr genutzt sondern ein Plane, welches im Grunde eine zweidimensionale Fläche (Planes haben kein Maß auf der Z Achse) im dreidimensionalem Raum ist. Statt Gauroudshading kommt nun Phong zum Einsatz und auch die langweilige Dauerrotation ist pasè.
Der angepasste Code aus Teil III:
package{
import flash.display.Bitmap;
import flash.display.MovieClip;
import flash.events.Event;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.shaders.ShadedMaterial;
import org.papervision3d.materials.shaders.PhongShader;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.BasicView;
import org.papervision3d.lights.PointLight3D;
public class Leda extends BasicView
{
private var materialsList :MaterialsList;
private var bitmapMaterial: BitmapMaterial;
private var shadedMaterial: ShadedMaterial;
private var shader :PhongShader;
private var primitive:Plane;
private var lightPoint :PointLight3D
public function Leda()
{
super(500, 500, true);
lightPoint = new PointLight3D();
shader = new PhongShader(lightPoint, 0xffffff, 0x000000, 15);
// leda ist eine bitmap in der bibliothek
var leda :BitmapData = new leda_data(500, 500)
bitmapMaterial = new BitmapMaterial(leda, true);
shadedMaterial = new ShadedMaterial(bitmapMaterial, shader);
// die z position für pixelpräzision
primitive = new Plane(shadedMaterial, 250, 250)
primitive.z = (camera.zoom * camera.focus) - Math.abs(camera.z);
scene.addChild(primitive);
startRendering();
}
override protected function onRenderTick(e:Event = null):void {
primitive.rotationY = viewport.containerSprite.mouseX / 4;
primitive.rotationX = viewport.containerSprite.mouseY / 4;
super.onRenderTick();
}
}
}
Es wird ein PointLight Objekt erstellt und dieses dem Constructor des Shaders übergeben, genau wie die Farbcodes für Licht und Schatten, in diesem Fall weis und schwarz. Der vierte Parameter bestimmt über die Intensität der Reflektion des Lichtes. Für Leda soll diese nicht zu hoch sein, damit sie die Textur nicht überblendet.
lightPoint = new PointLight3D();
shader = new PhongShader(lightPoint, 0xffffff, 0x000000, 15);
Leda liegt im JPG Format in der Bibliothek vor, exportiert man Sie in den Film, wird ihr eine Klasse zugewiesen, die von BitmapData erbt, wesshalb Breite und Höhe für die Initialisierung angegeben werden müssen. Dieses BitmapData Objekt übergibt man an das BitmapMaterial, der zweite parameter “true” aktiviert den Präzisionsmodus. Ohne diesen würde die Textur auf dem Plane hässliche Beulen bilden, wenn man es bewegt. Fehlt noch das ShadedMaterial, dieses erwartet das BitmapMaterial Objekt als ersten parameter, als zweiten den Shader selbst.
var leda :BitmapData = new leda_data(500, 500)
bitmapMaterial = new BitmapMaterial(leda, true);
shadedMaterial = new ShadedMaterial(bitmapMaterial, shader);
Die erste Zeile aus dem folgenden Abschnitt sollte leicht verständlich sein. Das Plane ist ein Primitive, es erhält das ShadedMaterial als Textur und anschließend werden Breite und Höhe bestimmt – die Tiefe fällt logischer Weise weg. Die nächste Zeile ist die magische Formel, mit der man erreicht, dass die Entfernung des Objekts im Raum zur Kamera (die ebenfalls “im Raum” ist) genau soviel beträgt, dass Ledas Textur nicht skalliert werden muss. Die sogenannte Pixelperfektion.
primitive = new Plane(shadedMaterial, 250, 250)
primitive.z = (camera.zoom * camera.focus) - Math.abs(camera.z);
Ein kleiner Exkurs zur Pixelperfektion: FlashPlayer ist überwiegend für Vektoren konzeptioniert, diese können verlustfrei skalliert werden, da sie auf Berechnungen basieren, nicht aber Bitmaps, welche bekannter maßen verpixeln (da sie auf Pixelinformationen basieren), sobald man sie vergrößert. Verkleinert man sie, ist der Rechenaufwand für ein scharfes Bild immer noch zu hoch, um flüssige Animationen rendern zu können.
Will man also eine Textur in PV3D scharf darstellen, muss die Z position des Objekts so bestimmt werden, dass die Textur auf dem Objekt in Orginalgröße gezeigt wird. So wie bei Leda, welche 250×250 pixel misst.
Wer mehr dazu wissen möchte, möge bei Bartek Drozdz vorbeischauen, dem die weite Verbreitung dieser überaus heiligen Formel zu verdanken ist.
Zu guter Letzt wird die statische Rotation ersetzt, nun kann der User mit der Maus über Ledas Rotation auf X und Y Achse im Raum bestimmen.
primitive.rotationY = viewport.containerSprite.mouseX / 4;
primitive.rotationX = viewport.containerSprite.mouseY / 4;
Glückwunsch, wer all die bissherigen Grundlagen gemeistert hat, dem fehlt nur noch eines um sie abzurunden. Interaktivität. Zwar reagiert leda hier bereits auf Benutzerinteraktion, doch sie feuert noch keine Events, auf die ein Handler reagieren könnte. Damit beschäftigt sich das letzte Grundlagentutorial.