package
{
import flash.display.*;
import flash.events.*;
import flash.utils.Dictionary;
import org.ascollada.*;
import org.papervision3d.cameras.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.objects.*;
import org.papervision3d.objects.parsers.*;
import org.papervision3d.lights.*;
import org.papervision3d.scenes.*;
import org.papervision3d.render.*;
import org.papervision3d.view.*;
import org.papervision3d.core.*;
import org.papervision3d.core.math.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.events.FileLoadEvent;
public class ERMain extends MovieClip
{
// Member variables
public var mCamera :Camera3D;
public var mCollada :DAE;
public var mSceneCenter :Number3D;
public var mRenderer :BasicRenderEngine;
public var mViewport :Viewport3D;
public var mLight :PointLight3D;
private var mContainer :Sprite;
private var mRadius :Number;
private var mRootNode :DisplayObject3D;
private var mRotationAnchor :Number3D;
private var mScene :Scene3D;
private var mTarget :DisplayObject3D;
private var mWheelZoomAmount :Number = 1.10;
// Constructor for the ERMain class
public function ERMain()
{
stage.quality = "HIGH";
stage.scaleMode = "noScale";
// 3D redraw mechanism as the 3D scene is manipulated
this.addEventListener( Event.ENTER_FRAME, EROnEnterFrame );
// Set the event handlers for the mouse to the stage so we will
// handle all mouse events not just those that click on a display
// object in this class. These event handlers handle the interactive
// rotation and mouse wheel zooming.
stage.addEventListener(MouseEvent.MOUSE_DOWN, ERMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, ERMouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_WHEEL, ERMouseWheelHandler);
mRotationAnchor = new Number3D;
// Perform the 3D initialization.
ERInitialize();
}
// This method creates and initializes the 3D scene.
private function ERInitialize():void
{
// Create canvas movieclip and center it
this.mContainer = new Sprite();
addChild( this.mContainer );
this.mContainer.x = 275;
this.mContainer.y = 200;
this.mViewport = new Viewport3D(550, 400, true, true);
addChild( mViewport );
this.mRenderer = new BasicRenderEngine();
// Create Scene
this.mScene = new Scene3D( );
this.mTarget = new DisplayObject3D ( );
// Create Camera. Camera is based on selected Swift 3D camera at the
time of export.
this.mCamera = new Camera3D();
this.mCamera.x = 0;
this.mCamera.y = 0;
this.mCamera.z = -2.39061;
this.mTarget.x = 0;
this.mTarget.y = 0;
this.mTarget.z = -0;
this.mCamera.zoom = 1.0;
this.mCamera.fov = 39.5978;
this.mCamera.target = this.mTarget;
// Establish the scene center to ensure all rotations
// occur about that center.
this.mSceneCenter = new Number3D;
this.mSceneCenter.x = 0;
this.mSceneCenter.y = 0;
this.mSceneCenter.z = 0;
this.mLight = new PointLight3D;
this.mLight.x = 0;
this.mLight.y = 0;
this.mLight.z = 0;
mCollada = new DAE( );
mCollada.addEventListener(FileLoadEvent.LOAD_COMPLETE, EROnFileLoaded,
false, 0, true);
mCollada.load("888.dae");
mRootNode = mScene.addChild( mCollada, "mRootNode" );
}
// The next three functions will turn all of the materials to double
sided.
private function EROnFileLoaded( event :Event ):void
{
var lMaterialsList:Object = mCollada.materials;
if ( lMaterialsList )
{
for each ( var lMaterial:MaterialObject3D in lMaterialsList )
lMaterial.doubleSided = true;
}
var lChildren:Dictionary = Dictionary (mCollada.children);
ERProcessChildrenMaterials ( lChildren );
}
private function ERProcessChildrenMaterials
( aChildren:Dictionary ):void
{
if ( aChildren )
{
for each ( var lChild:DisplayObject3D in aChildren )
ERProcessChildMaterials ( lChild );
}
var lChildren:Dictionary = Dictionary (mCollada.children);
}
private function
ERProcessChildMaterials( aChild:DisplayObject3D ):void
{
if ( aChild )
{
if ( aChild.materials )
{
for each ( var lMaterial:MaterialObject3D in
aChild.materials.materialsByName )
lMaterial.doubleSided = true;
}
var lChildren:Dictionary = Dictionary (aChild.children);
ERProcessChildrenMaterials ( lChildren );
}
}
// Rendering method to display changes as the scene is manipulated.
private function EROnEnterFrame( event :Event ):void
{
this.mRenderer.renderScene( mScene, mCamera, mViewport );
}
// When the mouse is pressed anywhere on the stage, set up for
// rotational manipulation and add the mouse move event handler.
// The rotational system is just like Swift 3D's trackballs. When
// the mouse is within the ball, the scene tracks like it is inside
// a ball and when the mouse is outside the ball, it spins around the
// axis perpendicular to the screen.
private function ERMouseDownHandler(event:MouseEvent):void
{
if ( mViewport.containerSprite.x < mViewport.containerSprite.y )
mRadius = mViewport.containerSprite.x;
else
mRadius = mViewport.containerSprite.y;
mRotationAnchor.x = mViewport.containerSprite.mouseX;
mRotationAnchor.y = mViewport.containerSprite.mouseY;
var lValue:Number = (mRadius * mRadius) - (mRotationAnchor.x *
mRotationAnchor.x) - (mRotationAnchor.y * mRotationAnchor.y);
if ( lValue < 0 )
mRotationAnchor.z = 0;
else
mRotationAnchor.z = Math.sqrt( lValue );
stage.addEventListener(MouseEvent.MOUSE_MOVE, ERMouseMoveHandler);
}
// This mouse move handler calculates the incremental rotation between
the mouse
// down or last mouse move event and the current mouse move event. It
then rotates
// the Papervision3D scene appropriate to that incremental rotation.
private function ERMouseMoveHandler(event:MouseEvent):void
{
var lCurrentPosition:Number3D = new Number3D;
var lLastPosition:Number3D = new Number3D;
var lAxis:Number3D = new Number3D;
var lCosAngle:Number;
var lAngle:Number;
var lTranslationMatrix:Matrix3D;
var lRotationMatrix:Matrix3D;
lCurrentPosition.x = mViewport.containerSprite.mouseX;
lCurrentPosition.y = mViewport.containerSprite.mouseY;
var lValue:Number = (mRadius * mRadius) - (lCurrentPosition.x *
lCurrentPosition.x) - (lCurrentPosition.y * lCurrentPosition.y);
if ( lValue < 0 )
lCurrentPosition.z = 0;
else
lCurrentPosition.z = Math.sqrt( lValue );
lLastPosition = mRotationAnchor;
mRotationAnchor = new Number3D ( lCurrentPosition.x,
lCurrentPosition.y, lCurrentPosition.z );
lLastPosition.normalize ( );
if ( lLastPosition.z == 0 )
lCurrentPosition.z = 0;
lCurrentPosition.normalize ( );
if ( lCurrentPosition.z == 0 )
lLastPosition.z = 0;
lAxis = Number3D.cross ( lLastPosition, lCurrentPosition );
lAxis.normalize ( );
lCosAngle = Number3D.dot ( lLastPosition, lCurrentPosition );
lAngle = Math.acos( lCosAngle );
ERRotateScene ( lAxis, lAngle );
event.updateAfterEvent();
}
// The mouse up handler terminates the interactive rotation mode by
// removing the mouse move handler.
private function ERMouseUpHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, ERMouseMoveHandler);
}
// The mouse wheel handler zooms in or out of the scene depending on
// the mouse wheel spin direction (positive or negative values).
private function ERMouseWheelHandler(event:MouseEvent):void
{
if ( event.delta > 0 )
mCamera.zoom *= mWheelZoomAmount;
else
mCamera.zoom /= mWheelZoomAmount;
}
public function ERZoomInScene( aZoomAmount:Number ):void
{
mCamera.zoom *= aZoomAmount;
}
public function ERZoomOutScene( aZoomAmount:Number ):void
{
mCamera.zoom /= aZoomAmount;
}
// The ERRotateScene method is used by both the interactive rotation
code
// and the button based rotation code.
public function ERRotateScene ( aAxis:Number3D, aAngle:Number ):void
{
var lTranslationMatrix:Matrix3D;
var lRotationMatrix:Matrix3D;
var lAxis:Number3D = aAxis.clone ( );
lTranslationMatrix = Matrix3D.translationMatrix( -mSceneCenter.x, -
mSceneCenter.y, mSceneCenter.z );
this.mCollada.transform = Matrix3D.multiply( lTranslationMatrix,
this.mCollada.transform );
lAxis.x = - lAxis.x;
Matrix3D.rotateAxis ( mCamera.transform, lAxis );
lRotationMatrix = Matrix3D.rotationMatrix( lAxis.x, lAxis.y, lAxis.z,
aAngle );
this.mCollada.transform = Matrix3D.multiply( lRotationMatrix,
this.mCollada.transform );
lTranslationMatrix = Matrix3D.translationMatrix( mSceneCenter.x,
mSceneCenter.y, -mSceneCenter.z );
this.mCollada.transform = Matrix3D.multiply( lTranslationMatrix,
this.mCollada.transform );
};
}
}