November 2009
3D-Verbiegungen in Flash
Krumme Dinger in der dritten Dimension
Die dritte Dimension ist für Flash dank zahlreicher 3D-Engines und seit neuestem durch native Methoden innerhalb von Flash CS4 ein gängiger, fast alltäglicher Ort geworden. Auf zahlreichen Websites tummeln sich 3D-Bildergalerien, wimmelt es von sich drehenden Würfeln oder werden interaktiv begehbare, virtuelle Räume geschaffen. Alles schön und gut, aber alles meist langweilig linear.
Text: Frank Reitberger
Der Quellcode steht auch als Download bereit.
Denn häufig werden nur Standard-Primitives (Cubes, Spheres, Cylinder usw.) verwendet, texturiert und dann noch ein wenig animiert. Dabei gibt es für all die gängigen 3D-Engines bereits eine Menge guter Bibliotheken, die man als Add-on benutzen kann, um das gesamte Setup zu verfeinern:
- Physics (http://www.jiglibflash.com/blog/)
- Augmented Reality (http://www.libspark.org/wiki/saqoosha/FLARToolKit/en)
- 3D Modifiers (http://code.google.com/p/as3dmod/)
Letztgenannte AS3mod beispielsweise ist eine Sammlung an Modifikatoren, die es dem Benutzer erlauben, direkt und einfach auf die Architektur von 3D-Objekten Einfluss zu nehmen. Derzeit stehen sieben Wandler zur Verfügung, mit denen sich schon einiges bewirken und manipulieren lässt:
- Bend (verbiegt ein Objekt)
- Noise (verformt ein Objekt zufällig)
- Skew (verzerrt ein Objekt)
- Taper (erzeugt zugespitzte bis konische Verformungen)
- Bloat (bläht Objekte stellenweise auf)
- Perlin (verwendet perlinNoise und verschiebt anhand der Farbwerte)
- Twist (verdreht ein Objekt in sich)
Und das Ganze ist noch dazu kinderleicht zu bedienen, sodass man sofort loslegen kann.
Was ist was?
AS3mod ist quasi ein Add-on und somit als zusätzliche Zutat zur vorab gewählten 3D-Engine gedacht. Derzeit unterstützt die Bibliothek Papervision3D, Away3D, Sandy3D und Alternativa3D. In unserem Fall habe ich mich für Papervision3D entschieden – die hier verwendeten AS3mod-Einstellungen lassen sich aber ebenso problemlos für alle soeben erwähnten Bibliotheken adaptieren. Einfach beim import ein anderes Plug-in einstöpseln, also anstelle von import com.as3dmod.plugins.pv3d.* beispielsweise für Away3D import com.as3dmod.plugins.away3d.* auswählen und schon läuft es.
package {///////////////////////////////////// import used classes///////////////////////////////////import com.as3dmod.*;import com.as3dmod.modifiers.*;import com.as3dmod.plugins.pv3d.*import flash.display.*;import flash.events.*;import flash.filters.*;import flash.text.*;import flash.utils.getTimer;import gs.*;import gs.easing.*;import org.papervision3d.cameras.*;import org.papervision3d.lights.*;import org.papervision3d.materials.*;import org.papervision3d.materials.shadematerials.*;import org.papervision3d.materials.shaders.*;import org.papervision3d.materials.utils.*;import org.papervision3d.objects.primitives.*;import org.papervision3d.render.*;import org.papervision3d.scenes.*;import org.papervision3d.view.*;///////////////////////////////////// class///////////////////////////////////public class TwistyCubes extends Sprite {public var surface :BitmapData;public var vortex :BitmapData;private var view :Viewport3D;private var scene :Scene3D;private var cylinder :Cylinder;private var cube01 :Cube;private var cube02 :Cube;private var light :PointLight3D;private var camera :Camera3D;private var renderer :BasicRenderEngine;private var stack01 :ModifierStack;private var stack02 :ModifierStack;private var twist01 :Twist;private var twist02 :Twist;///////////////////////////////// class constructor///////////////////////////////public function TwistyCubes() {super();if ( stage ) {setup();} else {addEventListener( Event.ADDED_TO_STAGE,setup );}}///////////////////////////////// setup///////////////////////////////private function setup(evt:Event=null):void {removeEventListener(Event.ADDED_TO_STAGE,setup)///////////////////////////////////// initialize///////////////////////////////////initEngine();setupMaterials();initBendings();launch();}///////////////////////////////////// initialize: 3d.engine///////////////////////////////////private function initEngine():void {this.view = new Viewport3D( 500, 500 );this.view.filters = [new DropShadowFilter(40, 90, 0, 0.6, 24, 24)];this.scene = new Scene3D();this.renderer = new BasicRenderEngine();this.camera = new Camera3D();this.camera.y = 400;this.camera.z = -850;addChild( this.view );}///////////////////////////////////// setup: material(s)///////////////////////////////////private function setupMaterials():void {///////////////////////////////////// setup: light///////////////////////////////////this.light = new PointLight3D();this.light.y = 400;this.light.x = 50;this.light.z = -600;///////////////////////////////////// setup: material(s)///////////////////////////////////var bmp01 :BitmapMaterial = new BitmapMaterial( surface );var shader01 :ShadedMaterial = new ShadedMaterial( bmp01, new PhongShader( this.light, 0xFFFFFF ) );var bmp02 :BitmapMaterial = new BitmapMaterial( surface );var shader02 :ShadedMaterial = new ShadedMaterial( bmp02, new PhongShader( this.light, 0xFFFFFF ) );var bmp03 :BitmapMaterial = new BitmapMaterial( surface );var shader03 :ShadedMaterial = new ShadedMaterial( bmp03, new PhongShader( this.light, 0xFFFFFF ) );var bmp04 :BitmapMaterial = new BitmapMaterial( surface );var shader04 :ShadedMaterial = new ShadedMaterial( bmp04, new PhongShader( this.light, 0xFFFFFF ) );var materialList: MaterialsList = new MaterialsList( {"top": new FlatShadeMaterial( this.light, 0x666666 ),"bottom": new FlatShadeMaterial( this.light, 0x666666 ),"left" : shader01,"right" : shader02,"front" : shader03,"back" : shader04} );///////////////////////////////////// setup: cube(s)///////////////////////////////////this.cube01 = new Cube( materialList, 500, 500, 500, 5, 5, 5 );this.cube01.rotationY = 45;this.cube02 = new Cube( materialList, 500, 500, 500, 5, 5, 5 );this.cube02.rotationY = 45;this.cube02.y -= 550;this.camera.target = this.cube01;///////////////////////////////////// add///////////////////////////////////this.scene.addChild( this.cube01 );this.scene.addChild( this.cube02 );///////////////////////////////////// event(s)///////////////////////////////////stage.addEventListener( MouseEvent.CLICK, deform );}///////////////////////////////////// initialize: 3d.bending(s)///////////////////////////////////private function initBendings():void {this.stack01 = new ModifierStack( new LibraryPv3d(), this.cube01 );this.stack02 = new ModifierStack( new LibraryPv3d(), this.cube02 );this.twist01 = new Twist( 0 );this.twist02 = new Twist( 0 );///////////////////////////////////// add: modifier(s)///////////////////////////////////this.stack01.addModifier( this.twist01 );this.stack02.addModifier( this.twist02 );}///////////////////////////////////// launch///////////////////////////////////private function launch():void {addEventListener( Event.ENTER_FRAME, onUpdateFrame );}private function onUpdateFrame(ev:Event):void {///////////////////////////////////// set: camera & light angle(s)///////////////////////////////////var vy:Number = (stage.mouseY / 400 - 0.5) * 2;var damp :Number = vy * 600;var angle:Number = vy * 90;this.camera.y = this.camera.y + ( damp - this.camera.y ) / 20;this.light.y = this.camera.y;///////////////////////////////////// set: shadow.angle(s)///////////////////////////////////var ds:DropShadowFilter;ds = this.view.filters[0];ds.angle = ds.angle + ( angle - ds.angle) / 20;this.view.filters = [ ds ];///////////////////////////////////// handle: modifier.stack///////////////////////////////////this.stack01.apply();this.stack02.apply();///////////////////////////////////// render///////////////////////////////////this.renderer.renderScene( this.scene, this.camera, this.view );}///////////////////////////////////// process: bending(s)///////////////////////////////////private function deform(evt:MouseEvent):void {TweenLite.to( this.twist01, 0.25, { "angle":0.6, "ease":Quad.easeOut, "onComplete":flatten, "onCompleteParams":[ this.twist01 ] } );TweenLite.to( this.cube01, 0.5, { "rotationY":this.cube01.rotationY + 90 } );TweenLite.to( this.twist02, 0.25, { "angle":0.6, "ease":Quad.easeOut, "onComplete":flatten, "onCompleteParams":[ this.twist02 ] } );TweenLite.to( this.cube02, 0.5, { "rotationY":this.cube02.rotationY - 90 } );}///////////////////////////////////// set.back.bending(s)///////////////////////////////////private function flatten( twist:Twist ):void {TweenLite.to( twist, 0.3, { "angle":0, "ease":Back.easeOut } );}
ich habe ein paar Beispiele im Netz gefunden die ich sehr beeindruckend finde!
Ich weis nicht genau ob die Beispiele eine der hier aufgeführten Klassen benutzt,aber es sieht stark danach aus ;)
Beispiel 1:
http://www.flashdevelopment.de/CONTENTS/DYNAMIC3DVIDEOSHOWCASE02/dynamic3dvideoshowcase02.php
Beispiel 2:
http://www.flashdevelopment.de/CONTENTS/DYNAMIC3DPRODUCTSLIDER01/dynamic3dproductslider01.php
Beispiel 3:
http://www.flashdevelopment.de/CONTENTS/3DCURVESHOWCASE01/3dcurveshowcase01.php
Beispiel 4:
http://www.flashdevelopment.de/CONTENTS/DYNAMIC3DCURVESTACK01/dynamic3dcurvestack01.php
Viele Grüße :) #zitieren
































