Analizzando i tutorials che avevo preparato per la parte 3 e 4 della mia guida di papervision, ho pensato di mostrare un altra tecnica che ho appreso partendo dal tutorial del mitico Lee Felarca riguardo i materiali e le luci, il problema è che il codice da lui presentato non funziona coi sorgenti di PV3D 2.0 beta ed erano necessarie delle importanti modifiche (purtroppo moltissimi tutorials in rete si basano sulla versione 2.0 alpha, ormai in disuso).
Cerchiamo quindi, partendo dall’esempio 4, di aggiungere un piano di appoggio interattivo, che rifletta le sfere come se fosse metallizzato. La programmazione di tale piano richiede purtroppo l’aggiunta e la modifica di parte del codice.
Questo è il risultato che dovremmo raggiungere (clicca su continua):
Vediamo il codice, le parti corrispondenti all’esempio 4 già descritto nel precedente articolo saranno colorate più scure:
package {
//autore: www.enricoviola.it/blog
//——————————-
//Guida personale a Papervision3D//importiamo innanzitutto questa classe per
import caurina.transitions.Tweener;import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.net.URLRequest;
//importare libreria per controllo del suono
import flash.media.Sound;import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shadematerials.CellMaterial;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.shadematerials.GouraudMaterial;
import org.papervision3d.materials.shadematerials.PhongMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.materials.WireframeMaterial;public class esempio4bis extends Sprite {
private var scene:Scene3D;
private var camera:Camera3D;
private var viewport:Viewport3D;
private var renderer:BasicRenderEngine;private static const RAGGIO_ORBITALE:Number = 120;
private const PianoBMP_SIDE:Number = 500;
private var viewportPiano:Viewport3D;
private var cameraPiano:Camera3D;
private var Piano:Plane;
private var matPiano:CompositeMaterial;
private var matPianoBmp:BitmapMaterial;
private var bmdPiano:BitmapData;
private var matrixPiano:Matrix;private var sfera1:Sphere;
private var sfera2:Sphere;
private var sfera3:Sphere;
private var sfera4:Sphere;
private var sferaGroup:DisplayObject3D;
private var luce:PointLight3D;private var staiRuotando:Boolean = false;
private var ultimoMouseX:int;
private var ultimoMouseY:int;
private var cameraPitch:Number = 60;
private var cameraYaw:Number = -60;public function esempio4bis() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;init3D();
createScene();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
//avviamo il listener ogni frame per il render
this.addEventListener(Event.ENTER_FRAME, loop);
}private function init3D():void {
viewport = new Viewport3D(0, 0, true, true);
viewport.opaqueBackground = 0;
addChild(viewport);
camera = new Camera3D(60);
scene = new Scene3D();
renderer = new BasicRenderEngine();
//posizioniamo la camera
camera.z = -500;
camera.orbit(cameraPitch, cameraYaw);
}private function createScene():void {
//la creazione della scena è stata già spiegata nell’esempio 3
luce = new PointLight3D(true);
luce.x = 400;
luce.y = 1000;
luce.z = -400;//sfera 1
var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterial(luce, 0xFFFFFF, 0×060433);//IMPORTANTE: bisona indicare che il materiale che stia realizzando
//sia posizionato come interattivo, al fine di rispondere efficacemente
//al comando (CLICK) proveniente dal mouse.
flatShadedMaterial.interactive = true;
sfera1 = new Sphere(flatShadedMaterial, 50, 10, 10);
sfera1.x = -RAGGIO_ORBITALE;//sfera 2 blu
var gouraudMaterial:MaterialObject3D = new GouraudMaterial(luce, 0×6654FF, 0×060433);
//rendiamo il materiale interattivo agli eventi del mouse
gouraudMaterial.interactive = true;
sfera2 = new Sphere(gouraudMaterial, 50, 10, 10);
sfera2.x = RAGGIO_ORBITALE;//sfera 3 verde
var phongMaterial:MaterialObject3D = new PhongMaterial(luce, 0xFFFFFF, 0×066021, 100);
//rendiamo il materiale interattivo agli eventi del mouse
phongMaterial.interactive = true;
sfera3 = new Sphere(phongMaterial, 50, 10, 10);
sfera3.z = -RAGGIO_ORBITALE;//sfera 4 rossa
var cellMaterial:MaterialObject3D = new CellMaterial(luce, 0xFFFFFF, 0xB11201, 12);
//rendiamo il materiale interattivo agli eventi del mouse
cellMaterial.interactive = true;
sfera4 = new Sphere(cellMaterial, 50, 10, 10);
sfera4.z = RAGGIO_ORBITALE;sferaGroup = new DisplayObject3D();
sferaGroup.addChild(sfera1);
sferaGroup.addChild(sfera2);
sferaGroup.addChild(sfera3);
sferaGroup.addChild(sfera4);//avendo reso interattivo il materiale applicato ad ogni sfera, è possibile ora
//applicare dei listener agli oggetti, precisamente il listener di papervision
//”InteractiveScene3DEvent” per gli eventi del mouse sugli oggetti 3D.
sfera1.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickSuSfera);
sfera2.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickSuSfera);
sfera3.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickSuSfera);
sfera4.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickSuSfera);scene.addChild(sferaGroup);
scene.addChild(luce);//realizziamo il viewport che ci serve per la riflessione
viewportPiano = new Viewport3D(PianoBMP_SIDE, PianoBMP_SIDE, false);
//diamo un colo grigio al piano
viewportPiano.opaqueBackground = 0×222222;
//aggiungiamo un filtro di sfuocatura per dare una impressione
//più realistica di riflesso in una superfice mettalica
viewportPiano.filters = [ new BlurFilter(15,15,1)];//creiamo il materiale
bmdPiano = new BitmapData(PianoBMP_SIDE,PianoBMP_SIDE,true);
matPianoBmp = new BitmapMaterial(bmdPiano);
//un materiale composito costituisce una amalgama di differenti
//materiali uniti in uno.
matPiano = new CompositeMaterial();
//rendiamolo interattivo per la semplice animazione
matPiano.interactive = true;
matPiano.addMaterial(matPianoBmp);
//aggiungiamo anche una gabbia
matPiano.addMaterial( new WireframeMaterial(0×444444,100) );//Matrix realizza una matrice per la trasformazione, esso
//non è un comando di PV3D ma di Flash, consente di mappare
//i punti per applicarvi una trasformazione
matrixPiano = new Matrix();
matrixPiano.scale(1,-1);
matrixPiano.translate(0,PianoBMP_SIDE);//realizziamo la camera (questa guarda le sfere da sotto verso sopra)
//essa rappresenta l’istantanea che ad ogni frame verrà fatta al viewport
//(ossia a ciò che si vede nella scena), questa verrà poi utlizzata
//come bitmap per riempire il piano, dando 1 sensazione di riflesso.
cameraPiano = new Camera3D();
cameraPiano.zoom = 27;
cameraPiano.focus = 50;
//questi 2 valori di sopra possono essere cambiati a piacere
//per risultati differenti.
cameraPiano.x = 0;
cameraPiano.y = -1000;
cameraPiano.z = 0;
cameraPiano.pitch(-90);// Realizzazione e sistemazione del piano
Piano = new Plane(matPiano, 350,350, 25,25);
Piano.x = Piano.z = 0;
Piano.y = -50;
Piano.rotationX = 90;
scene.addChild(Piano);
Piano.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickSuPiano);
}private function loop(event:Event):void {
sfera1.yaw(-8);
sfera2.yaw(-8);
sfera3.yaw(-8);
sfera4.yaw(-8);sferaGroup.yaw(3);
if (staiRuotando) {
var dPitch:Number = (mouseY - ultimoMouseY) / 2;
var dYaw:Number = (mouseX - ultimoMouseX) / 2;
cameraPitch -= dPitch;
cameraYaw -= dYaw;
if (cameraPitch <= 0) {
cameraPitch = 0.1;
} else if (cameraPitch >= 180) {
cameraPitch = 179.9;
}
ultimoMouseX = mouseX;
ultimoMouseY = mouseY;
camera.orbit(cameraPitch, cameraYaw);
}// Renderizziamo quindi la scena che si visualizza dalla
//camera del Piano (quella disposta in basso) e poi disegniamo
//(quindi memorizziamo) tale visuale come bitmap del Piano.
//Dopodichè si comanda l’aggiornamento del bipmap del Piano.
//Un metodo alternativo utilizza i seguenti
//comandi: “Use BitmapViewportMaterial” + “BitmapViewport3D”
renderer.renderScene(scene, cameraPiano, viewportPiano);
bmdPiano.draw(viewportPiano, matrixPiano);
matPianoBmp.bitmap = bmdPiano;
matPianoBmp.updateBitmap();//renderizziamo ora l’intera scena che verrà mostrata
renderer.renderScene(scene, camera, viewport);
}private function onMouseDown(event:MouseEvent):void {
staiRuotando = true;
ultimoMouseX = event.stageX;
ultimoMouseY = event.stageY;
}private function onMouseUp(event:MouseEvent):void {
staiRuotando = false;
}private function clickSuSfera(event:InteractiveScene3DEvent):void {
//lettura file suono mp3
var richiesta_file_mov:URLRequest = new URLRequest(”http://www.enricoviola.it/blog/risorse_varie/guidaPapervisio3D/boing.mp3″);
var boing:Sound = new Sound();
boing.load(richiesta_file_mov);
boing.play();var object:DisplayObject3D = event.displayObject3D;
Tweener.addTween(object, { y:200, time:1, transition:”easeOutSine”, onComplete:function():void { goBack(object); } } );
}private function goBack(object:DisplayObject3D):void {
Tweener.addTween(object, {y:0, time:3, transition:”easeOutBounce”});
}
//realizziamo queste 2 funzione che creano una piccola animazione
//al piano, facendolo inclinare di 90° e poi facendolo tornare
//piatto con un movimento a rimbalzo.
private function clickSuPiano(event:InteractiveScene3DEvent):void {
var object:DisplayObject3D = event.displayObject3D;
Tweener.addTween(object, { rotationX:0, time:3, transition:”easeOutSine”, onComplete:function():void { tornaPiano(object); } } );
}
private function tornaPiano(object:DisplayObject3D):void {
Tweener.addTween(object, {rotationX:90, time:5, transition:”easeOutBounce”});
}
}
}