Matrix3D bug? or me confused?

I assume the latter…

Anyway, trying to wrap my head around AS3’s Matrix3d class. In particular, the pointAt method. This supposedly, “Rotates the display object so that it faces a specified position.”

Here’s the class I’m using for testing:

[as]package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Vector3D;

[SWF(width=800, height=800)]
public class MatrixStuff extends Sprite
{
[Embed (source=”Compass.jpg”)]
private var Compass:Class;

private var sprite:Sprite;

public function MatrixStuff()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

var compass:Bitmap = new Compass();
compass.x = -compass.width / 2;
compass.y = -compass.height / 2;
sprite = new Sprite();
sprite.addChild(compass);
sprite.x = 400;
sprite.y = 400;
sprite.z = 100;
addChild(sprite);

addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function onEnterFrame(event:Event):void
{
sprite.transform.matrix3D.pointAt(new Vector3D(mouseX, mouseY, 0));
}
}
}[/as]

This should make the image “face” the mouse. Here’s the result:

[kml_flashembed publishmethod=”static” fversion=”8.0.0″ movie=”http://www.bit-101.com/blog/wp-content/uploads/2009/08/MatrixStuff.swf” width=”800″ height=”800″ targetclass=”flashmovie”]

Get Adobe Flash player

[/kml_flashembed]

As you can see, the bottom of the object is pointing at the mouse, rather than the front of the object. Per the documentation, this is controlled by the “at” parameter:

at:Vector3D (default = null) รขโ‚ฌโ€ The object-relative vector that defines where the display object is pointing. Object-relative defines the object’s transformation relative to the object space, the object’s own frame of reference and coordinate system. Default value is the -z axis (0,0,-1).

But this looks like it’s using a (0, 1, 0) vector. In fact, we can test this by passing in such a vector to the second parameter:

[as]sprite.transform.matrix3D.pointAt(new Vector3D(mouseX, mouseY, 0), new Vector3D(0, 1, 0));[/as]

Lo and behold, exact same behavior. Also, notice that it’s flipped on the y-axis. Not sure about that.

In fact, by using (0, -1, 0) I can get the “north” point to point at the mouse, and by using (1, 0, 0) and (-1, 0, 0), I can get the east and west points to point at the mouse. So far so good. Now, the documentation says the default is (0, 0, -1), so I try that, and the whole thing breaks. Doesn’t rotate at all. Same with (0, 0, 1).

Anyone else able to see this behavior? Anything I’m doing obviously wrong?

This entry was posted in ActionScript, Flash. Bookmark the permalink.

7 Responses to Matrix3D bug? or me confused?

  1. kp says:

    After some more messing about, I found that while (0, 0, -1) did not work, putting an even small value in one of the other axes makes it work:

    sprite.transform.matrix3D.pointAt(new Vector3D(mouseX, mouseY, 0), new Vector3D(0, .00001, -1));

    This seems to point in the direction of a bug in the method. some kind of divide by zero error? Or do I need to put something in the w parameter. Oh no. Vector3D’s w is the second most scary w in the world.

    Anyway, it’s still flipped upside down or backwards. Resetting the “up” parameter to its supposed default fixes that:

    sprite.transform.matrix3D.pointAt(new Vector3D(mouseX, mouseY, 0), new Vector3D(0, .00001, -1), new Vector3D(0, -1, 0));

    This works exactly like I expected it to in the beginning. Not sure what’s wrong though.

  2. kp says:

    huh. what do you know. If I set both optional params to their supposed defaults, it works fine too!

    sprite.transform.matrix3D.pointAt(new Vector3D(mouseX, mouseY, 0), new Vector3D(0, 0, -1), new Vector3D(0, -1, 0));

    I think i’m all set. chalking this one up to a bug.

  3. zproxy says:

    Hey, I am letting you know that I have just ported your example to C# ๐Ÿ™‚

    http://zproxy.wordpress.com/2009/08/13/example-matrixstuffexample/

  4. I also saw some strange behaviour with pointAt() .. I had better luck with Utils3D.pointTowards()
    http://www.dafishinsea.com/blog/2008/11/09/pointing-at-something-in-3d/
    According to Chris Nuuja this is due to the way I was deriving the matrix3D however, so I tried it another way:
    http://www.dafishinsea.com/blog/2008/11/26/swimming-with-the-fishes/
    (relevant code is here :http://dafishinsea.com/svn/trunk/FishSwim.as)
    This time pointAt() worked, but I was supplying all the parameters, so I guess you need to do that.

  5. wic says:

    I may be confused here, but coming from an opengl background, I’d think that your mouseX/mouseY needs should be changed to match the x/y coords in the object space. That is, I’m thinking that mouse coords are using (0,0) based the top-left and maybe the 3d world is using coordinates that is from bottom-right, ie y+ if pointing up the screen. So you may need to convert them (the mouseY at least). At least I dont understand how matrix3D.pointAt could know how your mouse coords are represented. Just a thought.

    • kp says:

      wic, everything in flash is top left origina, as far as i know. anyway, this works fine as long as you supply all the parameters, even though the last two are supposed to be optional.

  6. Promethe says:

    I noticed this weird behavior to but I did not spend much time on it.
    I used the pointAt method for the Billboard class of DirectFlex (http://directflex.net).

    It is not yet fully usable, but it does the main job done: the sprite always points at the camera.

    Always keep in mind that in Flash, the world-space Y axis is upside-down compared to the usual left handed coordinates system. I chose to use ‘classic’ left/right handed coordinates systems and convert to Flash coordinates with the projection transform.

Leave a Reply