How to manage Pitch, Roll and Yaw for a "first-person-shooter-view" ?

Hello world ! :smiley:
[b]

MY INTRODUCTION :[/b]

First, please, keep in mind that I am a french dude and that my knowledges in english are not as good as our vine…
( Sorry in advance, then, for all orthografik and syntaxik mistakes… )
We can now speak about 3D ( Well, let’s try… )

As the title means, I am trying to make a “doom-like” behavior with java3D. I ever know that there are a lot of others API and Engines in Java which are more oriented in 3Dgames… ( I have ever tried a look onto the “GAME/FPS/” - section of this Forum where I found a lot of intersting things about that : JOGL, LWLGL, J-MonkeyEngine, Xith3D, etc… ) But I would really like to make my own game with Java3D since I have ever made some efforts to understand its packages.

I know that it ever exists a famous Java3D game-engine (perhaps the only one, huh ? ) called HUMID ( With which had been computed a network game like QUAKE, named JAMID, ever in 2001 ! ! ! ) but I don’t know if it is open source and I never did success in finding it…
HUMID : Where are you ? :’(

I know that I can even find an exemple of this “kind of camera-navigation” here :
http://www.java2s.com/ExampleCode/3D/SimpleDOOMstylenavigationofa3DsceneusingJava3D.htm
The authors made here a keyBehavior.class which applies some transform3D on the viewPlatform.
These transform3D use setTranslate, rotX, rotY and rotZ, but HEADING has been disactivated.
I have tried it in re-activating these options, and there are then errors…
( There are also some helps, but too incomplete for me, in a book called “Killer programming in Java” )

Well, ALL THIS, to mean that after a long prospection, I did not success in find one only poor class which could do correctly the work, when there were a lot of one in the others engines…
Then I decided to make my own, even if i am still a little newbie, and if my study-level makes me wonder what is a vector ( < Nearly a joke… )

MY QUESTION : ( ;D Yes, it comes ! )

I have chosen to extends com.sun.j3d.utils.behaviors.vp.ViewPlatformAWTBehavior :
Well, I first used : transformTG.mul(rotX,rotY) but, if I could rotate my view horizontally ( PITCH ) and vertically ( ROLL / HEADING ) - and this, where I decided to translate - there was still a problem :
my YAW-rotation was also changing !

Then, I replace rotX and rotY by my own quaternion, but the problem stays the same ( I guess it must be logical… ) :
In fact, when I make little circles with my mouse ( makes then change PITCH and ROLL as attended ) the YAW is then progressively changing too : Unattended !!!..

I guess that there is then some natural mathematical relation between ( pitch & roll ) AND ( yaw ) that I have to inhibate if I want to make my behavior : :-[ But stop me, please, if I am wrong !
Please, how may I do this ?

Please, ??? how can I manage to change PITCH and ROLL and in the same time always keep my old YAW ?

Hello ! :slight_smile:

Well, not any suggestion yet ? Perhaps should I be really shorter in my explainations…?
Replacing (setRotation(Quaternion)) or (rotX, rotY and rotZ) by (setEuler) may be a good way to show what I am asking for :

With “roll” and “pitch” being obtained when mouse is moved left, right, up or down, we have then this in my Behavior class :

Transform3D t3d = new Transform3D();
targetTG.getTransform(t3d); // targetTG is the actual ViewPlatform's tranform
Transform3D rotEye = new Transform3D();     
rotEye.setEuler(new Vector3d(roll,pitch,0)); // roll,pitch,yaw
t3d.mul(rotEye);
targetTG.setTransform(t3d);

With this snipet, effetcs of roll and pitch on the view are ok :smiley: , but as they change, yaw is changing too >:(, althought it should not, should it ?
As strongs are my moves with the mouse, as far my target-view is changing ( ok ) but as far my view is rotating around herself ( not so ok !! )
Once upon the time : :-[ Please, what can I do to fix this ?

I’m afraid you’re in the space where Quaternions live, which is somewhere that is beyond my understanding as yet. However, I am wondering whether your problem is happening because you are using your world X and Y positions rather than the local ones of your viewplatform? That would mean that once your view was rotated away from it’s starting position changing position around one axis might and result in changing the pitch or yaw of the ViewPlatform.

Usually, when I run into this kind of problem I solve it by trial and error. It usually takes me ages and when I have just found a solution someone here tells me what I needed to know in the first place…

:smiley: THX, nice kind of kidding…

Well, I also thought it was due to something like that, :-* and have tried some tentatives around, but …In vain…
Perhaps have I then really approached the truth from close, but the results weren’t here…
I remember I tried something closed looking like this :

// First rotation ( horizontally ) is done as usual :
Transform3D t3d = new Transform3D();
targetTG.getTransform(t3d); // targetTG is the actual ViewPlatform’s tranform
Transform3D rotEyeY = new Transform3D();
rotEyeY.rotY(roll);
t3d.mul(rotEyeY);
targetTG.setTransform(t3d);
// Then, let’s determine the new axe for vertically rotation :
Vector3d camVec = new Vector3d();
t3d.get(camVec);
//Since I have the new axe of my camera, I have to find a perpendicular Vector to this axe, in the same Z-Plan…
//At the beginning at least, as my camera is in (XY) plan (Z=0), then :
Vector3d newYax_Vec = new Vector3d( -camVec.y , camVec.x , 0 );
AxisAngle4d newYax = new AxisAngle4d(newYax_Vec,pitch);
Transform3D rotEyeX = new Transform3D();
rotEyeX.setRotation(newYax);
t3d.mul(rotEyeX);
targetTG.setTransform(t3d);

The problem is that I obtained once again the same result, with PITCH & ROLL > OK but with still an unwanted YAW factor added…
I have to say that if I inhibate Vertically OR Horizontally rotating, all is working fine.
I am then sure that the problem of unattended YAW-increased is coming from the fact I multiply the two others rotations…

What I misunderstand is taht I think I am doing it as it must be ?
It is why I wonder if it is really due to what you propose… ???
But, really, THX for the response, it is cool to feel heard ! 8)

Have you looked into Node.localToVWorld? I’m really grasping at straws here, but worth a look, maybe…

:slight_smile: Hello Breakfast : Nice to have some help of you, again, and so fast !

I did not know “Node.LocalToVworld” and then spent some time in looking for its usage through the web.
I found an exemple of how to use it, and I merge it with my own code : But I am not sure at all of all this done in the right way :-
Well, please, have a look at this if you can :

// First, I applied my transform :
// I replaced (Quaternion) by ( rotX and rotY ) and then by ( setEuler(roll, pitch, yaw) because it is shorter,
// …But I heard about that it would not be finally exactly the same thing, and that FLAW would become
// dangerous at last with set Euler()…

Transform3D rotEye = new Transform3D();
rotEye.setEuler( new Vector3d( ROLL, PITCH, 0 ) );
// roll,pitch,yaw
targetTG.getTransform(t3d); // targetTG is the ViewPlatform’s tranform
t3d.mul(rotEye);
targetTG.setTransform(t3d);

// After have applied this transform, I want now to know if there is really a problem of coordinates.
// I then apply this, but without any warranty of what I am doing :

BranchGroup bg = new BranchGroup();
targetTG.addChild(bg);

// now, if I well understand, to calculate the absolute coordinates of the (0,0,0) local point :
Transform3D tr3d = new Transform3D();
targetTG.getLocalToVworld(tr3d);
System.out.println(“tr3d from TransformGroup:\n” + tr3d);
bg.getLocalToVworld(tr3d);
System.out.println(“tr3d from BranchGroup:\n” + tr3d);

Here is the kind of result I then had after having translated a few on Z-Axis, and then having made rotating my view a bit :

tr3d from TransformGroup:
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, 0.0, 1.0

tr3d from BranchGroup:
1.0, 0.0, 0.0, 0.0
0.0, 0.9999619230641713, -0.008726535498373935, 0.0
0.0, 0.008726535498373935, 0.9999619230641713, 5.200000000000002
0.0, 0.0, 0.0, 1.0

But I am not sure of what it means… :-[
I imagine it could be a matrix(4d?) which gives me the rotation around the local coordinates of my camera ???
If it is so, I even not understand now how I might be using it… :o
I keep on the way, but any more help would be greatly appreciated, THX !

It’s a Quaternion, which describes 3d translation and rotation all together.

There is more on Quaternions lower down on this page: http://jdj.sys-con.com/read/99792_3.htm

Honestly couldn’t tell you what you need to do with it, although I’m increasingly finding I need to learn…

:slight_smile: Hi space-koders, Hi Breakfast !

Yes, I wrote “Matrix4d”, but in fact you are right, it is a “Quat4d” ( that might be appliable to a matrix4D to set a rotation ) .
( THX for the link about quaternions : I ever knew a few things, like “Gimbal Lock” was a good reason to replace setEuler by a normalized Quaternion for exemple… ) Coming back to our result from the code, It really seems to work as this :

xAxis_x, xAxis_y, xAxis_z, Point3D_x
yAxis_x, yAxis_y, yAxis_z, Point3D_y
zAxis_x, zAxis_y, zAxis_z, Point3D_z
0 , 0 , 0 , 1 >>>???

If I disable horizontal rotation ( PITCH ) , I obtain something like this :
tr3d from BranchGroup:
1.0, 0.0, 0.0, 0.0
0.0, 0.9935718556765878, -0.11320321376790672, 0.0
0.0, 0.11320321376790672, 0.9935718556765878, 0.0
0.0, 0.0, 0.0, 1.0

If instead, I disable vertical rotation ( HEADING ) , it gives something like that :
tr3d from BranchGroup:
0.9961946980917464, 0.0, -0.08715574274765817, 0.0
0.0, 1.0, 0.0, 0.0
0.08715574274765817, 0.0, 0.9961946980917464, 0.0
0.0, 0.0, 0.0, 1.0

(In the two cases, I have made no translations : Just one unical rotation following one axis. All is then fine.)
If I go on without any translation, but with combinating the two rotations ( HEADING & PITCH ), I have something like this :
tr3d from BranchGroup:
-0.5065270115555557, -0.5607435739365442, 0.6549786491584798, 0.0
0.704289473639521, -0.7072981536953477, -0.06087412504272182, 0.0
0.49739996369638195, 0.4304601794220015, 0.7531914166045806, 0.0
0.0, 0.0, 0.0, 1.0
In this last case, camera is also turning around itself ( YAW-factor )
I wonder where, in this quaternion, can I identificate and reverse-back this YAW-factor to maintain my “original-horizontal-YAW” ?

But, even if I success in identificate what I must reverse ( Let’s not be hurry !!! ) …
I am starting to think that it would not be as good as if I have directly the good transform : What about this ?

P.S. :-[ I also post my request here :
http://forums.java.net/jive/thread.jspa?messageID=93937&#93937
Since there were some others responses ( but not enough for me to be circumvenant ), I decided here to link mutually the two forums.
As I wrote it there : Please, forgive this kind of double-posting, and feel free to respond on the forum you want, THX !

EDITed : I HAVE AT LEAST A GOOD BEGINNING OF ANSWER TO SOLVE THE PROBLEM

Ok, someone on the other forum linked me on this article :
http://www.javaworld.com/javaworld/jw-07-2003/jw-0704-3d_p.html
I wrote to the author who gently took the time to answer my question even if he is now working on JOGL and no more on Java3D.
He said me he had the same problem and solved it in applying all the transform at once…
I did not understand because I also tried this. ???
But, when I tried its code ( code and ressources are downloadable at the beginning and at the end of the article ),
I have had to see that it was perfectly working ( at least, a real DOOM-or-Quake-camera, and not an other wolfenstein-basic-camera !!! ;D )
I began to look inside, but I don’t know for the moment where I did a mistake in my own code… :-[
I will post here a simple and complete behaviour as soon as I will have all complete.

A lot of thanks for all your help ! :smiley:

I’m teaching a class on gaming at Chapman University and I’m not sure what you are asking, but it sounds similar to a problem one of my student’s was having.

Basically you have to base the yaw, pitch and roll movement on your current orientation. For pitch, you take a vector along the x axis (1,0,0) and transform it with the current orientation transformation matrix (t3dYPR). Use that to create an AxisAngle (basically a type of quaternion) with a rotation in the direction you want (forward or backward pitch) and use that to create another transformation. Then multiply your orientation transformation (t3dYPR) by that transformation and that adds the pitch.

You can download the complete code here: http://www.gamedev370.com/samps.html

if (keyPitchDown)
  {
  // create a vector in the x direction
  v3fTmp.set(1.0f,0.0f,0.0f);

  // rotate that vector into the current orientation
  t3dYPR.transform(v3fTmp);
 
  // create axis to rotate around that x axis in our orientation coordinate space
  aaYPR.set(v3fTmp,TURNDELTA);
 
  // set a temporary transform
  m3fTmp1.set(aaYPR);
  t3dTmp.set(m3fTmp1);
 
  // multiply the current view by that rotation
  t3dYPR.mul(t3dTmp);
  t3dYPR.normalize();
  }

I hope that helps,

Wood

Hello !

I have just finished my own code thanks to the Dr Pendergast.
It can be found here :
http://www.progmaster.info//zFiles/koders/Java/Java3D/first_person_shooter_camera_(2006_04_03).rar

In this one, I make something like this, what I couldn’t do before, when I first post here, because I did not know what the method “transform” could do !

// For translations, I get orientation and apply transform on it :
Transform3D tTemp = new Transform3D();
targetTG.getTransform(tTemp);
Vector3f tv = new Vector3f(0, 0, 0);
if (keycode == KeyEvent.VK_UP) { tv.set( 0, 0, -1 ); }
tTemp.transform(tv);

[b]

// For rotations, in my “integrateTransform” method, I have something like :

Transform3D tVect = new Transform3D();
tVect.set(platformVect);
Transform3D tXRot = new Transform3D();
Transform3D tYRot = new Transform3D();
Transform3D tZRot = new Transform3D();
tXRot.rotX(xAngle);
tYRot.rotY(yAngle);
tZRot.rotZ(zAngle);
tVect.mul(tYRot);
tVect.mul(tXRot);
tVect.mul(tZRot);
targetTG.setTransform(tVect);

[/b]

Well, I guess that it might be very similar to your own code, but I will of course try yours asap to be sure !
Whatever will be the result of this study, a lot of thanks to you and all those who were trying to help me here and on the other forum.

I hope you’re not creating new objects with each method call as your code would suggest.

There is more then one way to get what you want, but you’ll need to understand the concept of transforms. I’d suggest you go through some J3D examples first, then read the javadoc for Transform3D and Vector3f… useful stuff.

if Transform3D is a 4x4 matrix, it would only waste performance to create 3 new matrices to store the rotation in each - then multiply them together.


Transform3D a = new Transform3D();
a.set(...);
Transform3D rot = new Transform3D();
rot.rotY(...);
a.mul(rot);

is exactly the same as:


Transform3D a = new Transform3D();
a.set(...);
a.rotY(...);

So the pitch/roll/yaw would look like this:


Transform3D a = new Transform3D();
a.set(...);
a.rotY(yAngle); // note: order=y,x,z
a.rotX(xAngle);
a.rotZ(zAngle);

I’m not so sure about that… looking into javadocs:
set(V3f) - Sets the translational value of this matrix to the Vector3f parameter values, and sets the other components of the matrix as if this transform were an identity matrix.
rotX/Y/Z(double) - Sets the value of this transform to a counter clockwise rotation about the x/y/z axis. All of the non-rotational components are set as if this were an identity matrix.

…so no, it’s not the same.

Wow, you are right…

Didn’t expect that. This goes straight into expected behavior for a transform (aka: matrix) class.

Well, then use an alternative matrix-class and pump the results into your Transform3D, as in code where performance matters, multiplying a matrix by a matrix is rather wasteful, while the rotX/Y/Z functions are much more efficient.

Hmm, just a question.

If you’re creating a doom-style camera, you should not need ROLL at all, right?

PITCH is the rotation up/down, and YAW is the rotation about one’s vertical axis.
While ROLL is the rotation about the direction of travel.

That is, PITCH is the rotation about the y-axis, YAW is about z-axis, and ROLL is about x-axis.

Personally, I would use PITCH and YAW for a doom-style camera.

This DOES depend on which hand-orientation you’re using. Java3D uses the right-hand notation and so do I.

I hope this is to the topic.

I think that’s the point- he was getting Roll and he didn’t want it.