Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411665 Posts in 69396 Topics- by 58452 Members - Latest Member: Monkey Nuts

May 16, 2024, 06:38:42 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Matrix3D Question
Pages: [1]
Print
Author Topic: Matrix3D Question  (Read 2295 times)
bateleur
Level 10
*****



View Profile
« on: February 11, 2010, 02:32:06 PM »

I've been messing around with 3D in Flash for an ongoing project and have run into something which is puzzling me. It occurs to me that this is so fundamental that probably I just have The Stupid and hopefully someone can point out why I am confused.

I have some code that looks like this:

Code:
function (matrixA:Matrix3D,matrixB:Matrix3D) {
 trace("MatrixA:");
 matrixDump(matrixA);
 trace("MatrixB:");
 matrixDump(matrixB);
 matrixA.append(matrixB);
 trace("MatrixOut:");
 matrixDump(matrixA);
}

...and running it with a couple of matrices I have lying around produces this output:

Code:
MatrixA:
     1 0 0 0
     0 1 0 0
     0 0 1 0
     -4096 4096 2048 1
MatrixB:
     100 0 0 0
     0 98.5 -0.125 -0.125
     0 17.375 1 1
     0 0 100 2000
MatrixOut:
     100 0 0 0
     0 98.5 -0.125 -0.125
     0 17.375 1 1
     -409600 438940.5 1405.625 28112.5

Which makes complete sense to me right up to that last "28112.5".

Isn't "append" just matrix multiplication? The other 15 numbers look right for that. And if so, shouldn't that last number be 3536? And if not (to either question) why not?

I would just shrug and say "Ho hum, never mind, the 3D all works so never mind the maths". Except the trouble is the 3D doesn't all work. Something is messing up my transformations and... well... I need to understand what's going on here!

Many thanks for any assistance!  Gentleman
Logged

Zaphos
Guest
« Reply #1 on: February 11, 2010, 03:12:49 PM »

The 1405 also looks wrong ...

Um, that's really weird; maybe write your own matmult function?  Googling around I see other people saying flash's Matrix3D is somehow completely screwed up -- http://www.actionscript.org/forums/showthread.php3?t=189950

edit: I tried the transpose example from that thread, and it does arbitrarily multiply and divide by 20 when doing a matrix transpose ... what the hell flash, how do you even get that bug?
« Last Edit: February 11, 2010, 03:21:33 PM by Zaphos » Logged
bateleur
Level 10
*****



View Profile
« Reply #2 on: February 12, 2010, 12:50:28 AM »

Thanks! I was worried I was completely losing it...

But also: Aarrrgh! That is a really inconvenient bug! Cry
Logged

grapefrukt
Level 1
*



View Profile WWW
« Reply #3 on: February 12, 2010, 01:22:26 AM »

i extremely rarely use the Matrix3D class, but I've heard about a few nasty bugs in it too. If you can't be bothered to write your own I'd suggest snatching the one from away3d http://www.google.com/codesearch?q=Matrix3D+package:http://away3d\.googlecode\.com&origq=Matrix3D&btnG=Search+Trunk
Logged
bateleur
Level 10
*****



View Profile
« Reply #4 on: February 12, 2010, 02:24:46 AM »

The irony is I'm using Away3D Lite as my 3D engine... and it walks right into the Adobe Matrix3D bug. Screamy

But thanks for the link. Ultimately I'm unlikely to switch away from Adobe's class for efficiency reasons. I need to end up with an Adobe Matrix3D for Utils3D.projectVectors and I'd rather not be copying properties across for every Mesh every frame.

Instead I'm going to hack a detect-and-fix-bug-on-the-fly function into Away3D Lite. Should only be a few lines.
Logged

westquote
Level 0
**


I make games in Philly. How rare!


View Profile WWW
« Reply #5 on: February 12, 2010, 08:05:13 PM »

edit: I tried the transpose example from that thread, and it does arbitrarily multiply and divide by 20 when doing a matrix transpose ... what the hell flash, how do you even get that bug?

This is just intuition, but I wonder if the arbitrary 20x is something very strange related to their internal twips unit (1 point = 1/72 inch = 20 twips)?

Also, what are those matrices supposed to be in the OP?  The first looks like a straightforward translation, and the second looks more like a projection matrix.  What are you trying to do?
Logged

Twitter: @westquote - Webpage: Final Form Games
Zaphos
Guest
« Reply #6 on: February 12, 2010, 08:44:23 PM »

The first looks like the transpose of a translation, rather ...
Logged
Glaiel-Gamer
Guest
« Reply #7 on: February 12, 2010, 09:48:14 PM »

When in doubt, livedocs

http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Matrix3D.html

"The first time the append() method is called, it makes a modification relative to the parent space. Subsequent calls are relative to the frame of reference of the appended Matrix3D object."

Note: internally (in the swf file at least), flash stores positions as "Twips" which are 1/20th of a pixel, so this might have something to do with it
Logged
westquote
Level 0
**


I make games in Philly. How rare!


View Profile WWW
« Reply #8 on: February 12, 2010, 10:45:07 PM »

The first looks like the transpose of a translation, rather ...

Ah, I was assuming row vectors, which is what I use in my code (though it tends not to line up with academic writing and math papers).

As for the append(): if the native coordinate space is twips (which is seems that they are), and your authoring coordinate space is pixels, then you are authoring your matrices as local-to-pixel transforms.  Thus, it makes some sense that it composes your first local-to-pixel matrix with a pixel-to-twips transform, which results in a local-to-twips transform.  Everything from that point on chains one local space to another (localA-to-localB), factoring out any need for further incorporation of twips calculations.

I don't have a seat of flash that I can verify this with, but I suspect that they intended for you to throw these matrices into an opaque system that expects data (vertices?) in a user coordinate system, with an accompanying user-to-twips transform.  Does this make sense to those more familiar with the system?
Logged

Twitter: @westquote - Webpage: Final Form Games
Zaphos
Guest
« Reply #9 on: February 13, 2010, 12:23:49 AM »

I loaded up flash again and I can't replicate the behavior anymore ... flash did update itself last time I opened it, so maybe the issue was actually fixed?  I don't think the transpose thing could have been anything but a bug; it directly contradicted the livedocs, and it doesn't seem to be happening anymore?  I tried replicating bateleur's case as well and it also seems to work correctly now.


Code:
var m:Matrix3D = new Matrix3D(Vector.<Number>(
        [1, 2, 3, 4,
         5, 6, 7, 8,
         9, 10,11,12,
         13,14,15,16]));
m.transpose();
trace(m.rawData);

var m1:Matrix3D = new Matrix3D();
var m2:Matrix3D = new Matrix3D();
var v1:Vector.<Number>=Vector.<Number>(
        [1, 0, 0, -4096,
         0, 1, 0, 4096,
         0, 0, 1, 2048,
         0, 0, 0, 1]
        );
var v2:Vector.<Number>=Vector.<Number>(
        [100, 0, 0, 0,
         0, 98.5, 17.375, 0,
         0, -.125, 1, 100,
         0, -.125, 1, 2000]
        );


m1.rawData = v1;
m2.rawData = v2;

trace(m1.rawData);
trace(m2.rawData);

m2.append(m1)

trace(m2.rawData);

now outputs:
Code:
1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16
1,0,0,-4096,0,1,0,4096,0,0,1,2048,0,0,0,1
100,0,0,0,0,98.5,17.375,0,0,-0.125,1,100,0,-0.125,1,2000
100,0,0,-409600,0,98.5,17.375,439040,0,-0.125,1,1636,0,-0.125,1,3536
... which looks correct?  (trusting the Joe ... Ward comment that rawData is stored column by column)

edit: oh wait, to match bateleur's I should be doing m1.append(m2) ... um, I think bateleur's matrices might be transposed in that case.  But if I do permute things around, still, flash seems to be doing things sane-ly now.
« Last Edit: February 13, 2010, 12:35:31 AM by Zaphos » Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #10 on: February 13, 2010, 02:09:20 AM »

You are treating matrix3d as if it were a 4x4 matrix. But I don't think that is the intention. It only represents 3x3 matrices with +ve determinant plus a translation, is the impression I got from the docs. I cannot think why, but perhaps it breaks in other cases. The fact that the bottom row of the matrix is accessible, despite the fact it should always be (0,0,0,1), is probably an artefact of where the matrices are used in for projections. That row is, for all intents and purposes, private, so it seems legit for Adobe to shove scale factors or what have you in there.
Logged
bateleur
Level 10
*****



View Profile
« Reply #11 on: February 13, 2010, 09:48:03 AM »

Also, what are those matrices supposed to be in the OP?  The first looks like a straightforward translation, and the second looks more like a projection matrix.  What are you trying to do?

Internally to Away3D Lite, operations like this are carried out to produce projection matrices. Their assumption (not mine) is that a sequence like A.B.C.P where A, B and C are 3D transforms and P is a projection matrix result in a projection matrix such that:

(((v.A).B).C).P = v.(A.B.C.P)

Of course, if Matrix3D is just a straight 4x4 matrix then this identity holds by associativity of matrix multiplication.

As Boris points out, the docs do not guarantee that these things behave like 4x4 matrices... but clearly they do in practice.

And yes, the most recent version of Flash player fixes the bug... which doesn't help me since I cannot assume everyone has it. Fortunately it turned out to be very easy to hack round once I knew it was there.
Logged

Zaphos
Guest
« Reply #12 on: February 13, 2010, 11:35:22 AM »

And yes, the most recent version of Flash player fixes the bug... which doesn't help me since I cannot assume everyone has it. Fortunately it turned out to be very easy to hack round once I knew it was there.
Could you post your workaround function?  It might help future confused people out Smiley
Logged
bateleur
Level 10
*****



View Profile
« Reply #13 on: February 13, 2010, 12:39:27 PM »

Sure. The detection code is app-specific, so no use to anyone (it just involves checking whether two points which should be on top of each other despite being projected via different matrices have become separated). The alternate append code looks like this:

Code:
package uk.co.fastram.lib {

 import flash.geom.Matrix3D;

public class MatrixTools {

 public static function append(mtx1:Matrix3D,mtx2:Matrix3D) {
  var raw1:Vector.<Number> = mtx1.rawData;
  var raw2:Vector.<Number> = mtx2.rawData;
  var result:Vector.<Number> = new Vector.<Number>(16,true);

  result[0]  = raw1[0]*raw2[0]  + raw1[1]*raw2[4]  + raw1[2]*raw2[8]  + raw1[3]*raw2[12];
  result[1]  = raw1[0]*raw2[1]  + raw1[1]*raw2[5]  + raw1[2]*raw2[9]  + raw1[3]*raw2[13];
  result[2]  = raw1[0]*raw2[2]  + raw1[1]*raw2[6]  + raw1[2]*raw2[10]  + raw1[3]*raw2[14];
  result[3]  = raw1[0]*raw2[3]  + raw1[1]*raw2[7]  + raw1[2]*raw2[11]  + raw1[3]*raw2[15];

  result[4]  = raw1[4]*raw2[0]  + raw1[5]*raw2[4]  + raw1[6]*raw2[8]  + raw1[7]*raw2[12];
  result[5]  = raw1[4]*raw2[1]  + raw1[5]*raw2[5]  + raw1[6]*raw2[9]  + raw1[7]*raw2[13];
  result[6]  = raw1[4]*raw2[2]  + raw1[5]*raw2[6]  + raw1[6]*raw2[10]  + raw1[7]*raw2[14];
  result[7]  = raw1[4]*raw2[3]  + raw1[5]*raw2[7]  + raw1[6]*raw2[11]  + raw1[7]*raw2[15];

  result[8]  = raw1[8]*raw2[0]  + raw1[9]*raw2[4]  + raw1[10]*raw2[8] + raw1[11]*raw2[12];
  result[9]  = raw1[8]*raw2[1]  + raw1[9]*raw2[5]  + raw1[10]*raw2[9] + raw1[11]*raw2[13];
  result[10] = raw1[8]*raw2[2]  + raw1[9]*raw2[6]  + raw1[10]*raw2[10] + raw1[11]*raw2[14];
  result[11] = raw1[8]*raw2[3]  + raw1[9]*raw2[7]  + raw1[10]*raw2[11] + raw1[11]*raw2[15];

  result[12] = raw1[12]*raw2[0] + raw1[13]*raw2[4] + raw1[14]*raw2[8] + raw1[15]*raw2[12];
  result[13] = raw1[12]*raw2[1] + raw1[13]*raw2[5] + raw1[14]*raw2[9] + raw1[15]*raw2[13];
  result[14] = raw1[12]*raw2[2] + raw1[13]*raw2[6] + raw1[14]*raw2[10] + raw1[15]*raw2[14];
  result[15] = raw1[12]*raw2[3] + raw1[13]*raw2[7] + raw1[14]*raw2[11] + raw1[15]*raw2[15];

  mtx1.rawData = result;
 }

}
}

...called by using "MatrixTools.append(m1,m2)" where you would have used "m1.append(m2)".

(Permission granted to use and/or modify the above code for any purpose.)
Logged

Glaiel-Gamer
Guest
« Reply #14 on: February 13, 2010, 01:02:03 PM »

I don't have a seat of flash that I can verify this with, but I suspect that they intended for you to throw these matrices into an opaque system that expects data (vertices?) in a user coordinate system, with an accompanying user-to-twips transform.  Does this make sense to those more familiar with the system?

The docs state that the class is used as the matrix3d member of displayObject, so i guess they only meant it to be for their internal stuff
Logged
bateleur
Level 10
*****



View Profile
« Reply #15 on: February 13, 2010, 01:49:07 PM »

No, I don't believe that.

If you intend a class to be internal you expose it only as an opaque handle. The availability of rawData as read/write property makes it clear that at least someone on the development team intended to expose the full functionality of the class.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic