views:

447

answers:

3

I have an 2D image that I want to draw in true 3D, and spin around its centre.

I'm using Actionscript 3 code (actually Haxe, no IDE), and I'm struggling to discover the values by experimentation.

I have a DisplayObject. If I use rotateZ = 45, the object rotates around it's top-left, rather than centre; more complicated Display.transform.matrix things like rotate(Math.PI/4) work the same way. How can I rotate on the Z axis around the DisplayObject's XY centre?

And how do I then get the perspective to work? Is the perspective relative to the parent, or the object after rotation?

What rotation and position do I use on the DisplayObject instance? What are the values for the perspective transform, and on what object do I apply them?

A: 

you can change the perspective with rotationX, rotationY, rotationZ object properties, but its only working in flashplayer > 9, if you wonna have more control i suggest you to use papervision3d library (e.g. camera fov, zoom ect.).

antpaw
yes, but what would the values be? Do I have to set them in specific order, e.g. set the perspective transform to the scene before adding the bitmap, or?
Will
A: 

Hi Will,

I'm slightly confused by your question, but it's an interesting one nevertheless.

Do you have something isometric working and want to render a perspective projected view or the other way around ? You have a perspective view and want to go isometric ?

In the Flash CS4 IDE you can play with a '3D' few parameters. I've assembled a bunch of MovieClips into a cube to illustrate the point.

Here is the cube, rotate at 45 degrees on Y, then at 45 degrees on X as you can see in the Transform Panel:

flash perspective

Here is the same cube, with the Perspective Angle changed in the 3D Position And View group in the Property Inspector on the right.

flash isometric

The property in the IDE can be controlled through actionscript. Each DisplayObject has a transform property which holds references for objects controlling the 2D and 3D properties like: Matrix, Matrix3D, PerspectiveProjection and others.

You can control the perspective distortion through the fieldOfView property of PerspectiveProjection.

Assuming the box clip is named box, I could set it's fieldOfView to something really small ( as your allowed values larger than 0 and smaller than 180 only ) and that would be it.

e.g.

var isometric:PerspectiveProjection = new PerspectiveProjection();
isometric.fieldOfView = 0.00001;
box.transform.perspectiveProjection = isometric;

For orbiting, check out this article on devnet. It explains an approach to orbiting as well. Depending on what you're trying to achieve, it might Ralph Hauwert's Arcball article.

Here are a few as3 isometric libraries out there like FFilmation and as3isolib, but I'm not sure what you need exactly. As antpaw was saying, if you're working on something bigger, you might use the flexibility 3D APIs like Papervision or Away3D.

At disturb we made fun isometric interface for visualizing tweets called Twigital. We used papervision for that.

UPDATE

It seems you need to rotate around a pivot dynamically. You can do that using the transform matrix. Here is how you do it in 2D:

/**
     * Rotates a matrix about a point defined inside the matrix's transformation space.
     * This can be used to rotate a movie clip around a transformation point inside itself. 
     *
     * @param m A Matrix instance.
     *
     * @param x The x coordinate of the point.
     *
     * @param y The y coordinate of the point.
     *
     * @param angleDegrees The angle of rotation in degrees.
     * @playerversion Flash 9.0.28.0
     * @langversion 3.0
     * @keyword Matrix, Copy Motion as ActionScript    
     * @see flash.geom.Matrix         
     */
    public static function rotateAroundInternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
    {
     var point:Point = new Point(x, y);
     point = m.transformPoint(point);
     m.tx -= point.x;
     m.ty -= point.y;
     m.rotate(angleDegrees*(Math.PI/180));
     m.tx += point.x;
     m.ty += point.y;
    }



    /**
     * Rotates a matrix about a point defined outside the matrix's transformation space.
     * This can be used to rotate a movie clip around a transformation point in its parent. 
     *
     * @param m A Matrix instance.
     *
     * @param x The x coordinate of the point.
     *
     * @param y The y coordinate of the point.
     *
     * @param angleDegrees The angle of rotation in degrees.
     * @playerversion Flash 9.0.28.0
     * @langversion 3.0
     * @keyword Matrix, Copy Motion as ActionScript    
     * @see flash.geom.Matrix       
     */
    public static function rotateAroundExternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void
    {
     m.tx -= x;
     m.ty -= y;
     m.rotate(angleDegrees*(Math.PI/180));
     m.tx += x;
     m.ty += y;
    }

The code's not mine though, it's Adobe's ( Robert Penner's I'm guessing ), part of the MatrixTransformer class.

Now, for 3D, it's even easier, because the Matrix3D class has rotation methods like prependRotation and appendRotation, that accept 3 parameters:

  • degrees:Number
  • axis:Vector3D
  • pivotPoint:Vector3D

So you can easily rotate a box 30 degrees on the X axis about 0,0,0 with something like:

var m:Matrix3D = box.transform.matrix3D;
m.prependRotation(30,Vector3D.X_AXIS,new Vector3D(0,0,0));

Again, check out the devnet articles, the Matrix3D class and the Vector3D class.

If you want to get more in depth knowledge about Vectors, Matrices and Transformations, you can check out 3D Math Primer, the whole thing is really well explained, and it's just math, so the things you learn are handy in any 3d setup ( pure as3, away3d, papervision, openGL, etc. ).

HTH, George

George Profenza
thank you George; I've tried to rephrase my question slightly to steer away from isometry.
Will
I have revised my answer as well, as you can see in the UPDATE. Goodluck!
George Profenza
+3  A: 

A very common approach is to have a pivot DisplayObjectContainer, add your actual plane into that container, and offset it from the center. Then you actually rotate the container.

var pivot : DisplayObjectContainer;

// plane is a display object (e.g. Sprite) that has been created previuosly
// and contains your 2D image.
plane.x = -plane.width/2;
plane.y = -plane.height/2;
pivot.addChild(plane);

pivot.rotationY = 45;

Here, the plane is put inside the container named pivot, and offset by half it's width and height. This means that the center of the plane display object will be aligned with the registration point (origin) of the container. Rotating the container (pivot) around the origin now will rotate all of it's children, including the plane, around that same point.

This is usually easier to work with than matrix transformations. Especially as 3D matrices can easily get hard to follow, unless you're readily familiar with the math.

Besides, just modifying the plane.transform.matrix3D matrix object will not affect the display object, until you reset the matrix. This can be very tedious if you're using a tween engine for example, where you might need to have an UPDATE event handler that resets the matrix each time, like so:

plane.transform.matrix3D = myModifiedMatrix3D;

Using the pivot approach, you can simply tween the rotationX/Y/Z properties.

richardolsson
This is the most straightforward way. Confirmed, works for me and simplified my code greatly.
Will