Archive

Archive for the ‘Experiment’ Category

Box2Dwrapper – More Examples with Joints

April 1st, 2009

Hi!

Here are a few examples on how to set up joints using Box2Dwrapper. More to come! Remember, you can grab the wrapper source here : https://box2dwrapper.googlecode.com/svn/trunk I’ll be posting more complex examples soon so stay tuned ;)

Prismatic Joint Example

package
{
    import Box2D.Common.Math.b2Vec2;
   
    import com.box2dwrapper.math.Vec;
    import com.box2dwrapper.object.Box;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class PrismaticJointExample extends Box2DView
    {
        public function PrismaticJointExample()
        {
            super();
            initialize();
        }
       
        private function initialize():void
        {
            createBoundingWalls();
            showDebug = true;
            allowDragging = true;
                       
            createObjects();
           
            startPhysicsRender();
        }
       
        private function createObjects():void
        {
            var plank:Box = new Box();
            plank.scale(100, 20);
            plank.position(stage.stageWidth * 0.5, stage.stageHeight * 0.5);
            plank.type = "dynamic";
            addBody(plank);
           
            var joint:Joint = new Joint(Joint.PRISMATIC);
            joint.initialize(world.GetGroundBody(), plank.body, plank.body.GetWorldCenter(), new b2Vec2(1, 0));
            joint.lowerTranslation = -3;
            joint.upperTranslation = 3
            joint.enableLimit = true;          
           
            joint.maxMotorForce = 100;
            joint.motorSpeed = 4.0;
            joint.enableMotor = true;          
           
            addJoint(joint);
        }
       
    }
}

Revolute Joint Example

package
{
    import com.box2dwrapper.math.Vec;
    import com.box2dwrapper.object.Box;
    import com.box2dwrapper.object.Circle;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class RevoluteJointExample extends Box2DView
    {
        public function RevoluteJointExample()
        {
            super();
            initialize();
        }
       
        private function initialize():void
        {
            createBoundingWalls();
            showDebug = true;
            allowDragging = true;
                       
            createObjects();
           
            startPhysicsRender();
        }
       
        private function createObjects():void
        {
            var pivot:Circle = new Circle();
            pivot.radius = 10;
            pivot.position(stage.stageWidth * 0.5, stage.stageHeight * 0.5);
            pivot.type = "static";
            addBody(pivot);
           
            var plank:Box = new Box();
            plank.scale(20, 100);
            plank.position(pivot.x, pivot.y + 35);
            plank.type = "dynamic";
            addBody(plank);
           
            var tac:Joint = new Joint(Joint.REVOLUTE);
            tac.initialize(pivot.body, plank.body, pivot.body.GetWorldCenter());
           
            tac.enableMotor = true;
            tac.motorSpeed = 2;
            tac.maxMotorTorque = 50;
           
            addJoint(tac);
        }
       
    }
}

Gear Joint Example

package
{
    import Box2D.Dynamics.Joints.b2GearJoint;
    import Box2D.Dynamics.Joints.b2GearJointDef;
   
    import com.box2dwrapper.object.Circle;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class GearJointExample extends Box2DView
    {
        public function GearJointExample()
        {
            super();
            showDebug = true;
            allowDragging = true;
            initialize();
            startPhysicsRender();
        }
       
        private function initialize():void
        {
            var gear1:Circle = new Circle();
            gear1.radius = 40;
            gear1.density = 2;
            gear1.position(stage.stageWidth * 0.45, stage.stageHeight * 0.5);
            gear1.type = "dynamic";
            addBody(gear1);
           
            var gear2:Circle = new Circle();
            gear2.radius = 60;
            gear2.density = 3;
            gear2.position(stage.stageWidth * 0.65, stage.stageHeight * 0.5);
            gear2.type = "dynamic";
            addBody(gear2);
           
            var joint1:Joint = new Joint(Joint.REVOLUTE);
            joint1.initialize(world.GetGroundBody(), gear1.body, gear1.body.GetWorldCenter());
            addJoint(joint1);
           
            var joint2:Joint = new Joint(Joint.REVOLUTE);
            joint2.initialize(world.GetGroundBody(), gear2.body, gear2.body.GetWorldCenter());
            addJoint(joint2);
           
            var gearJoint:Joint = new Joint(Joint.GEAR);
            gearJoint.body1 = gear1.body;
            gearJoint.body2 = gear2.body;
            gearJoint.joint1 = joint1.joint;
            gearJoint.joint2 = joint2.joint;
            gearJoint.ratio = 1;
            addJoint(gearJoint);               
        }      
    }
}

Experiment, Lab, as3

FirstPersonCamera3D updated to v1.9

January 21st, 2009

First of all, I just want to say thanks for all the feedback I got from you guys. So, THANKS!

A few MAJOR changes have been made to the FirstPersonCamera3D class:

Change made to initialize method

In order for the class to work, the initialize method now accepts the viewport instance as it’s first argument instead of a reference to the stage (the other two arguments are explained in the next paragraph).

firstPersonCamera.initialize(viewport, .2, .2);

Movement logic revamped

The entire code for the actual moving around has been totally revamped, hence, removing its dependency to Tweener or any other tween engine for that matter. Also, all ENTER_FRAMES have been removed and movement is calculated in the “look” method. With the new logic, moving in diagonal directions is way smoother also.

Along with the revamp came two new properties which will greatly increase the way we use movement: “speed” and “friction“. By adding these properties, we can simulate various types of movement, anywhere from gliding on ice to trying to move in quicksand!

Speed could be a number 0 – 1 where 0 is full stop and 1 is really really fast. Defaults to .2

Friction is a number 0 – 1 where 1 does not allow you to move and 0 is really really slippery. Defaults to .1

These properties can be directly set in the “initialize” method as so:

firstPersonCamera.initialize(viewport, .2, .2);

… where the second argument is “speed” and the third argument is “friction”

Change in the “mapKeys” method

The “mapKeys” methods can now accept any of the following:

FirstPersonCamera3D.ARROWS;  //maps only the arrow keys
FirstPersonCamera3D.WASD;  //maps the wasd keys
FirstPersonCamera3D.WASD_AND_ARROWS;  //maps both arrows and wasd keys

New moveBounds property

Another newly added property is “moveBounds”. This property limits the cameras movement to a set of predetermined boundries. Essentially, its like placing the camera within 4 walls. This is the syntax:

firstPersonCamera.moveBounds = {front:3500, back:-3500, left:-3500, right:3500};

For several hours I tinkered around with the class trying to set up collision detection, but then I figured that the best way to deal with collisions is to actually have some sort of “plugin” system where you could essentially integrate the FirstPersonCamera3D object with your Physics Engine of choice! This may be coming sooner than you think ;)

Here’s the new class:

package
{
    import flash.display.Stage;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.utils.*;
   
    import org.papervision3d.cameras.Camera3D;
    import org.papervision3d.core.math.Number3D;
    import org.papervision3d.view.Viewport3D;
   
    /**
     * Camera3D object with First Person functionality
     * @author Reynaldo Columna
     *
     */

    public class FirstPersonCamera3D extends Camera3D
    {
       
        /**
         * Holds the key codes for the arrow keys
         */

        public static const ARROWS:Object = {left:37, right:39, forward:38, back:40};
        /**
         * Holds the key codes for the "w", "a", "s" and "d" keys
         */
       
        public static const WASD:Object = {left:65, right:68, forward:87, back:83};
        /**
         *  Holds the key codes for both the "w", "a", "s" and "d" keys and the arrow keys
         */
       
        public static var WASD_AND_ARROWS:Array;
       
        protected static const UP_ARROW:int = 38;
        protected static const LEFT_ARROW:int = 37;
        protected static const RIGHT_ARROW:int = 39;
        protected static const DOWN_ARROW:int = 40;
       
        private static var FORWARD_KEY:int;
        private static var LEFT_KEY:int;
        private static var RIGHT_KEY:int;
        private static var BACK_KEY:int;
       
        protected var _sensitivity:Number;
        protected var _maxRotationX:Number;
        protected var _maxRotationY:Number;
        protected var _stageReference:Stage;
        protected var _viewportReference:Viewport3D;
        protected var _friction:Number;
        protected var _speed:Number;
        protected var _mode:String;
        protected var _moveBounds:Object;
       
        private var mouseDownPositionX:Number;
        private var mouseDownPositionY:Number;
        private var currentRotationY:Number;
        private var currentRotationX:Number;
       
        private var velocity:Number3D;
        private var movingForward:Boolean;
        private var movingLeft:Boolean;
        private var movingRight:Boolean;
        private var movingBack:Boolean;
        private var doManualLook:Boolean;
        private var useBothSetsOfKeys:Boolean;
       
        /**
         * Constructs the camera just as you would with a Camera3D object
         * @param fov
         * @param near
         * @param far
         * @param useCulling
         * @param useProjection
         *
         */
 
        public function FirstPersonCamera3D(fov:Number=60, near:Number=10, far:Number=5000, useCulling:Boolean=false, useProjection:Boolean=false)
        {
            super(fov, near, far, useCulling, useProjection);
        }
       
        /**
         * initializes the camera functionality
         * @param $viewport viewport
         * @param $speed 0 - 1 where 0 is full stop and 1 is really really fast! Defaults to .2
         * @param $friction 0 - 1 where 1 does not allow you to move and 0 is really really slippery! Defaults to .1
         *
         */
       
        public function initialize($viewport:Viewport3D, $speed:Number = 0.2, $friction:Number = 0.1):void
        {
            viewportReference = $viewport;
            stageReference = viewportReference.containerSprite.stage;
            friction = map($friction, 0, 1, 1, 0);
            speed = map($speed, 0, 1, 0, 100);
            movingForward = false;
            movingLeft = false;
            movingRight = false;
            movingBack = false;
            moveBounds = null;
            velocity = new Number3D();
            useBothSetsOfKeys = false;
            FirstPersonCamera3D.WASD_AND_ARROWS = [FirstPersonCamera3D.ARROWS, FirstPersonCamera3D.WASD];
            addListeners();
        }
       
        /**
         * Maps the keys to be used for movement. If no keys are specified, the arrow keys are used as defauilt.
         * @param keys An object with the following values: forward, back, left and right. Each should be a key code.
         *
         */
 
        public function mapKeys(keys:* = null):void
        {
            if(keys == FirstPersonCamera3D.WASD_AND_ARROWS){
                useBothSetsOfKeys = true;
                keys = null
            }
            FirstPersonCamera3D.FORWARD_KEY = ((keys != null) ? keys.forward : FirstPersonCamera3D.UP_ARROW) || FirstPersonCamera3D.UP_ARROW;
            FirstPersonCamera3D.BACK_KEY = ((keys != null) ? keys.back : FirstPersonCamera3D.DOWN_ARROW) || FirstPersonCamera3D.DOWN_ARROW;
            FirstPersonCamera3D.LEFT_KEY = ((keys != null) ? keys.left : FirstPersonCamera3D.LEFT_ARROW) || FirstPersonCamera3D.LEFT_ARROW;
            FirstPersonCamera3D.RIGHT_KEY = ((keys != null) ? keys.right : FirstPersonCamera3D.RIGHT_ARROW) || FirstPersonCamera3D.RIGHT_ARROW;
        }
       
        /**
         * Unregisters mapped keys
         *
         */
 
        public function removeKeyMapping():void
        {
           FirstPersonCamera3D.FORWARD_KEY = FirstPersonCamera3D.BACK_KEY = FirstPersonCamera3D.LEFT_KEY = FirstPersonCamera3D.RIGHT_KEY = -1;
        }
       
        /**
         * Makes the camera "look" around based on the mouse position
         * @param $sensitivity Number 0 to 1 representing how sensible the camera is to the mouse movement.
         * @param $maxRotationX Number representing the max horizontal rotation (0 to 360)
         * @param $maxRotationY Number representing the max vertical rotation (0 to 360)
         *
         */
 
        public function look($sensitivity:Number = 0.5, $maxRotationX:Number = 90, $maxRotationY:Number = 90):void
        {
            sensitivity = $sensitivity;
            maxRotationX = $maxRotationX;
            maxRotationY = $maxRotationY;
           
            if(mode == "auto"){
                var horizontalDegrees:Number = map(stageReference.mouseX, 0, stageReference.stageWidth, maxRotationX * -1, maxRotationX);
                var verticalDegrees:Number = map(stageReference.mouseY, 0, stageReference.stageHeight, maxRotationY * -1, maxRotationY);
                rotationX += (verticalDegrees - rotationX) * sensitivity;
                rotationY += (horizontalDegrees - rotationY) * sensitivity;
            }else if(mode == "manual"){
                if(doManualLook){
                    var horizontalDistance:Number = stageReference.mouseX - mouseDownPositionX;
                    var verticalDistance:Number = stageReference.mouseY - mouseDownPositionY;
                    var finalRotationX:Number = currentRotationX + (verticalDistance * (sensitivity * .5));
                    var finalRotationY:Number = currentRotationY + (horizontalDistance * (sensitivity * .5));
                    rotationX += (finalRotationX - rotationX) * sensitivity;
                    rotationY += (finalRotationY - rotationY) * sensitivity;
                }
            }
           
            renderMovement();
        }
       
        private function addListeners():void
        {
            stageReference.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
            stageReference.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
        }
       
        private function removeListeners():void
        {
            stageReference.removeEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
            stageReference.removeEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
            stageReference.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
            stageReference.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
        }
       
        private function map(value:Number, min1:Number, max1:Number, min2:Number, max2:Number):Number
        {
            return min2 + (max2 - min2) * (value - min1) / (max1 - min1);
        }
       
        private function renderMovement():void
        {
            if(movingBack){
                velocity.z -= speed * Math.cos(rotationY * (Math.PI / 180));
                velocity.x -= speed * Math.sin(rotationY * (Math.PI / 180));
            }
           
            if(movingForward){
                velocity.z += speed * Math.cos(rotationY * (Math.PI / 180));
                velocity.x += speed * Math.sin(rotationY * (Math.PI / 180));
            }
           
            if(movingLeft){
                velocity.z += speed * Math.sin(rotationY * (Math.PI / 180));
                velocity.x -= speed * Math.cos(rotationY * (Math.PI / 180));
            }
           
            if(movingRight){
                velocity.z -= speed * Math.sin(rotationY * (Math.PI / 180));
                velocity.x += speed * Math.cos(rotationY * (Math.PI / 180));
            }
 
            velocity.multiplyEq(friction);
 
            x += velocity.x;
            z += velocity.z;
           
            if(moveBounds != null){
                if(x < moveBounds.left) x = moveBounds.left;
                if(x > moveBounds.right) x = moveBounds.right;
                if(z < moveBounds.back) z = moveBounds.back;
                if(z > moveBounds.front) z = moveBounds.front;
            }
           
        }
       
        public function clear():void
        {
            removeListeners();
            stageReference = null;
            viewportReference = null;
        }
       
        /*
        Properties
        */

       
        /**
         * Sets or returns the look sensitivity
         * @return Number
         *
         */
 
        public function get sensitivity():Number { return _sensitivity }
        public function set sensitivity(value:Number):void { _sensitivity = value; }

        /**
         * Sets or returns the maximum horizontal rotation
         * @return Number
         *
         */
 
        public function get maxRotationX():Number { return _maxRotationX }
        public function set maxRotationX(value:Number):void { _maxRotationX = value; }
       
        /**
         * Sets or returns the maximum vertical rotation
         * @return Number
         *
         */

        public function get maxRotationY():Number { return _maxRotationY }
        public function set maxRotationY(value:Number):void { _maxRotationY = value; }
       
        /**
         * Sets or returns a reference to the stage
         * @return Number
         *
         */
 
        public function get stageReference():Stage { return _stageReference }
        public function set stageReference(value:Stage):void { _stageReference = value; }
       
        /**
         * Sets or returns a reference to the viewport
         * @return
         *
         */
       
        public function get viewportReference():Viewport3D { return _viewportReference }
        public function set viewportReference(value:Viewport3D):void { _viewportReference = value; }
       
        /**
         * Sets or returns the friction
         * @return
         *
         */
       
        public function get friction():Number { return _friction }
        public function set friction(value:Number):void { _friction = value; }
       
        /**
         * Returns or set the speed of movement
         * @return
         *
         */
       
        public function get speed():Number { return _speed }
        public function set speed(value:Number):void { _speed = value; }
       
        /**
         * Sets or returns the camera mode. The mode can be either auto or manual. Setting the mode to
         * auto will make the camera look around automatically based on the mouse movement. Setting it
         * to manual will make the camera look around only when you click and drag.
         * @return
         *
         */
 
        public function get mode():String
        {
            return _mode
        }
        public function set mode(value:String):void
        {
            _mode = value;
            switch(_mode.toLowerCase())
            {
                case "manual" :
                stageReference.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
                stageReference.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
                break
               
                case "auto" :
                stageReference.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
                stageReference.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
                break
            }
        }
       
        /**
         * Sets or gets an object whith values that contraing the camera movement with bounds. The values are
         * "left", "right", "back" and "front"
         * @return
         *
         */
       
        public function get moveBounds():Object { return _moveBounds; }
        public function set moveBounds( value:Object ) { _moveBounds = value; }
       
        /*
        Handlers
        */

       
        private function handleKeyDown(evt:KeyboardEvent):void
        {
            switch(evt.keyCode)
            {
                case FirstPersonCamera3D.FORWARD_KEY:
                movingForward = true;
                break;
               
                case FirstPersonCamera3D.BACK_KEY:
                movingBack = true;
                break;
               
                case FirstPersonCamera3D.LEFT_KEY:
                movingLeft = true;
                break;
               
                case FirstPersonCamera3D.RIGHT_KEY:
                movingRight = true;
                break;
            }
            if(useBothSetsOfKeys){
                switch(evt.keyCode)
                {
                    case FirstPersonCamera3D.WASD.forward:
                    movingForward = true;
                    break;
                   
                    case FirstPersonCamera3D.WASD.back:
                    movingBack = true;
                    break;
                   
                    case FirstPersonCamera3D.WASD.left:
                    movingLeft = true;
                    break;
                   
                    case FirstPersonCamera3D.WASD.right:
                    movingRight = true;
                    break;
                }
            }
        }
       
        private function handleKeyUp(evt:KeyboardEvent):void
        {
            switch(evt.keyCode)
            {
                case FirstPersonCamera3D.FORWARD_KEY:
                movingForward = false;
                break;
               
                case FirstPersonCamera3D.BACK_KEY:
                movingBack = false;
                break;
               
                case FirstPersonCamera3D.LEFT_KEY:
                movingLeft = false;
                break;
               
                case FirstPersonCamera3D.RIGHT_KEY:
                movingRight = false;
                break;
            }
            if(useBothSetsOfKeys){
                switch(evt.keyCode)
                {
                    case FirstPersonCamera3D.WASD.forward:
                    movingForward = false;
                    break;
                   
                    case FirstPersonCamera3D.WASD.back:
                    movingBack = false;
                    break;
                   
                    case FirstPersonCamera3D.WASD.left:
                    movingLeft = false;
                    break;
                   
                    case FirstPersonCamera3D.WASD.right:
                    movingRight = false;
                    break;
                }
            }
        }
       
        private function handleMouseDown($event:MouseEvent):void
        {
            mouseDownPositionX = stageReference.mouseX;
            mouseDownPositionY = stageReference.mouseY;
            currentRotationY = rotationY;
            currentRotationX = rotationX;
            doManualLook = true;
        }
       
        private function handleMouseUp($event:MouseEvent):void
        {
            doManualLook = false;
        }
       
    }
}

[EDIT]

General setup :

firstPersonCamera = new FirstPersonCamera3D();
firstPersonCamera.initialize(viewport, .2, .2);
firstPersonCamera.y = 750;
firstPersonCamera.focus = 11;
firstPersonCamera.mode = "manual";
firstPersonCamera.moveBounds = {front:3500, back:-3500, left:-3500, right:3500};
firstPersonCamera.mapKeys(FirstPersonCamera3D.WASD_AND_ARROWS);
.
.
.
override protected function onRenderTick(event:Event=null):void
{
    firstPersonCamera.look(0.5);
    renderer.renderScene(scene, firstPersonCamera, viewport);
}

Experiment, Lab, papervision3d

Dragging objects in Papervision3D

December 26th, 2008

A few months ago, Andy Zupko added some methods to Papervision3D which facilitated the ability to drag objects in 3d space. I collected those methods and placed them in a static class called RayTracer. The class currently has only one method which returns a Number3D object with the coordinates in 3D space based on the position of your mouse on a Plane3D object.

Andy says:

In lay terms – this basically shoots a ray from the camera, through where the mouse is, into 3D space. You can then do whatever you want knowing where that ray is.

This is the code for the test above:

package
{
    import flash.events.Event;
   
    import org.papervision3d.core.math.Number3D;
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.objects.primitives.Sphere;
    import org.papervision3d.view.BasicView;

    public class Dragging3D extends BasicView
    {
       
        private var sphere:Sphere;
       
        public function Dragging3D()
        {
            initialize();
            createObjects();
            startRendering();
        }
       
        private function initialize():void
        {
            camera.zoom = 11;
            camera.focus = 100;
            camera.z = -2000;
            camera.y = 200;
        }
       
        private function createObjects():void
        {
            var plane:Plane = new Plane(new ColorMaterial(0x0FFFF00), 1000, 1000, 10, 10);
            plane.rotationX = 90;
            scene.addChild(plane);
           
            var wireMaterial:WireframeMaterial = new WireframeMaterial();
            sphere = new Sphere(wireMaterial, 50, 10, 10);
            sphere.useOwnContainer = true;
            sphere.y = 25;
            scene.addChild(sphere);
        }
       
        override protected function onRenderTick(event:Event = null):void
        {
            super.onRenderTick(event);
           
            var intersect:Number3D = RayTracer.getIntersection(viewport, camera, [0, 1, 0]);

            sphere.x = intersect.x;
            sphere.z = intersect.z;
        }
    }
}

The magic happens in the onRenderTick method. This is where we added the RayTracer static method. The first two arguments are self explanatory. The final argument is an array representing the “normal” on an imaginary plane:

[0, 1, 0] = XY plane = objects dragged on the x and z axises
[1, 0, 0] = YZ plane = objects dragged on the y and z axises
[0, 0, 1] = XZ plane = objects dragged on the x and y axises

This is the RayTracer class:

package
{
    import org.papervision3d.core.math.Number3D;
    import org.papervision3d.core.math.Plane3D;
    import org.papervision3d.core.proto.CameraObject3D;
    import org.papervision3d.view.Viewport3D;

    public class RayTracer
    {
       
        public static function getIntersection(viewport:Viewport3D, camera:CameraObject3D, normal:Array):Number3D
        {
            var plane3D:Plane3D = new Plane3D(new Number3D(normal[0], normal[1], normal[2]), new Number3D(0, 0, 0));
            var cameraPosition:Number3D = new Number3D(camera.x, camera.y, camera.z);
            var ray:Number3D = camera.unproject(viewport.containerSprite.mouseX, viewport.containerSprite.mouseY);
            ray = Number3D.add(ray, cameraPosition);
            var intersect:Number3D = plane3D.getIntersectionLineNumbers(cameraPosition, ray);
            return intersect;
        }
       
    }
}

Should be pretty simple to implement. Hit me back if you have any questions!

Experiment, Lab , ,

Exploring a Papervision3D class – Text3D

December 13th, 2008

Hi:

As some of you may know VectorVision (vector fonts in flash) was added into Papervision3D last week so I decided to check out the new typography package. To my surprise, it was fairly simple to set up. This is a small example.

package
{
    import flash.events.Event;
   
    import org.papervision3d.materials.special.Letter3DMaterial;
    import org.papervision3d.typography.Font3D;
    import org.papervision3d.typography.Text3D;
    import org.papervision3d.typography.fonts.HelveticaRoman;
    import org.papervision3d.view.BasicView;

    public class SampleText3D extends BasicView
    {
       
        private var text3D:Text3D;
        private var textMaterial:Letter3DMaterial;
        private var font3D:Font3D;
               
        public function SampleText3D()
        {
            initialize();
            startRendering();
        }
       
        private function initialize():void
        {
            textMaterial = new Letter3DMaterial(0x00FFFF);
            font3D = new HelveticaRoman();
            text3D = new Text3D("Hello there.", font3D, textMaterial);
            text3D.scale = 2;
            scene.addChild(text3D);
        }
       
        override protected function onRenderTick(event:Event = null):void
        {
            super.onRenderTick(event);
            text3D.yaw(0.5);
            text3D.roll(0.5);
        }
    }
}

Experiment, Lab ,

Exploring a Papervision3D class – MovieAssetParticleMaterial

December 12th, 2008
Comments Off

Hi All!

Not to long ago, I decided to go on a reconnaissance mission and plunged into the Papervison3D classes. I decided to read up on a class a week and just devour it ans learn as much about it as I could. I didn’t get the chance to do that until now. Here’s the first class : MovieAssetParticleMaterial and below is an example of what you can do with it.

The MovieAssetParticleMaterial is the material used for the Particle class which in turn is added to an instance of the Particles class using its “addParticle” method. I know that may have sounded a bit confusing, but here’s the break down. In the code for the example, I created 150 particles in a loop and add each particle to an array for later use:

for(var a:Number = 0; a<Particles3D.PARTICLE_COUNT; a++){
    var particleMaterial:MovieAssetParticleMaterial = new MovieAssetParticleMaterial("orb", true);
    particleMaterial.smooth = true;
   
    var particles3D:Particles = new Particles("particles_"+a);
    var particle:Particle = new Particle(particleMaterial, 2.5);
   
    particles3D.addParticle(particle);
    container3D.addChild(particles3D);
   
    arrParticles.push(particles3D);
}

After you have your particles set up, you would need some sort of 3D shape to map them to. Start off with something as simple as a sphere:

sphere = new Sphere(new WireframeMaterial(0x000000), 200, 15, 10);

Notice that all we did was create an instance of it, we really never added it to the scene. That’s because all we need is the vertice coordinates of the sphere in order to map the particles to them. We alreay have all our particles in an array, now we need to get all the vertices for the sphere in an array. Luckily, that is a very simple task:

var vertices:Array = sphere.geometry.vertices;

Now all we need to do is place a particle on each vertice by means of a loop and a little help from Tweener as so:

var vertices:Array = sphere.geometry.vertices;
activeVertices = vertices.length;
selectedShape = sphere;
for(var a:Number = 0; a<activeVertices; a++){
    Tweener.addTween(arrParticles[a], {x:vertices[a].x,
                           y:vertices[a].y,
                           z:vertices[a].z,
                           time:2,
                           transition:"easeInStrong"});
}

Thats pretty much it! I’m sure there’s loads of really cool stuff that can be done with 3D particles. Below is the full code for the example above. Enjoy!

package
{
    import caurina.transitions.Tweener;
   
    import flash.events.Event;
   
    import org.papervision3d.core.geom.Particles;
    import org.papervision3d.core.geom.renderables.Particle;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.materials.special.MovieAssetParticleMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.primitives.Cylinder;
    import org.papervision3d.objects.primitives.Sphere;
    import org.papervision3d.view.BasicView;

    public class Particles3D extends BasicView
    {
        private static const PARTICLE_COUNT:uint = 150;
        private var sphere:Sphere;
        private var cylinder:Cylinder;
        private var container3D:DisplayObject3D;
        private var selectedShape:DisplayObject3D;
        private var arrParticles:Array;
        private var activeVertices:Number;
       
        public function Particles3D()
        {
            super();
            createParticles();
            createObjects3D();
            mapParticlesToSphere();
            startRendering();
        }
       
        private function createParticles():void
        {
            container3D = new DisplayObject3D();
            arrParticles = [];
           
            for(var a:Number = 0; a<Particles3D.PARTICLE_COUNT; a++){
                var particleMaterial:MovieAssetParticleMaterial = new MovieAssetParticleMaterial("orb", true);
                particleMaterial.smooth = true;
               
                var particles3D:Particles = new Particles("particles_"+a);
                var particle:Particle = new Particle(particleMaterial, 2.5);
               
                particles3D.addParticle(particle);
                container3D.addChild(particles3D);
               
                arrParticles.push(particles3D);
            }
           
            scene.addChild(container3D);
        }
       
        private function createObjects3D():void
        {
            sphere = new Sphere(new WireframeMaterial(0x000000), 200, 15, 10);
            cylinder = new Cylinder(new WireframeMaterial(0x000000), 60, 840, 10, 10);
        }
       
        private function mapParticlesToSphere():void
        {
            var vertices:Array = sphere.geometry.vertices;
            activeVertices = vertices.length;
            selectedShape = sphere;
            for(var a:Number = 0; a<activeVertices; a++){
                Tweener.addTween(arrParticles[a], {x:vertices[a].x,
                                                   y:vertices[a].y,
                                                   z:vertices[a].z,
                                                   time:2,
                                                   transition:"easeInStrong"});
            }
            Tweener.addTween(arrParticles[a], {time:4, onComplete:mapParticlesToCylinder});
        }
       
        private function mapParticlesToCylinder():void
        {
            var vertices:Array = cylinder.geometry.vertices;
            activeVertices = vertices.length;
            selectedShape = cylinder
            for(var a:Number = 0; a<activeVertices; a++){
                Tweener.addTween(arrParticles[a], {x:vertices[a].x,
                                                   y:vertices[a].y,
                                                   z:vertices[a].z,
                                                   time:2,
                                                   transition:"easeInStrong"});
            }
            Tweener.addTween(arrParticles[a], {time:4, onComplete:mapParticlesToSphere});
        }
       
        private function hideUnusedParticles():void
        {
            for (var a:Number = 0; a < Particles3D.PARTICLE_COUNT; a++) {
                if (a < selectedShape.geometry.vertices.length) {
                    arrParticles[a].visible = true;
                } else {
                    arrParticles[a].visible = false;
                }
            }
        }
       
        override protected function onRenderTick(event:Event=null):void
        {
            super.onRenderTick(event);
            container3D.yaw(.5);
            container3D.roll(.5);
            hideUnusedParticles();
        }      
       
    }
}
;

Experiment, Lab , ,