ship.align(plane) IN MULTIPLE ITERATIONS

Started by AGP, July 20, 2009, 07:23:03 PM

Previous topic - Next topic

AGP

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()?

paulscode

#16
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:

        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 );

AGP

Forward, before any rotation, obviously, is +y. But the ship's rotation around z is precisely what shouldn't change in the new matrix.

AGP

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:

      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).

paulscode

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.

paulscode

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:

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.

AGP

That solved the screen going black, but now the ship rotates all over the place. Are you sure my changes are right?

paulscode

#22
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?

            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:
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
)

AGP

I never thought to test weight as 1, that was clever. That's bizarre. Egon?

paulscode

#24
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).

paulscode

#25
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  (source code(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):
            SimpleVector look = new SimpleVector( ship.getZAxis() );
            look.y = 0;
            look = look.normalize();


The rest is the same as above.

paulscode

#26
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
            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();

paulscode

#27
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
            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)  (source code)

Method #2 (align x)  (source code)

AGP

Awesome, Paul, thanks a whole lot, man. Now to study it. :-)