Matrix3D bug? or me confused?
Wednesday 12 August 2009 - Filed under ActionScript + Flash
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:
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?
2009-08-12 » keith
12 August 2009 @ 8:33 pm
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.
12 August 2009 @ 8:36 pm
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.
13 August 2009 @ 3:07 am
[...] Example: MatrixStuffExample Filed under: examples, jsc — Tags: matrix — zproxy @ 7:07 am I have ported an actionscript Matrix3D example from Bit-101 blog to C#. [...]
13 August 2009 @ 3:17 am
Hey, I am letting you know that I have just ported your example to C#
http://zproxy.wordpress.com/2009/08/13/example-matrixstuffexample/
13 August 2009 @ 8:17 am
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.
13 August 2009 @ 8:30 am
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.
13 August 2009 @ 9:04 am
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.
17 August 2009 @ 5:11 pm
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.