www.jpct.net

jPCT - a 3d engine for Java => Support => Topic started by: AGP on July 20, 2009, 07:23:03 pm

Title: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 20, 2009, 07:23:03 pm
I'm trying to achieve the equivalent of ship.align(plane) (leveling the ship) in multiple iterations. This is what I have. What I'm getting instead is the exact same thing as ship.align(plane): it aligns the ship to the plane in a single pass. Shouldn't lastRotation.interpolate(Matrix, Matrix, .1f) take care of only rotating 10%?

Code: [Select]
if (shipLeveling == 10) {
      lastRotation = plane.getRotationMatrix();
      shipLeveling = 0;
}

Matrix softMatrix = ship.getRotationMatrix();
lastRotation.interpolate(lastRotation, softMatrix, 0.1f);// interpolate between the matrices
Matrix matrix = new Matrix(lastRotation);
ship.setRotationMatrix(matrix);
shipLeveling++;
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 20, 2009, 11:03:57 pm
I flipped the matrices between plane and ship (lastRotation=ship.getRotationMatrix(), softMatrix=plane.getRotationMatrix()) after re-reading the documentation. It seems to work now, except that it's never finished in the ten iterations (if I call level() multiple times it eventually completes). How do I make it complete in 10 iterations?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: EgonOlsen on July 20, 2009, 11:19:14 pm
Just play around with the weight. I don't know of any formula to compute the number of iterations needed for a defined outcome.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 20, 2009, 11:20:45 pm
OK. Here's another question: what if I wanted to align only two out of the three axis? How could I get a Matrix whose z is the ship's rotation matrix's z and whose x and y are the plane's? I know I can get the axis with the get_Axis() methods, but there are no equivalent set() ones.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 21, 2009, 03:32:42 am
I just thought I would be Mr. Obvious and point out that if two of the axes are defined, then all three are defined.  I suppose what you want to do (correct me if I am wrong) is to have the x and y axis both on the plane.  However, rather than defining their position ahead of time, you want to use the object's rotation around the z-axis to somehow determine the directions for the x and y axes.

If that is your goal, there is something I think you will need to define before you can devise a formula to use.  What is "true up" in relation to the object at any given rotation?  Consider situations like the object facing down (the world +y direction) and rotated pi-radians around its z-axis.  Would "true up" be the world +z direction in that case?  Or should it be the world -y direction, or something else entirely?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 21, 2009, 08:06:13 am
I see your point, Paul (may I safely assume it's not your code that's writing me? :-), but what I meant is that I need to reset the ship's rotation on two axis only. In this case, I need to reset the ship's x and y, since I'm once again working on the x/y plane and all I want is for the ship to level (as opposed to leveling and facing in a different direction relative to the plane).

Which brings me to a suggestion, Egon: since you already implemented the config.oldStyle3DS boolean, why not change the new style loader to rotate all the models into jpct's x/z plane? And everyone who, like me, has worked with the x/y will just set the boolean to true whereas everyone else will no longer have to worry about this issue.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 21, 2009, 07:13:12 pm
So, Egon, is it possible to get a Matrix with the z rotation of one object and the x and y rotations of another?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: EgonOlsen on July 21, 2009, 09:10:02 pm
Pfff...it sure is. I'm just not sure how to do it. There's some code to derive the angles from a matrix. Maybe you can do that on both and create a new matrix from the angles. I'm not sure if this will give you the desired effect though.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 21, 2009, 09:27:40 pm
As for getting them, wouldn't I just use the Matrix.get_Axis() methods? What about setting them?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: EgonOlsen on July 21, 2009, 10:13:58 pm
No, it's one that easy. Just search the forum...i think it shows two variants to solve this task. I'm not sure which one is better. If you have the angles, you can try to apply those rotations to a new matrix. However, i don't think that this will work. I matrix is more than a bunch of angles.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 21, 2009, 10:31:37 pm
I need to reset the ship's rotation on two axis only. In this case, I need to reset the ship's x and y, since I'm once again working on the x/y plane and all I want is for the ship to level (as opposed to leveling and facing in a different direction relative to the plane).
Ah, I think that is close to what I was imagining, except that you just want the vector between the x and y axes to be parallel to the "leveling-plane" (instead of the axes necessarily being on the plane as I wrote above).

So in this case, what you want is for the ship to rotate around its z-axis until both the x-axis and the y-axis vectors are the same distance from the "leveling-plane" (thus, the ship levels with the plane, but its z-direction doesn't change).  Let me know if I am understanding the problem correctly now.  I'll start working on a formula to accomplish this.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 21, 2009, 11:05:59 pm
I don't care about the distance between the ship and the plane, I just want the ship to fly parallel to the plane itself (which is the ground). And thanks for the help.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 21, 2009, 11:12:32 pm
And Egon, I wouldn't know what to search for. I found this: http://www.jpct.net/forum2/index.php/topic,1191.0.html, but I'm not sure I get it or whether it's what I'm looking for. I'm sure I sound like an idiot but I really only started taking a course on 3d graphics programming (it was c opengl). I loved, but I didn't get to finish it and I'm sort of new to this matrix stuff (first one I used was yours on the racer).
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 22, 2009, 02:11:23 am
Ok, I got it now.  I didn't realize you were talking about the ground being the plane you wanted to align to.  When you mentioned the x and y changing, for some reason I assumed you were talking about the plane created by the x and y axes (no wonder you seemed confused by my previous posts).

Just to be absolutely sure that I understand you now, I drew a diagram showing what you want to create a matrix for (it shows the two rotations that you want to be able to make via the new rotation matrix):
(http://www.paulscode.com/images/PlaneRotation.gif)

--EDIT--
I just realized that the method I had here previously for determining the direction vectors will not work (it would not work in cases where the ship was rotated both around the z-axis and the x-axis).  I'll think about it some more and see if I can come up with a way to calculate the "look" and "up" direction vectors.
--END EDIT--

Now from these vectors, you can create your destination rotation matrix.  This is how I did it for the Camera.setOrientation method (you'll have to invert the matrix for use with an Object3D - I was too lazy to change and test it myself):
Code: [Select]
        Matrix m = new Matrix();
       
        m.set( 0, 0, right.x );
        m.set( 1, 0, right.y );
        m.set( 2, 0, right.z );
        m.set( 3, 0, 0.0f );
       
        m.set( 0, 1, up.x );
        m.set( 1, 1, up.y );
        m.set( 2, 1, up.z );
        m.set( 3, 1, 0.0f );
       
        m.set( 0, 2, look.x );
        m.set( 1, 2, look.y );
        m.set( 2, 2, look.z );
        m.set( 3, 2, 0.0f );
       
        m.set( 0, 3, 0.0f );
        m.set( 1, 3, 0.0f );
        m.set( 2, 3, 0.0f );
        m.set( 3, 3, 1.0f );
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 22, 2009, 05:54:01 am
Ok, I've thought about it some more, and I think this should work for determining the direction vectors needed to create the matrix.

The first thing to do is to figure out the "look" direction (i.e. the direction that the ship should be flying toward after applying the rotation matrix).  One way to do this would be to cast the ship's initial direction vector onto a plane that is parallel to the ground and passes through the ship's position in world space:
Code: [Select]
SimpleVector look = new SimpleVector( ship.getZAxis() );
look.add( ship.getTransformedCenter() );
look.y = ship.getTransformedCenter().y;
look.normalize();

Once you have the "look" direction, the remaining direction vectors are easy.  Up is simply:
Code: [Select]
SimpleVector up = new SimpleVector( 0, -1, 0 );And right is the cross product of the first two:
Code: [Select]
SimpleVector right = up.calcCross( look ).normalize();
Just plug those into the matrix and that should be what you need.  Let me know if it doesn't work for some reason.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 22, 2009, 05:59:15 am
Thanks a lot for the help. My world is on an x/y plane, with +z going up. And about the m.set methods, would I afterwards just add m.invert()?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 22, 2009, 11:44:55 am
I assume the ship model also follows that as well (where its z-axis points toward the top of the model rather than the front)?  In that case, which axis is "forward"?  x, -x, y, or -y?

As for inverting the matrix, you could use the invert3x3 method, although the more logical aproach would be to figure out the correct location for the values in the matrix.  It should be like this, although I haven't actually tested to make sure:

Code: [Select]
        m.set( 0, 0, right.x );
        m.set( 1, 0, up.x );
        m.set( 2, 0, look.x );
        m.set( 3, 0, 0.0f );
       
        m.set( 0, 1, right.y );
        m.set( 1, 1, up.y );
        m.set( 2, 1, look.y );
        m.set( 3, 1, 0.0f );
       
        m.set( 0, 2, right.z );
        m.set( 1, 2, up.z );
        m.set( 2, 2, look.z );
        m.set( 3, 2, 0.0f );
       
        m.set( 0, 3, 0.0f );
        m.set( 1, 3, 0.0f );
        m.set( 2, 3, 0.0f );
        m.set( 3, 3, 1.0f );
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 22, 2009, 06:09:32 pm
Forward, before any rotation, obviously, is +y. But the ship's rotation around z is precisely what shouldn't change in the new matrix.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 22, 2009, 07:11:05 pm
I don't quite get it yet (I will once I see it working), but this is what I wrote. It's a variation on yours in that I get the ship's YAxis, I set look.z, and up became (0, 0, 1) to account for the x/y plane:
Code: [Select]
      private void pauls() {
SimpleVector look = new SimpleVector( ship.getYAxis() );//getZAxis
look.add(ship.getTransformedCenter());
look.z = ship.getTransformedCenter().z;
look.normalize();
SimpleVector up = new SimpleVector(0, 0, 1);

SimpleVector right = up.calcCross( look ).normalize();
Matrix m = new Matrix();
       
m.set( 0, 0, right.x );
m.set( 1, 0, up.x );
m.set( 2, 0, look.x );
m.set( 3, 0, 0.0f );

        m.set( 0, 1, right.y );
        m.set( 1, 1, up.y );
        m.set( 2, 1, look.y );
        m.set( 3, 1, 0.0f );
       
        m.set( 0, 2, right.z );
        m.set( 1, 2, up.z );
        m.set( 2, 2, look.z );
        m.set( 3, 2, 0.0f );
       
        m.set( 0, 3, 0.0f );
        m.set( 1, 3, 0.0f );
        m.set( 2, 3, 0.0f );
        m.set( 3, 3, 1.0f );
if (shipLeveling == 15) {
      lastRotation = ship.getRotationMatrix();
      shipLeveling = 0;
}

lastRotation.interpolate(lastRotation, m, 0.12f);//OINTERPOLATE BETWEEN THE MATRICES
Matrix matrix = new Matrix(lastRotation);
ship.setRotationMatrix(matrix);
shipLeveling++;
      }

Is it supposed to be right? Because it doesn't work yet (the screen goes black, of all things).
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 22, 2009, 10:10:58 pm
This looks correct to me.  I wonder if I'm using the matrix incorrectly (the parts that are filled in with 0's and 1's) somehow causing the ship's position to change or something.  Let me play around with this a little to see if I can figure out what is going on here.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 22, 2009, 11:38:21 pm
Ok, I found what causing the black screen - I didn't realize that normalize() doesn't actually change a vector (a better name for the method would be "calcNormal()").  Change the line to:

Code: [Select]
look = look.normalize();
However, there is still another problem with the code somewhere (its not quite doing what I expected it should), so I'll continue working on it.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 22, 2009, 11:50:01 pm
That solved the screen going black, but now the ship rotates all over the place. Are you sure my changes are right?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 23, 2009, 12:08:28 am
I'm not sure.  I'm having problems with the interpolate method itself at the moment. 
Shouldn't destMatrix and m be identical in this case?

Code: [Select]
            Matrix m = new Matrix( srcMatrix );
            m.interpolate( m, destMatrix, 1 );
           
            System.out.println( "srcMatrix: " );
            System.out.println( srcMatrix );
            System.out.println( "destMatrix: " );
            System.out.println( destMatrix );
            System.out.println( "m: " );
            System.out.println( m );


--EDIT--
Here is a printout of all three matrices for reference

I get the following:
Code: [Select]
srcMatrix:
(
-0.693466 -0.08907764 0.7149619 0.0
-0.31167796 0.93176264 -0.1862187 0.0
-0.6495859 -0.35197458 -0.67390835 0.0
0.0 0.0 0.0 1.0
)

destMatrix:
(
-0.99985695 0.0 0.016913526 0.0
0.0 1.0 0.0 0.0
-0.010317787 -0.79237705 -0.6099444 0.0
0.0 0.0 0.0 1.0
)

m:
(
-0.9997003 -0.0064068944 0.027718963 0.0
-0.008176312 0.7837748 0.0 0.0
-0.012727153 -0.3899964 -0.9996158 0.0
0.0 0.0 0.0 1.0
)
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 23, 2009, 12:11:50 am
I never thought to test weight as 1, that was clever. That's bizarre. Egon?
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 23, 2009, 12:28:52 am
At any rate, the interpolation issue is not the only problem - the destMatrix calculated is still not correct, so I'll work on solving that problem in the mean time until Egon can shed some light on the interpolation thing.

-- EDIT-- Never mind, Egon.  I figured out what I was doing wrong (see below).
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 23, 2009, 01:24:31 am
Ok, I solved both problems.  Here is a demo applet (let me know if this is the correct behavior you are looking for).  The controls are a little screwy, but it is enough to demonstrate the concept.  Drag the mouse to rotate the object.  After releasing the mouse, the ship will smoothly interpolate to align with the ground.  Arrow keys to orbit camera, shift+arrows linear-moves camera, and ctrl+arrows zooms in and out.  If the ship gets "stuck", just wait a couple of seconds for it to correct itself (caused by an unrelated bug)

Demo Applet (http://www.paulscode.com/source/AutoNavigation/PlaneAlign.html)  (source code (http://www.paulscode.com/source/AutoNavigation/PlaneAlign.html))  (ground on x/y plane)

-- EDIT--  I converted the applet so that the ground is now on the x/y plane.

The interpolation problem was because the destMatrix was improperly constructed (look, up, and right were not at right angles to each other).  This problem was caused by another problem.  Basically, "casting the ray onto the plane" idea was overly complicated (I still think it should have worked - something must be wrong with my logic).  At any rate, the much simpler (and working) method is to simply take the z-axis, change it's y-coordinate to 0, and normalize.  Looks like this (ground on x/z plane):
Code: [Select]
            SimpleVector look = new SimpleVector( ship.getZAxis() );
            look.y = 0;
            look = look.normalize();

The rest is the same as above.
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 23, 2009, 02:08:02 am
Ok, I got it working for when the ground is on the x/y plane like in your project.  I did have to change the formula a bit to make it work properly (I tend to have trouble visualizing these things until I actually run some tests).  Anyway, here is the correct formula for determining the direction vectors (ground on x/y plane):

Method #1
Code: [Select]
            SimpleVector up = new SimpleVector( ship.getYAxis() );
            up.z = 0;
            up = up.normalize();
            SimpleVector look = new SimpleVector( 0, 0, 1 );
            SimpleVector right = up.calcCross( look ).normalize();
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: paulscode on July 23, 2009, 03:15:27 am
I am probably beating a dead horse at this point, but in case wanted to align only the wings of the ship with the ground (rather than both the wings and tail like in the first method), here are the direction vectors to use (ground on x/y plane):

Method #2
Code: [Select]
            SimpleVector up = new SimpleVector( ship.getYAxis() );
            SimpleVector worldZ = new SimpleVector( 0, 0, 1 );
            SimpleVector right = up.calcCross( worldZ ).normalize();
            SimpleVector look = right.calcCross( up ).normalize();

--EDIT--

I uploaded another demo applet using this new method, so you can compare the different behaviors to see which one is what you are looking for.  If neither of them are correct, let me know that, too ;D

Method #1 (align x and y) (http://www.paulscode.com/source/AutoNavigation/PlaneAlign.html)  (source code (http://www.paulscode.com/source/AutoNavigation/PlaneAlignSource.zip))

Method #2 (align x) (http://www.paulscode.com/source/AutoNavigation/PlaneAlign1D.html)  (source code (http://www.paulscode.com/source/AutoNavigation/PlaneAlign1DSource.zip))
Title: Re: ship.align(plane) IN MULTIPLE ITERATIONS
Post by: AGP on July 23, 2009, 03:56:34 am
Awesome, Paul, thanks a whole lot, man. Now to study it. :-)