Email Updates RSS Subscribe
Line

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.

Launch
Line

Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit www.byhook.com.

Line

Gradually rotate toward a point in 3D with Flash Player 9

Line
Posted on January 15th, 2010 by Norm McGarry
Line

Have you ever looked at yourself in the mirror and said that Flash Player 9′s 3D options are just as great as those available in Flash Player 10? No. That’s because you would never do that. Never.

In the world of Flash Player 9, you aren’t given too many 3D options. Papervision and Away3D. Those two seem to be the most stable and full-featured. How do you rotate an object to a particular rotation over time? When integrated with a physics engine (I was using JigLib), this isn’t so simple. Both engines have a great lookAt() method that will rotate your object in a particular direction, however I wanted to do this gradually, not instantaneously.

Flash 10 has a great utility class called Utils3D. This class has a method called pointTowards that is absolutely fantastic. All methods are native to flash, which means they are built into the compiler and are extremely efficient. The pointTowards method accepts arguments of percent (the percentage to move), mat (the Matrix3D to manipulate), and pos  (the Vector3D to point towards). There are additional options, but this is all I needed.

The physics engine of JigLib would throw around the objects, so they would be at a random rotation, and I wanted to point them straight up. With Flash Player 10, I just passed in the orientation matrix of the RigidBody, gave it a Vector3D of new Vector3D(0,1,0) so it would land face up. And I wanted to move it 15% every frame. This gave it a gradual motion and looked extremely natural.

Here comes Flash 9 to ruin the day. What are my options? I searched the internet long and hard and found close to nothing that mimicked this exact functionality. It seemed to me like it had to have been done elsewhere. After reading way too much math on rotation matrices and quaternions, and through a conversation with Brad, I realized it was much easier than it sounded. This is what I ended up coming up with:

a = a + (b - a)p

I knew the ideal rotation of being face up was simply rotationX=0, rotationY=0 and rotationZ=0. After trying to do this equation with a Matrix3D, I realized there was an easier way!

I simply added a method to the RigidBody class in JigLib called rotateTo that gradually moved into this position.

        	/**
         	* Rotates the 3d object a percentage towards an ideal rotation
    	 	*
    	 	* @param	ax		The angle in degrees of the rotation around the x axis.
    	 	* @param	ay		The angle in degrees of the rotation around the y axis.
    	 	* @param	az		The angle in degrees of the rotation around the z axis.
    	 	* @param	percent		The percent to move.
    	 	*/
		public function rotateTo(ax:Number, ay:Number, az:Number, percent:Number = 1):void
		{
			var rotateX:Number = _rotationX + (degreesToRadians(ax) - _rotationX) * percent;
			var rotateY:Number = _rotationY + (degreesToRadians(ay) - _rotationY) * percent;
			var rotateZ:Number = _rotationZ + (degreesToRadians(az) - _rotationZ) * percent;
 
			_rotationX = rotateX;
			_rotationY = rotateY;
			_rotationZ = rotateZ;
 
			setOrientation(createRotationMatrix());
		}

Oh, so simple! The method simply takes the rotationX, rotationY and rotationZ and finds the percentage of the difference compared to the ideal values passed in, which we then increment by this difference. And we’re done! We then use the built in method in JigLib’s RigidBody class called createOrientationMatrix() to convert the values into the correct rotation matrix. In retrospect, I laugh at the simplicity. A little lesson in KISS (Keep It Simple Stupid).

Line
1 Response to “Gradually rotate toward a point in 3D with Flash Player 9”
  1. Hi,

    I’m really appreciating the you’ve shared this snippet! Thanks!
    It’s challenging to work with Papervision3D + Jiglib, but both of them are great initiatives.
    I’ve created an external helper class, so it should work directly with the trunk svn version (without modifying the RigidBody. class):

    package jiglib.thirdparty
    {
    import jiglib.physics.RigidBody;
    import jiglib.math.JMatrix3D;
    /**
    * @author Norm McGarry (http://labs.byhook.com/2010/01/15/gradually-rotate-by-a-percentage-in-player-flash-9/)
    * @author Andras Csizmadia (additional changes)
    */
    public class JiglibHelper
    {
    public function JiglibHelper()
    {
    super();
    }

    /**
    * Rotates the 3d object a percentage towards an ideal rotation
    *
    * @param ax The angle in degrees of the rotation around the x axis.
    * @param ay The angle in degrees of the rotation around the y axis.
    * @param az The angle in degrees of the rotation around the z axis.
    * @param percent The percent to move.
    */
    public static function rotateTo(target:RigidBody, ax:Number, ay:Number, az:Number, percent:Number = 1):void
    {
    var rotateX:Number = target.rotationX + (degreesToRadians(ax) – target.rotationX) * percent;
    var rotateY:Number = target.rotationY + (degreesToRadians(ay) – target.rotationY) * percent;
    var rotateZ:Number = target.rotationZ + (degreesToRadians(az) – target.rotationZ) * percent;

    target.rotationX = rotateX;
    target.rotationY = rotateY;
    target.rotationZ = rotateZ;

    target.setOrientation(createRotationMatrix(target));
    }

    public static function createRotationMatrix(target:RigidBody):JMatrix3D
    {
    var rx:JMatrix3D = JMatrix3D.rotationX(target.rotationX);
    var ry:JMatrix3D = JMatrix3D.rotationY(target.rotationY);
    var rz:JMatrix3D = JMatrix3D.rotationZ(target.rotationZ);
    var um:JMatrix3D = JMatrix3D.multiply(rx, ry);
    um = JMatrix3D.multiply(um, rz);
    return um;
    }

    public static function radiansToDegrees(rad:Number):Number
    {
    return rad * 180/Math.PI;
    }

    public static function degreesToRadians(deg:Number):Number
    {
    return deg * Math.PI/180;
    }

    }
    }


Leave a Reply

*

Line
Line
Pony