Archived

This topic is now archived and is closed to further replies.

Steelrose

Tracking a point on a model

Recommended Posts

Steelrose    122
Hey fokes, as a few of you may know I''m trying to create a spaceshooter. I need some help on getting something working right. I''m trying to set up the players craft so the shots come from predefined points on the ship, or gunports. Right now they come from the center of the player, and when I try to set a location to fire from it works oddly. I''ll try to explain. Say as if I set the gunport at -1,-1, 3. I can get the rotations and such to match so it fires straight, but the shot comes from a location that is relitive to the globel x,y,z axis. So when I turn in a direction the gunport doesn''t move with the ship. The world location does but it fires from the globel location. if anyone understands this (or even the way I wrote it) please give me an idea on what I am missing. I had thought about creating a model for the player that isn''t drawn and tracking points to fire from but I''m not sure that''s possible.

Share this post


Link to post
Share on other sites
Crispy    556
I didn''t read the explanation in your post too thoroughly, but (based on the rest of your post) if you''re using a static model (such as a space ship) that has its guns always fixed in the same position relative to the origin of the model, you could translate to the model''s origin, add the ship''s rotations on each axis and then translate to the guns themselves. Use several nested glPushMatrix() and glPopMatrix() calls to make your job easier.

Once you''ve translate to the mouth of the gun, you add its rotation relative to the ship''s forward heading and you''ve go yourself the point where the projectiles come from and the direction in which they travel (this way you can have guns that can be adjusted (aimed) without rotating the ship itself).

If you''re having a hard time understanding this, don''t hesitate to ask.

Share this post


Link to post
Share on other sites
Steelrose    122
I think I understand, but could you explain a little more clearly. I tried to translate the players rotations to the model and then add the starting location. That didn''t work very well. Could you give a better explaination of the useage of a model and how would I track the points to use?

Share this post


Link to post
Share on other sites
Crispy    556
Sure.

Let's bring a 2D example with the following shape:


*****
*** ***
| * o * |
* *
***


"o" is the origin of the spaceship (a pivot that is always relative to the (0, 0, 0) position (origin) of the world). Let's suppose each letter placeholder is one unit in gl space and that the straight lines are turrets. In that case the left gun has an offset of (-3, 0) relative to "o" and the right gun has an offset of (3, 0) relative to "o".

When you draw your scene, you "reset the world" (the modelview matrix) by calling glLoadIdentity(). At this point your translation matrix has no practical meaning (it points to (0, 0, 0)). If you now translate to "o", you're at the origin of the ship. If the ship is rotated in any way, you need to add the rotations now. Now all of the points on the ship are rotated (more precisely, it's the modelview matrix that is rotated). If you now translate (-3, 0), you'll end up at the tip of the left turret (left on the ASCII image above). If you then want to get to the right turret, you'll have to either 1) make up for the previous translation, eg translate (6, 0), or 2) memorize the modelview matrix prior to your last translation and translate (3, 0).

Let's covert this to pseudo code:

LoadIdentity();

PushMatrix();
Translate(Ship_Origin);
Rotate(Ship_Rotation_on_all_axis);

Render(Ship);

PushMatrix();
Translate(-3, 0); //the left turret
Rotate(Left_Turret_Rotation); //wanna rotate your turrets as well?
Spawn(Projectile);
PopMatrix();

PopMatrix();
Translate(3, 0); //the right turret
Rotate(Right_Turret_Rotation);
Spawn(Projectile);
PopMatrix();
PopMatrix();

//now the modelview matrix is centered back on the world origin


Did that make it clearer?

edit: formatting

[edited by - crispy on September 2, 2003 6:16:46 PM]

Share this post


Link to post
Share on other sites
Steelrose    122
So let me get this straight.

I need to first translate the ship, then push matrix and translate the shot, poping then translates to the ship, then popping again moves the ship the the location in the world.

Does this apply to a first person system?

[edited by - Steelrose on September 2, 2003 6:57:30 PM]

Share this post


Link to post
Share on other sites
Crispy    556
Do you know what a stack is? Anyway - a stack is mostly a FIFO or FILO strcuture (FIFO - first-in-first-out, FILO - first-in-last-out). OpenGL allows you to push the currently selected matrix into a FILO stack. As a rule items are _pushed_ into a stack and _popped_ from the stack. Hence, when you call glPushMatrix(), you store the current modelview matrix (world rotation/translation/scale) in an internal stack. When you call another glPushMatrix() right after it, you''ll push the first matrix a notch deeper and to access it again, you''d now have to call glPopMatrix() twice.

What this means is that - when you call glTranslatef(), glScalef() or glRotatef(), you modify the current modelview matrix (you morph the world).

Usually you want to add many objects to your scene, but you don''t always want to calculate the necessary coordinates for each of the vertices. Instead you know one point that you have a very good understanding where it has to reside in the virtual world relative to the absolute origin (the (0, 0, 0) after you call glLoadIdentity()). In that case, you use glTranslatef() to move to that location and render the object there. By this you, however, modify the modelview matrix (you move the entire world to a new location). To draw another object elsewhere in the scene using the same method, you''ll need to know where the previous "world" was. This is what glPushMatrix() and glPopMatrix() do. Strange to thing that everything in your little virtual world is described by a puny 4x4 matrix, isn''t it?

Share this post


Link to post
Share on other sites
Crispy    556
quote:
Original post by Steelrose
I need to first translate the ship, then push matrix and translate the shot, poping then translates to the ship, then popping again moves the ship the the location in the world.



0) push the matrix
1) you translate to the ship''s coordinates
2) push the matrix
3) translate to the turret where you can add your projectile
4) popping now takes you back to the ship''s coordinates (1)
5) popping one more time takes you back to the world origin (0)

quote:

Does this apply to a first person system?



this applies to any system.

Share this post


Link to post
Share on other sites
JohnyB    122
Thanks! I get it now I still want to do some reading to find out a little more I think I read some of this on the OpenGL Red Book. Don''t know where though, I''m still going through it anyway, thanks for the help again.

Share this post


Link to post
Share on other sites
Steelrose    122
I don''t think it''s gonna work very well. I''ll post some code so you can take a look.


bool FireWeapon(void)
{
ACTOR *newshot;
newshot = new ACTOR;

newshot->worldPos = player->worldPos; //get players position

newshot->rot = player->rot; //get players rotation

newshot->rightVector = player->rightVector; //get players right hand vector

newshot->upVector = player->upVector; //get players up hand vector

newshot->rotation = player->rotation; //get players rotation stored as QUATERNION

newshot->directionVector = player->directionVector; //get players foward vector


switch(player->typeshot)
{
case SHOT1:
newshot->type = Weapon1.type; //Set the actor type

newshot->typeshot = Weapon1.typeshot; //Set the shot type

newshot->active = Weapon1.active; //Activate the actor

newshot->radius = Weapon1.radius; //Set the actors radius

newshot->mass = Weapon1.mass; //Calculate the actors mass

newshot->normalMaxVelocity = Weapon1.normalMaxVelocity;
newshot->currentMaxVelocity = Weapon1.currentMaxVelocity; //Setup the max velocities

newshot->forward = Weapon1.forward;
newshot->damage = Weapon1.damage;
newshot->lifeTime = Weapon1.lifeTime;
newshot->rechargeTime = Weapon1.rechargeTime;
break;
case SHOT2:
newshot->type = Weapon2.type; //Set the actor type

newshot->typeshot = Weapon2.typeshot; //Set the shot type

newshot->active = Weapon2.active; //Activate the actor

newshot->radius = Weapon2.radius; //Set the actors radius

newshot->mass = Weapon2.mass; //Calculate the actors mass

newshot->normalMaxVelocity = Weapon2.normalMaxVelocity;
newshot->currentMaxVelocity = Weapon2.currentMaxVelocity; //Setup the max velocities

newshot->forward = Weapon2.forward;
newshot->damage = Weapon2.damage;
newshot->lifeTime = Weapon2.lifeTime;
newshot->rechargeTime = Weapon2.rechargeTime;
break;
default:
break;
}

ShotList.Append(newshot);

return true;
}


Everything in stored in classes. This bit is called when the player presses the fire key on the keyboard. Weapon1 and Weapon2 are predefined elsewhere in the program. This bit just takes data from the player and sets up the location. Then depending on the weapon fired, takes and copies data from the predefined weapon. After all this is done, it places the data into a linked list that I have written to I can access and manipulate the data. This is where I need to move the shot to the gunport.

I tried using the glPushMatrix and glPopMatrix but it doesn''t seem to work in this portion of the program. I know I am missing something but I can''t figure out what.

Share this post


Link to post
Share on other sites
Crispy    556
quote:
Original post by Steelrose
I don''t think it''s gonna work very well. I''ll post some code so you can take a look.



Does this mean that it doesn''t work or that you haven''t tried? What I described is trivial translation theory. If the projectile isn''t spawned at the correct position it''s either because you''re not doing everything correctly (the source code you posted is pretty irrelevant to thatr particular problem), you''re not stating your problem correctly or you''re building off of incorrect information.

If you''re having a specific problem, describing it in more detail will end up benefiting everyone.

Share this post


Link to post
Share on other sites
Steelrose    122
Yes I have tried to get the translation to work correctly using push and pop and no it didn't work. if you will recall:

/*
I tried using the glPushMatrix and glPopMatrix but it doesn't seem to work in this portion of the program. I know I am missing something but I can't figure out what.
*/

Now I will try to explain the problem in more detail.
The ship apperently has an xyz axis that is aligned with the world xyz axis. translating the gunport translates it on this axis. Therefore when I rotate the craft the gunport is translated on that axis and not on the direction vector of the ship. In other words, a shot that is supposed to fire from the right of the ship fires from the left when you rotate 180 degrees on the y axis.

Edit:
Just thought of a bit of data I left out. The shots and ships are rendered at different times. First the ships then in a seperate function, the shots. The shots are created and placed into a linked list and when the time comes to draw them, the program goes through the list and draws them after checking for collision and translating and so-forth.

[edited by - Steelrose on September 3, 2003 2:26:59 PM]

Share this post


Link to post
Share on other sites
Crispy    556
Hmm - I think you''re confused about something (and now you''re getting me slightly confused ).

Anyway, let''s start with the more trivial stuff: you can''t have an xyz axis. x, y and z are separate axes by themselves, if you pair them you get a plane (as in xz plane, xy plane) and all together they form a 3D space.

It seems to me you''re not applying the ship''s rotation after you translate to its origin, but that can''t really be the problem. Make sure you''re not applying any other rotations between drawing the ship and the projectiles - if you do, you''ll need to encapsulate these with respective glPushMatrix() and glPopMatrix() calls as well; if you get your code working, do your best to remove as many of these calls as possible, though - it will only be good for the performance). I can''t really tell from your description, but you could also be experiencing Gimbal lock - don''t use right angles and stuff in your rotations to be sure.

If all else fails, try creating an empty scene (just comment out all other code), place the ship at the world origin, allow it to rotate (but not move) and try to get the projectile position right. Then, when you''re sure it works, add all kinds of translation and gunport rotation (if you wish) stuff. I think you have a bug in your code that you''re not aware of. If you can''t tell where it is, start commenting out portions of code - it that''s the most effective method.

Share this post


Link to post
Share on other sites
Steelrose    122
Well I am happy to say I figured out what the hell I was doing wrong. And the solution was suprisingly easy.

To give a quick sum up. In the code I had posted above I (finally) noticed that I had vectors for up, right, and forward. I realized that I had the axis for the shot right there. So I multiplied the x,y,z of the shot location with the correct vector and bingo, works like a charm.

And in case anyone was wondering, I am using Trent''s 3d space code for the basis of my own program.

Thanks to those who gave help in any way. Turns out you wern''t wrong, I just described the problem wrong.

Share this post


Link to post
Share on other sites