Pointing at something in 3D
After I did the example yesterday of the many fish scattered across the screen, it seemed rather sad that they were not moving, so I set about making them move. I want them to also point in the direction of their movement, and in looking over the docs, I found a method of Matrix3D called pointAt(). This sounded promising, and I kindof got it working, except that now my fish had infinite height… Not a pretty sight let me tell ya. I don’t know what caused this ‘glitch in the matrix’ but when I saw that Utils3D also had a similar method called pointTowards, I thought I’d give that a go. Not expecting any difference, I was thrilled to see that it actually worked. I did also have to fiddle with obtaining the target matrix value, as it apparently has to be relative to the matrix we are manipulating. Anyhoo, enough chatter (you can read the code if you’re interested, though I must apologize for the lack of comments , which I intend to remedy later) — here is the result:
flash 10 required
November 26th, 2008 at 12:05 pm
Concerning pointAt: I think you are seeing the results of a bug. We didn’t anticipate that people would try to use matrix3D methods on the results of perspectiveProjection.toMatrix3D(). The “normal” 3d pipeline would be to first transform localspace 3d coordinates into camera space coordinates, then do clipping, then project the clipped points to 2d screen space. Don’t get me wrong, its a natural thing to do if you don’t care about clipping, its just not something we tested (nor anything the beta sites tested). And, unfortunately, its buggy. The workaround is to only use the results of perspectiveProjection.toMatrix3D() as the argument to Utils3D.projectVectors(). Don’t modify it in any way. Use a seperate Matrix3D to move things around in 3d space. Here’s an example from your fish3d.as:
projectionMatrix = perspective.toMatrix3D();
//use a seperate matrix “worldMat” for world positioning.
worldMat.identity();
worldMat.prependTranslation(xp,yp,zp);
//note: your rotation order was inverted here. Effect order in the end is is scaleX, scaleY, scaleZ, rotX, rotY, rotZ, transX, transY, transZ
worldMat.prependRotation(zr,new Vector3D(0,0,1)/*Vector3D.Z_AXIS*/);
worldMat.prependRotation(yr,new Vector3D(0,1,0)/*Vector3D.Y_AXIS*/);
worldMat.prependRotation(xr,new Vector3D(1,0,0)/*Vector3D.X_AXIS*/);
// or more simply:
/*
Vector. components = worldMat.decompose(); // this could be done once in init()
components[0] = new Vector3D(xp,yp,zp);
components[1] = new Vector3D(xr*DegToRad, yr*DegToRad, zr*DegToRad);
worldMat.recompose(components);
*/
worldMat.transformVectors(localVertices, worldVertices);
Utils3D.projectVectors(projectionMatrix, worldVertices, projectedVerts, uvts);
November 26th, 2008 at 9:28 pm
[...] in the direction of their motion using Matrix3D.pointAt() which worked for me this time, unlike last time. Thanks Chris for pointing me in the right [...]
November 26th, 2008 at 9:48 pm
I gave pointAt() another chance and it worked out (see new post above) so it must have been something weird about how I was using it before. I guess the new 3D API assumes some sort of familiarity with traditional 3D rendering processes – which I lack – so I’m not sure how to fit the pieces together sometimes.