www.jpct.net
jPCT  a 3d engine for Java => Support => Topic started by: AGP on September 24, 2010, 05:12:42 pm

The following have been my attempts at converting 3ds max's camera matrix into jPCT's. None have worked (and I've since forgotten the Maxscript to even get the camera's matrix!). Anyway, if anyone could help with this I would really appreciate it.
private Matrix convertMaxToJpctMatrix(Matrix toConvert) {
Matrix newMatrix = new Matrix(toConvert);
Matrix transformer = new Matrix();
float[] transformerValues = {1f, 0f, 0f, 0f,0f, 0f, 1f, 0f,0f, 1f, 0f, 0f,0f,0f,0f,1f};
// float[] transformerValues = {1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f,0f,0f,1f};
transformer.setDump(transformerValues);
/**
[ 1 0 0 ]
[ 0 0 1 ]
[ 0 1 0 ]*/
/**1st
1 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
2nd:
0 1 0 0
0 0 1 0
1 0 0 0
0 0 0 1
3rd (ON THE LEFT:
1.0 0.0 0.0 0.0
0.0 1.0 0.0f 0.0
0.0 0.0f 1.0 0.0
0.0 0.0 0.0 1.0
*/
newMatrix.matMul(transformer);
// transformer.matMul(newMatrix);
return newMatrix;
}

I'm confused...what is the input matrix and what's the expected result and the actual result?

The input matrix are the values I got from 3ds max maxscript console. The above method is called like so:
theCamera.setFOVLimits((float)Math.toRadians(10), (float)Math.toRadians(170));
theCamera.setFOV((float)Math.toRadians(34.254));
Matrix cameraMatrix = new Matrix();
// float[] maxMatrix = {0.0860526f,0.996188f,0.0143083f, 0.543894f,0.0590056f,0.837077f,0.83473f,0.0642504f,0.546898f,86.031f,21.7374f,75.9077f};
float[] maxMatrix = {0.0860526f,0.543894f,0.83473f,0f,0.996188f,0.0590056f,0.0642504f,0f,0.0143083f,0.837077f,0.546898f,0f,15.3374f,15.4662f,114.723f,1f};
cameraMatrix.setDump(maxMatrix);
cameraMatrix = convertMaxToJpctMatrix(cameraMatrix);
SimpleVector cameraPosition = new SimpleVector(86.031f, 21.7374f, 75.9077f);//IN MAX: 86.031,21.7374,75.9077
theCamera.setBack(cameraMatrix);
theCamera.setPosition(cameraPosition);

What i actually meant was something like:
This is the max matrix: <matrix>...it rotates the camera around <whatever> <some> degrees
This is the jPCT is would expect: <matrix>
This is what i get: <matrix>
I'm having a real hard time figuring out how to convert them, if i have no idea what the initial matrix looks like and what it is supposed to do.

OK, the variable named maxMatrix is the Max Matrix. The expected result is that I would be looking at the exact same thing in a jPCT scene as I am in Max, but instead the camera is always facing (and is positioned) somewhere else. The scene is of that QG 2.5d game I've been doing for nearly two years and, since I'm nearly finished now, I need to address this issue. Right now, I have made an approximation with the following method, but I need an exact result, since the backgrounds in this game are all 2D.
Oh, and the camera will never move in this game (the backgrounds, as said, are 2D screens). I can't get the position and rotation in Max of the camera until Monday, when I can get to the Max scene and check, sorry.
private void oldCamera() {
SimpleVector cameraPosition = hero.getTransformedCenter();
cameraPosition.z = 32;
theCamera.rotateCameraX((float)Math.toRadians(35));//ORIGINALLY 20
theCamera.setPosition(cameraPosition);
theCamera.moveCamera(Camera.CAMERA_MOVEUP, 33.2f);
theCamera.moveCamera(Camera.CAMERA_MOVELEFT, 12f);//14f
theCamera.moveCamera(Camera.CAMERA_MOVEOUT, 140f);//14f ORIGINALLY
theCamera.setFOVLimits((float)Math.toRadians(5), (float)Math.toRadians(175));
theCamera.setFOV(theCamera.getFOV()/3.2f);
}

Do you have any information about the kind of matrix (row/columnmajor) and the coordinate system max is using? How, you example, does a matrix look like that makes the camera facing 90° down?

I'm fairly sure Max uses 4x4 row major matrices, and, I also read that rotations in max are backwards (Max is righthanded, but the rotations are lefthanded). In the Max orthographic viewports, X points right, Y points up, and Z points out of the screen toward you. Worldspace coordinate system is such that X runs in a positive direction to the right, Z runs in a positive direction upward, and Y runs in a positive direction away from you.

Can you access max matrix represention so that you can post a matrix from max that does that simple 90° down look?

I'm downloading a Max trial right now, since I'm not home, but it'll take a little while, buddy.

Got it. Took me longer to remember the damn dollar sign than to download it : )
This camera faces down on the viewport. Again, in worldspace coordinate system X runs in a positive direction to the right, and Y runs in a positive direction away from you, Z runs in a positive direction upward. $Camera001.transform gives: (matrix3 [1,0,0] [0,1,0] [0,0,1] [0,0,0])

That's an identity matrix, i.e. the camera hasn't roated at all. What i meant was a matrix from a camera that has a simple but defined rotation like 90° around X or something like that.

Sorry, I was in a hurry to leave for a wedding last night but I wanted to get this done first. The thing is, I don't know anything about MaxScript and Google isn't helping much. I'll look up how to get the rotation matrix and post back.

When I rotate it so that the camera is facing forward on the viewport, the camera's matrix reads (matrix3 [1,0,0] [0,0,1] [0,1,0] [0,0,0]). Does that help?
That was positive 90º on x, by the way.

I'm not sure, if my thinking is correct, but this looks very much like a normal GL like matrix. So to convert it, it would think that
float[] mat={1,0,0,0, 0,0,1,0, 0,1,0,0, 0,0,0,1};
Matrix m=new Matrix();
m.setDump(mat);
m.transformToGL();
should do the trick. I'm abusing the transformToGLmethod here to actually do the opposite. A simple rotation around X with 90° will have the same effect, but this is cheaper.

I don't get it: where do these values come from? I mean, I noticed the pattern of the extra 0 for the first rows and the extra 1 for the last, but is that what I need to add every time?

This is just to make a 4x4 matrix out of this 3x4 matrix. Just add a 0 in each row but the last and a 1 in the last.

Didn't work, Egon. I can't see anything.

Then...be creative. I mean, what can be different between 3ds and jPCT? The matrix order (row/columnmajor), the coordinates system...or 3ds stores something really strange in that matrix.
So i would do the following to find out:
 leave out the transform2GL call
 try to transpose the matrix (with and without transform2GL)
 last idea: Try to invert it. Maybe 3ds uses an inverted matrix for whatever reason...
Create yourself a simple testcase in 3ds with a cube or something that is viewed by a camera with a simple transformation. Load that cube, place it like in 3ds and try to make the jPCT matrix match the view in 3ds.

And don't forget to make this 3x4>4x4 step every time. That's definitely needed no matter what else you do to the matrix.

I added the 0s and the 1. When I commentedout the entire matrix thing and set the FOV to 45 (as it is in Max), and entered the position of the camera (y/z flipped) and set camera.lookAt to the position of Max's camera's target, I got a camera looking sideways at the scene (as if it had been jpctYrotated 90º around the center of the scene). But I got to see the characters (the height was right). Bizarre, right?
theCamera.setFOVLimits((float)Math.toRadians(10), (float)Math.toRadians(170));
theCamera.setFOV((float)Math.toRadians(45));
theCamera.setPosition(new SimpleVector(51.598f, 59.977f, 26.276f));
/* float[] mat = {0.147809f,0.989015f,0f,0f,
0.581329f,0.0868801f,0.809016f,0f,
0.80013f,0.11958f,0.587785f,0f,
51.5975f,26.2763f,59.9766f,1f};
Matrix m = new Matrix();
m.setDump(mat);
m.transformToGL();
theCamera.setBack(m);
*/
theCamera.lookAt(new SimpleVector(24.935f, 40.39f, 22.292f));

Might be an artifact of lookAt(). There are unlimited ways to stand at some position and look at another, because you can always rotate around the direction vector and "look at" is still true. If you already have the camera's position and a target to look at...maybe you have an up vector too? In that case, you might want to use setOrientation() instead, where the direction vector is the vector between the target and the position (i.e. targetposition).

Without the transformToGL call some of the characters show up rotated as if they were lying on the ground, but in a weird position on screen. I wish I was on more surefooting on this, man, so I can't very well get creative.
How do I get an upvector?

How do I get an upvector?
No idea...it's possible to derive it from the cam's rotation matrix, but if that one would be working, you wouldn't need it in the first place...so...isn't it possible to get it from max? I mean you can get obviously get the position and the target. Both are worth nothing without the up vector, so there should be a way to get it!?

Question: is the upvector just, say, a (0, 1, 0)type of vector? Meaning are there only three (or six with negative values) possibilities for it?

When I commentedout the entire matrix thing and set the FOV to 45 (as it is in Max), and entered the position of the camera (y/z flipped) and set camera.lookAt to the position of Max's camera's target, I got a camera looking sideways at the scene (as if it had been jpctYrotated 90º around the center of the scene). But I got to see the characters (the height was right). Bizarre, right?
This sounds like you have the wrong coordinate system. The fact that you see the characters should mean that the target position is in the same coordinate system as the camera lookAt position, but the fact that in jPCT's coordinate system everything is rotated and you are looking from the side could mean that the entire scene (including the lookAt vector you are using) is rotated 90 around the jPCT camera's yaxis. You should be able to just flip the x and z coordinates (in camera space) for the object positions and the camera lookAt vector (leave the camera in the position you have it), to have everything oriented properly.
Question: is the upvector just, say, a (0, 1, 0)type of vector? Meaning are there only three (or six with negative values) possibilities for it?
Correct as long as the camera is aligned with the cardinal directions.

This sounds like you have the wrong coordinate system. The fact that you see the characters should mean that the target position is in the same coordinate system as the camera lookAt position, but the fact that in jPCT's coordinate system everything is rotated and you are looking from the side could mean that the entire scene (including the lookAt vector you are using) is rotated 90 around the jPCT camera's yaxis. You should be able to just flip the x and z coordinates (in camera space) for the object positions and the camera lookAt vector (leave the camera in the position you have it), to have everything oriented properly.
Well, jPCT's up axis is y, whereas worldspace up for max is +z. I accounted for that. Or do you mean something else?
Correct as long as the camera is aligned with the cardinal directions.
Cool, so I go at it by trialanderror. But here's another thing: there is no setOrientation method in Camera! : )

Well, jPCT's up axis is y, whereas worldspace up for max is +z. I accounted for that. Or do you mean something else?
No, I mean more like the xaxis you are using is equivalent to jPCT's zaxis.

I flipped the values now and, unfortunately, no cigar. I see nothing on screen.

Cool, so I go at it by trialanderror. But here's another thing: there is no setOrientation method in Camera! : )
There is: http://www.jpct.net/doc/com/threed/jpct/Camera.html#setOrientation(com.threed.jpct.SimpleVector,%20com.threed.jpct.SimpleVector) (http://www.jpct.net/doc/com/threed/jpct/Camera.html#setOrientation(com.threed.jpct.SimpleVector,%20com.threed.jpct.SimpleVector)) Which version are you using ???

I flipped the values now and, unfortunately, no cigar. I see nothing on screen.
Is camera at 0,0,0? If not, you'll need to subtract it from the converted vectors. Also try reversing the sign of x, z, or both.

Which version are you using?
I had already updated it to 1.21 today to use the transformToGL() method, but I guess it was a Firefox caching thing. I see it now.
Is camera at 0,0,0? If not, you'll need to subtract it from the converted vectors. Also try reversing the sign of x, z, or both.
Cool, I'll try and be right back, thanks.

OK, I tested all 12 possibilities for up vectors with setOrientation (12 because I tried flipping x and z as well). Nothing showed me anything. What I didn't try is flipping the x and z of setPosition, but that shouldn't be the difference between me seeing SOMETHING and nothing, right?

That is very strange. I can't imagine a scenario where you can see something then flipping the x and z coordinates in camera space of that thing plus the x and z values of the camera's look direction in camera space and no longer being able to see the thing  seems like that should always result in the equivalent of rotating the thing 90 degrees around its yaxis. Obviously such a scenario exists in your case, so I guess it is just a limitation of my imagination..

Ok, give this a try (to see if my logic about flipping x and z in camera space to rotate the scene properly is incorrect). Set up your scene as you did earlier where you can see the characters from looking sideways at the scene (i.e. comment out matrix thing, FOV to 45, position of camera y/z flipped and camera.lookAt to the position of Max's camera's target). Then call the following method:
public void rotateScene90( Object3D[] sceneObjects, SimpleVector lookTarget, Camera camera )
{
SimpleVector sourcePosition, targetPosition, translation;
for( int x = 0; x < sceneObjects.length; x++ )
{
// convert object's position into camera space:
sourcePosition = new SimpleVector( sceneObjects[x].getTransformedCenter() );
sourcePosition = sourcePosition.calcSub( camera.getPosition() );
sourcePosition.matMul( camera.getBack() );
// determine the new position (in camera space):
targetPosition = new SimpleVector(sourcePosition.z, sourcePosition.y, sourcePosition.x );
// convert new position into world space:
targetPosition.matMul( camera.getBack().invert3x3() );
targetPosition.add( camera.getPosition() );
// translate to the new position:
sceneObjects[x].translate( targetPosition.calcSub( sceneObjects[x].getTransformedCenter() ) );
}
// convert the looktarget into camera space:
sourcePosition = new SimpleVector( lookTarget );
sourcePosition = sourcePosition.calcSub( camera.getPosition() );
sourcePosition.matMul( camera.getBack() );
// determine the new looktarget (in camera space):
targetPosition = new SimpleVector(sourcePosition.z, sourcePosition.y, sourcePosition.x );
// convert the new looktarget into world space:
targetPosition.matMul( camera.getBack().invert3x3() );
targetPosition.add( camera.getPosition() );
// look toward the new looktarget:
SimpleVector look = targetPosition.calcSub( camera.getPosition() ).normalize();
SimpleVector up = camera.getYAxis();
up.scalarMul( 1 ); // Bug fix, shouldn't be necessary? Try removing if scene is upsidedown
camera.setOrientation( look, up );
}
Notice the bug fix for the setOrientation issue. Depending on the scene, the call to up.scalarMul( 1 ) may or may not be necessary (remove it if the scene winds up upsidedown).