ship.align(plane) IN MULTIPLE ITERATIONS

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

Previous topic - Next topic

AGP

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%?


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

AGP

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?

EgonOlsen

Just play around with the weight. I don't know of any formula to compute the number of iterations needed for a defined outcome.

AGP

#3
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.

paulscode

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?

AGP

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.

AGP

So, Egon, is it possible to get a Matrix with the z rotation of one object and the x and y rotations of another?

EgonOlsen

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.

AGP

As for getting them, wouldn't I just use the Matrix.get_Axis() methods? What about setting them?

EgonOlsen

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.

paulscode

Quote from: AGP on July 21, 2009, 08:06:13 AM
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.

AGP

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.

AGP

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

paulscode

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


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


paulscode

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:
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:
SimpleVector up = new SimpleVector( 0, -1, 0 );
And right is the cross product of the first two:
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.