Papervision3d Sprite3D ( small modification )

Working on a small project in Papervision 3D I found myself in need of a way to have a 3d object that always faces the camera. That’s when I came across Paul Tondeur’s Sprite3D class ( which works great ).

After playing with that class I realized I dont need some of it’s features like loading lots of images and calculating the angle and showing the right image so it gives a 3d impression.

So I’ve made a slight change to this class to have only one image ( also saving some size )

Here’s the code:

package {
/** papervision classes **/
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.render.data.RenderSessionData;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Plane;

/**
* creates a plane which is always in front of the camera.
*
* @based on  Paul Tondeur's Sprite3D
*/
public class Sprite3D extends DisplayObject3D
{
private var _plane:Plane = null;		// plane object
private var _material: BitmapMaterial = null;	// texture
private var _firstProject:Boolean = true;	// first time projected
private var toDEGREES :Number = 180/Math.PI;	// degrees

/**
* Create a new Sprite3D object
*
* @param	material	A BitmapMaterial
* @param 	width		Optional width of Sprite3D
* @param	height	        Optional height of Sprite3D
*/

public function Sprite3D(material:BitmapMaterial, width:Number = 250, height:Number = 250)
{
super();
_material = material;
_plane = new Plane(_material, width, height );
addChild(_plane);
}

public override function project( parent : DisplayObject3D,  renderSessionData:RenderSessionData ):Number
{
/**
* First time the sprite3d is projected, it needs to project _plane as well.
* If not, we won't see anything happen as soon as we adjust it's matrix.
* This only accurs the first time and seems like a pv3d bug			 */

if( this._firstProject )
{
_plane.project(this, renderSessionData);
this._firstProject = false;
}

/** Update transformation matrix, when dirty transformations are used */
if( this._transformDirty ) 	updateTransform();
/**	Get rotation matrix of this object and calculate rotation values*/
var m:Matrix3D = this.transform;
var rotation:Number3D = new Number3D();
rotation.x = Math.atan2(-m.n23 , m.n22) * toDEGREES;
rotation.y = Math.atan2(-m.n31 , m.n33) * toDEGREES;
rotation.z = Math.atan2(-m.n12 , m.n22) * toDEGREES;
/** Correct _plane and keep it always in front of the camera */
m = new Matrix3D();
m = m.copy3x3( this.transform );
_plane.transform.calculateInverse( m );
_plane.transform = Matrix3D.multiply3x3( _plane.transform , renderSessionData.camera.transform );
return super.project(parent,renderSessionData);
}

/**
* Returns a DispayObject3D
*/
public function get object3D():DisplayObject3D
{
return this._plane;
}

/**
* Returns the material of the object
*/
public function get mat():BitmapMaterial
{
return this._material;
}
}}
Advertisements

6 thoughts on “Papervision3d Sprite3D ( small modification )

  1. Hi

    thanks for this code, im trying to use it for one of my projects, but with no success. I have a canvas full with sprites at random 3D positions, and i rotate this canvas. What i cant figure out, how to make all sprites face the camera. Heres my example code:

    package{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;

    public class test extends Sprite{

    var canvas:Sprite = new Sprite();
    var sprites:Array = []

    public function test(){
    addChild(canvas)
    for (var i:int=0;i<20;i++){
    var sp:Sprite = new Sprite();
    canvas.addChild(sp);
    sp.graphics.beginFill(0xFF0000);
    sp.graphics.drawCircle(0,0,4);
    sp.x = Math.random()*400-200;
    sp.y = Math.random()*400-200;
    sp.z = Math.random()*400-200;
    sprites.push(sp);
    }
    addEventListener(Event.ENTER_FRAME,function():void{
    canvas.rotationX++;
    canvas.rotationY = canvas.rotationY+Math.random()*2;
    canvas.rotationZ++;
    for (var i:int=0;i<20;i++){
    var s:Sprite = sprites[i];
    //method 1: invert rotations: (not working)
    s.rotationX = -canvas.rotationX;
    s.rotationY = -canvas.rotationY;
    s.rotationZ = -canvas.rotationZ;
    // method 2: multiply by inverse rotation matrix (even worse results)
    /*var trVec:Vector. = canvas.transform.matrix3D.decompose();
    trVec[0] = new Vector3D(1,1,1,1); //translation
    trVec[1] = new Vector3D(0,0,0,0); //rotation
    trVec[2] = new Vector3D(1,1,1,1); //scale
    var invMatrix:Matrix3D = new Matrix3D();
    invMatrix.recompose(trVec);
    invMatrix.invert(); //invert translation matrix
    s.transform.matrix3D.prepend(invMatrix); //multiply the transform matrix by invMatrix
    */
    }
    })
    }
    }
    }

    Do you know what im doing wrong?
    Thanks

  2. > Sprite3D works only with Papervision3D.

    Yeah, i know this. I am trying to make billboard sprites without Papervision, because i dont need 99% of the features of it. I only need the algorithm to make objects always face the camera.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s