Sign in to follow this  
medevilenemy

6DOF, and my game

Recommended Posts

I've been working on a new project for a few months now, and I'm now working on the weapon/projectile related functions and I have gradually come to notice that there are a couple issues with the way i'm handling 6DOF motion. I'm using a modified form of JYK's OpenGLObject class to handle placing and rotating objects and it itself works fine. I've noticed, however, that there is no clear way to determine absolute orientations within the game world (in a way reportable to the player, like angles or a bearing or whatever) and more importantly, there doesn't seem to be any clear way to determine absolute distances and relative orientations between objects (which is something I'll need for the AI and for collision detection. What I'm basically trying to ask is: can anyone suggest something that maintains proper 6DOF functionality (rotations/motion) but includes some practical way to determine absolute relations and values? (for those who are curious, here -- http://www.sendspace.com/file/ftezv9 -- is a recent (this afternoon) screenshot of the game. The only significant thing of note is the new HUD layout I added in last night. (the old HUD was really space-consuming and clunky. Things you cant see in the screenie: rotational controls are on the keyboard, but I also recently added mouse controls after not doing anything for a couple months, and the starfield does rotate appropriately with camera rotation)

Share this post


Link to post
Share on other sites
If you are using some sort of scene graph, there should be no problem at all.
Scene graphs provide you with all the information necessary.

If you don't, let me give you a quick introduction.
A scene graph is a tree data structure that organizes objects and operations
by their spatial information - so to speak, their position.
Each node in the tree stors its relative position to its father's position,
and its orientation relative to its father's.
Getting info about absolute position and orientation is only a means of
adding up the available information starting from the root node up to the node
your object resides in.
Translation (relative position) and rotation (relative orientation) are
information which reside in special node types, as well as e.g. texturing info
and material parameters (this is not necessarily the case, but common).
If you want differential information on two objects, you can determine the first
common father node both share, and calculate spatial info for both objects
relative to that node; then all you need to do is subtract both values and you
have your differential information.

There are several types of scene graphs, which basically differ in the number of
space subdivisions per node, but with all the principle of organizing data and
retrieving this data is the same.

If you ask how to organize the handling of objects within the tree, this is just
a question of collision - with using scene graphs, you can reduce almost all
problems to collision.
Determining the node an object is put into so is really just a collision test
with a node's bounding box; the smallest box you find where your object fits in
completely is the node to put it into.

Share this post


Link to post
Share on other sites
I am not currently using a scene graph. I am using jyk's OpenglObject class to handle the actual rotation and motion, which uses a series of Vector3 (3D vector) objects to store the actual data.

Share this post


Link to post
Share on other sites
Another thought: I've looked into scene graphs, and I don't think they are quite necessary for my game. I can handle things relatively easily with lists of objects, and a handler for each type... but those handlers can't do their jobs if I don't have a practical way to compare specific relations/etc.

Share this post


Link to post
Share on other sites
So you are using a list of objects that have spatial information in them...
that means your problem is more of a mathematical problem class than of a code
problem class, as your objects already bear all the information necessary.

Grab yourself a math textbook doing vector math and linear algebra, this should
be sufficient information for you to solve the problem on your own.

I mean, when you use a plain object list, that stores some vector3 instances that
make up the spatial information, than every object has it's absolute distance from
the system origin and it's absolute rotation to where it is heading in itself;
all you must do is expose this information, get the info of two objects, and
compute the differential info of those like it's shown in the book.

Share this post


Link to post
Share on other sites
I could try to pull the data I need out of the matrix/vectors, but there is a lot of information stored in there... a lot a lot of information. And it is rather hard to figure out what is stored where... I realize I did not explain that well... sorry about that one.

Share this post


Link to post
Share on other sites

If you can get a forward vector and create a normal vector from it (project a line segment from your position to a second point distance 1 along the views facing), then you could find/extract the angles like a bearring on the XY reference plane (compass direction) and up/down angle off that surface plane(or rather a coplanar at eye level). That would be fairly basic trig.

Absolute distances should be extractable from XYZ positions differences between the source and target. Relative orientations for a reference plane based on the cooedinate system would likewise just be trig.

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
I could try to pull the data I need out of the matrix/vectors, but there is a lot of information stored in there... a lot a lot of information. And it is rather hard to figure out what is stored where... I realize I did not explain that well... sorry about that one.


so you are actually asking what the data in the matrix and vectors represent so you can then understand which values to punch-into an equation? or are you asking for the equation? or both? I won't be able to answer either way, but I can see how clarifying this might help others to help you.

Share this post


Link to post
Share on other sites
These are the variables in the "OpenglObject" class which store the relevant dataL

Vector3 m_pos;
Vector3 m_side;
Vector3 m_up;
Vector3 m_forward;
Vector3 m_upMove;
Vector3 m_forwardMove;

Basically, I have to figure out which vector stores what values, and then write a couple little general functions to extract it (which shouldn't be too hard... although I don't have experience working with C++ vector classes -- although I do know the trig/vector math)

Thanks for all the help, everyone.

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
These are the variables in the "OpenglObject" class which store the relevant dataL

Vector3 m_pos;
Vector3 m_side;
Vector3 m_up;
Vector3 m_forward;
Vector3 m_upMove;
Vector3 m_forwardMove;

Basically, I have to figure out which vector stores what values, and then write a couple little general functions to extract it (which shouldn't be too hard... although I don't have experience working with C++ vector classes -- although I do know the trig/vector math)

Thanks for all the help, everyone.



I'm not sure what you want, but if you want to create a 3 by 3 orientation matrix for an object, you use the following format, assuming forward = x, up = y, side = z:


R = [ x.x y.x z.x ]
[ x.y y.y z.y ]
[ x.z y.z z.z ]


If those vectors are all unit vectors, then that should be a valid orthogonal rotation matrix. pos is the position of the object. I'm not sure what upMove and forwardMove are though, maybe velocity?

I suggest that you learn how to do the math yourself, and write your own class for scene management. It will give you lots of experience that you wouldn't have otherwise. The reasons why people like me know about all of these things is not because we asked for help on a forum, but because we took the time to actually figure it out for ourselves. It's been proven that you learn much better by teaching yourself than you do by acting in a monkey see, monkey do fashion, though it's generally a bit more painful at first.

Share this post


Link to post
Share on other sites
Again, I apologize for doing such a bad job of explaining my question. I have these vectors, what I'm trying to do is pull out specific orientation related angles from them (whatever works, preferably roll, pitch, yaw if they would work), specific velocities of motion (i assume that is what upmove and forwardmove are, but that makes me wonder why there isnt a sidemove) and if possible a specific location in the global coordinate system (basically, pull the displacement out of the matrix, and apply it to the global system to get a global coordinate position). I just don't how to properly access vectors in C++. I know the mathematics of vectors, but how do I apply that to a data object?

Share this post


Link to post
Share on other sites
That totally depends on the implementation of the vector class, as in standard
C++ there is no such class; thus, everybody solves this problem in his own way,
although each and every one of it still represents a vector...

So, either you provide more info (on the scene org class you use, the vector class
and the matrix class and how their interface looks like) or (preferably) you go
looking for it yourself; if you know the math, as you claim, it shouldn't be too
hard to identify which method does what and delivers what.

Either way, I would strongly suggest you to do some basic research in scene
management on your own and start writing your own class which serves the basic
needs before you go and use other people's (probably more advanced) classes,
as you need to have done it yourself at least once to be able to grasp what's
going on.
Start with a quadtree structure maybe, it should provide you with a reasonable
understanding on how scene management works, what data you will come across
and what this data represents; quadtrees are easy enough to go for a start since
they are basically two-dimensional - the 3d equivalent would be octrees, which
work the same way, but might be a but too complicated to follow for a start.

And, by the way, the names of the vectors in that class are fair enough
self-explanatory; all it takes is a little bit of reading and it jumps off your
head what the meaning of all those vectors is; and, btw, you claim you know vector
math and linear algebra, so why don't you know trigonometry - or why is it that
you seem unable to calculate angles from vector components?

Share this post


Link to post
Share on other sites
I do know how... I just don't know how to access the various parts of the vector object... I'll go digging around in the class, and hopefully I'll find a function to return the magnitude and direction. I don't know if its there, but I hope so.

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
These are the variables in the "OpenglObject" class which store the relevant dataL

Vector3 m_pos;
Vector3 m_side;
Vector3 m_up;
Vector3 m_forward;
Vector3 m_upMove;
Vector3 m_forwardMove;

Basically, I have to figure out which vector stores what values, and then write a couple little general functions to extract it (which shouldn't be too hard... although I don't have experience working with C++ vector classes -- although I do know the trig/vector math)

Thanks for all the help, everyone.


I'm going to take a stab here...

Imagine a person standing still just blankly staring forward...

m_pos = the bottom-most point and directly between the feet (the bottom of the bounding-box)
m_side = the right-most point (maybe left instead) and sits roughly around the person's elbow (the right/left side of the bounding-box)
m_up = i'm sure you see where i am going with this... the top of the head (the top of the bounding-box)
m_forward = somewhere around the belly-button (the front of the bounding-box... this could be because the bounding-box isn't a 2D square stretched to a 3D rectangle, but rather a 2D rectangle stretched to a 3D rectangle and therefore you can't just rely on the m_side value to determine the front and back dimensions as well)
m_upMove = the velocity per frame towards the m_up vector
m_forwardMove = the velocity towards the m_forward vector

Now most people of normal thinking probably would have (like myself) had rotation values for the different axis etc, but if what i have said for the different vector vars is correct then i would have to say it appears that instead of simple bounding-box and rotation values this instead has the ALREADY rotated information... so to discover what the rotation values applied were you will need to reverse-rotate (i think i just made that up) back to the original forward-facing position you (and me) would have expected to have started with and not what appears to be here.

If that doesn't make sense to you then think of it this way... imagine yourself facing forward and you have golf-balls stuck to your body in the positions i mentioned earlier. now randomly walk around and look at something, and add a little forward lean, and side lean. The golf-balls now roughly represent what it seems you have in the vector variables you are trying to figure-out.

I'm guessing there is no m_sideMove because whatever the thing is that these variable represent doesn't have a "strafe" movement and only goes wherever it's facing and with a possible vertical "jump" or "fall" etc.

I'm probably speaking rubbish and would be interested in what the data actually does represent if i am wrong.

Share this post


Link to post
Share on other sites
Well, its one of jyk's utility classes, not mine, so all I can tell you is that I am using it to handle the motion of Spacecraft/other spatial objects in a 3D Space based pseudo rpg type thing I'm working on (I really don't have a better name than that for it right now, sorry). You are probably right about the vectors, but one thing seems odd about that... if they represent motion in a single direction, it doesn't make sense for them to be vectors... since vectors represent a combination of a magnitude and and angle, not just a magnitude. In any case, I will have to figure it out before I can implement any collision detection or the AI.

Thanks for the feedback, though... It may prove useful once this all gets settled.

Share this post


Link to post
Share on other sites
Since I wrote the aforementioned OpenGLObject class, I'll go ahead and chime in with some clarification.

The class supports movement along each of the three axes (forward/backward, up/down, and strafe). The reason there are separate 'move' vectors for forward and up is that the class supports three different types of object/camera motion. The three modes are:

1. FPS. Similar to a character in a first-person shooter. Forward/backward motion is always in the ground plane, and up/down motion is always along the world up axis. Given that the character can (presumably) pitch the view up and down, the forward and up orientation vectors may be different than the forward and up movement vectors, hence the separate 'move' vectors for these axes.

2. FPS spectator. Similar to FPS, except that forward motion is along the view vector rather than being constrained to the ground plane (allowing you to 'fly'). In this case the forward move vector corresponds to the forward orientation vector, but the up move vector is still the world up vector (which may or may not correspond to the orientation up vector).

3. 6DOF. Motion is always along the local axes, so the 'move' vectors always correspond to the 'orientation' vectors.

The reason there is no 'side move' vector is that the strafe move vector always corresponds to the side orientation vector, regardless of mode.

Since the OP is using 6DOF mode, the move vectors can effectively be ignored (since they are the same as the corresponding orientation vectors).

Although an Euler-angle triple is a common representation (and due to its intuitiveness and prevalence in tutorials and certain types of games might be considered by some to be the 'normal' representation for orientation), the three orthonormal vectors used by the OpenGLObject class is actually much more straightforward and useful (at least for the 6DOF case). These vectors can easily be converted to matrix or quaternion form if needed (in fact, the class includes functions for conversion to matrix form).

@The OP: I'm not completely clear on the nature of the problem you're trying to solve, but whatever it is, the three basis vectors (plus the position, depending on the nature of the computation) almost certainly provide all the information you need. This representation is the 'absolute orientation' you're looking for (provided it isn't a node down a branch of a scene graph).

For AI, I think the most useful pieces of info would be the position of the enemy in local space (derived by transforming said position by the inverse of the transform matrix, which, by the way, can be queried directly from the OpenGLObject class), and perhaps the relative orientation of the enemy (computable using a little vector and/or matrix math). To provide more details than that, we'd probably have to know more about how you intend to use this information.

Share this post


Link to post
Share on other sites
Ah yeah, thats exactly what I'm trying to do. Basically, the AI needs to be able to tell whether or not its guns (which are separate objects ships carry) is lined up with an enemy ship or object so it can fire at it... and everything (especially projectiles) need to know where they are in global space so they can determine whether or not they are within the bounding box for an object.

I figured all the required information is stored within the object already, I just don't quite know how to pull it out. The reason I was asking about angular measurements is because that is way I can best understand orientation, but if I can somehow write a function to handle it another way that works too. The biggest thing is pulling out the global coordinate location (that is, global in the sense of the main coordinate system where everything is), and orientation data in such a way that I can compare with corresponding data from other objects and determine collisions/line of sight/etc.

Thanks Again!

Share this post


Link to post
Share on other sites
<bump>

also, @jyk: I just noticed some odd behavior with the rotations using the openglobject code (probably my fault). for some reason, when rolled 90 degrees, pitch becomes yaw.

I am including the relevent code below


class PShip
{
private:
void UpdateFromPitchYaw();
void Orthonormalize();
float DegToRad(float angle);
float RadToDeg(float angle);
Vector3 m_pos;
Vector3 m_side;
Vector3 m_up;
Vector3 m_forward;
Vector3 m_upMove;
Vector3 m_forwardMove;
float m_pitch;
float m_yaw;
float acceleration;
float maxvelocity;
float damage; // Damage Dealt Per Bullet
int throttle; // keep between -100 and 100
int energy; // keep between 0 and 100
int weaponheat; // keep between 0 and 100
float currenthp;
float maxhp;
float currentshields;
float maxshields;
bool engineson;
bool shieldson;
bool weaponson;

public:
void Init(float hpc, float hpt, float shieldsc, float shieldst, float dmg);
void Draw(); // Draws the ship model with the appropriate texture at the appropriate angles

Vector3 GetPos() const;
Vector3 GetSide() const;
Vector3 GetUp() const;
Vector3 GetForward() const;
Vector3 GetUpMove() const;
Vector3 GetForwardMove() const;
void SetPos(const Vector3& pos);
void SetMode(int mode);
void Identity();
void ApplyYaw(float angle);
void ApplyPitch(float angle);
void ApplyRoll(float angle);
void MoveAlongSideAxis(float t);
void MoveAlongUpAxis(float t);
void MoveAlongForwardAxis(float t);
void LookAt(const Vector3& pos, const Vector3& target, const Vector3& up);
void SetOpenGLModelMatrix();
void SetOpenGLViewMatrix();
void MultOpenGLModelMatrix();
void MultOpenGLViewMatrix();
void GetModelMatrix(float m[16]) const;
void GetViewMatrix(float m[16]) const;
void Move(
bool yawLeft, bool yawRight,
bool pitchDown, bool pitchUp,
bool rollRight, bool rollLeft,
bool moveLeft, bool moveRight,
bool moveUp, bool moveDown,
bool moveForward, bool moveBack,
float yawSpeed, float pitchSpeed, float rollSpeed,
float sideSpeed, float upSpeed, float forwardSpeed,
float dt);
void ChangeThrottle(int percent); // Changes the value of throttle by percent
void TakeDamage(float amount); // Applies damage to the ship
float GetDamage(void); // Returns the current value of the variable 'Damage'
float GetCurrenthp(void);
float GetMaxhp(void);
float GetCurrentShields(void);
float GetMaxShields(void);
int GetThrottle(void);
int GetEnergy(void);
int GetHeat(void);
void Increasehp(void);
void IncreaseShields(void);
bool IsDead(); // Returns true if the ship is dead or false if it is not
} pShip;

void PShip::Init(float hpc, float hpt, float shieldsc, float shieldst, float dmg)
{
Identity();
m_upMove = m_up;
m_forwardMove = m_forward;
acceleration = 0.01;
acceleration = 0;
maxvelocity = 0;
throttle = 0;
energy = 100;
weaponheat = 0;
damage = dmg;
currenthp = hpc;
maxhp = hpt;
currentshields = shieldsc;
maxshields = shieldst;
engineson = true;
shieldson = true;
weaponson = true;
}

void PShip::Draw()
{
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHT1);
//DrawObj(models[0], 0, 0, 0, -2.0); // Draw Ship Model
glColor4d(1.0, 0.0, 0.0, 1.0);
/*glBegin(GL_QUADS);
glVertex3d(-1, 1, zz);
glVertex3d(1, 1, zz);
glVertex3d(1, -1, zz);
glVertex3d(-1,-1, zz);
glEnd();*/

glPushMatrix();
MultOpenGLModelMatrix();
starfield.Draw();
glPopMatrix();
glDisable(GL_LIGHT1);

}
// INSERT FUNCTIONS HERE

Vector3 PShip::GetPos() const {return m_pos;}
Vector3 PShip::GetSide() const {return m_side;}
Vector3 PShip::GetUp() const {return m_up;}
Vector3 PShip::GetForward() const {return m_forward;}
Vector3 PShip::GetUpMove() const {return m_upMove;}
Vector3 PShip::GetForwardMove() const {return m_forwardMove;}
void PShip::SetPos(const Vector3& pos) {m_pos = pos;}
void PShip::Identity()
{
m_pos.set(0.0f, 0.0f, 0.0f);
m_side.set(1.0f, 0.0f, 0.0f);
m_up.set(0.0f, 1.0f, 0.0f);
m_forward.set(0.0f, 0.0f, 1.0f);
m_upMove = m_up;
m_forwardMove = m_forward;
m_pitch = 0.0f;
m_yaw = 0.0f;
}
void PShip::ApplyYaw(float angle)
{
// Rotate side and forward about up

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 forward = c * m_forward + s * m_side;
Vector3 side = c * m_side - s * m_forward;

m_side = side;
m_forward = forward;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::ApplyPitch(float angle)
{
// Rotate up and forward about side

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 up = c * m_up + s * m_forward;
Vector3 forward = c * m_forward - s * m_up;

m_up = up;
m_forward = forward;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::ApplyRoll(float angle)
{
// Rotate side and up about forward

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 side = c * m_side + s * m_up;
Vector3 up = c * m_up - s * m_side;

m_side = side;
m_up = up;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::MoveAlongSideAxis(float t)
{
m_pos += m_side * t;
}
void PShip::MoveAlongUpAxis(float t)
{
m_pos += m_upMove * t;
}
void PShip::MoveAlongForwardAxis(float t)
{
m_pos += m_forwardMove * t;
}
void PShip::LookAt(const Vector3& pos, const Vector3& target, const Vector3& up)
{
m_forward = target - pos;
m_forward.normalize();
m_side = up.cross(m_forward);
m_side.normalize();
m_up = m_forward.cross(m_side);
m_pos = pos;
}
void PShip::SetOpenGLModelMatrix()
{
float m[16];
GetModelMatrix(m);
glLoadMatrixf(m);
}
void PShip::SetOpenGLViewMatrix()
{
float m[16];
GetViewMatrix(m);
glLoadMatrixf(m);
}
void PShip::MultOpenGLModelMatrix()
{
float m[16];
GetModelMatrix(m);
glMultMatrixf(m);
}
void PShip::MultOpenGLViewMatrix()
{
float m[16];
GetViewMatrix(m);
glMultMatrixf(m);
}
void PShip::GetModelMatrix(float m[16]) const
{
m[0] = m_side[0];
m[1] = m_side[1];
m[2] = m_side[2];
m[3] = 0.0f;

m[4] = m_up[0];
m[5] = m_up[1];
m[6] = m_up[2];
m[7] = 0.0f;

m[8] = m_forward[0];
m[9] = m_forward[1];
m[10] = m_forward[2];
m[11] = 0.0f;

m[12] = m_pos[0];
m[13] = m_pos[1];
m[14] = m_pos[2];
m[15] = 1.0f;
}
void PShip::GetViewMatrix(float m[16]) const
{
m[0] = -m_side[0];
m[1] = m_up[0];
m[2] = -m_forward[0];
m[3] = 0.0f;

m[4] = -m_side[1];
m[5] = m_up[1];
m[6] = -m_forward[1];
m[7] = 0.0f;

m[8] = -m_side[2];
m[9] = m_up[2];
m[10] = -m_forward[2];
m[11] = 0.0f;

m[12] = m_pos.dot(m_side);
m[13] = -m_pos.dot(m_up);
m[14] = m_pos.dot(m_forward);
m[15] = 1.0f;
}
void PShip::UpdateFromPitchYaw()
{
float sp = sinf(DegToRad(m_pitch));
float cp = cosf(DegToRad(m_pitch));
float sy = sinf(DegToRad(m_yaw));
float cy = cosf(DegToRad(m_yaw));

m_side.set(cy, 0.0f, -sy);
m_forward.set(sy * cp, -sp, cy * cp);
m_up = m_forward.cross(m_side);

m_upMove.set(0.0f, 1.0f, 0.0f);
m_forwardMove = m_forward;
}
void PShip::Orthonormalize()
{
m_forward.normalize();
m_side = m_up.cross(m_forward);
m_side.normalize();
m_up = m_forward.cross(m_side);
}
void PShip::Move(
bool yawLeft, bool yawRight,
bool pitchDown, bool pitchUp,
bool rollRight, bool rollLeft,
bool moveLeft, bool moveRight,
bool moveUp, bool moveDown,
bool moveForward, bool moveBack,
float yawSpeed, float pitchSpeed, float rollSpeed,
float sideSpeed, float upSpeed, float forwardSpeed,
float dt)
{
if (yawLeft)
ApplyYaw(yawSpeed * dt);
if (yawRight)
ApplyYaw(-yawSpeed * dt);
if (pitchDown)
ApplyPitch(pitchSpeed * dt);
if (pitchUp)
ApplyPitch(-pitchSpeed * dt);
if (rollRight)
ApplyRoll(rollSpeed * dt);
if (rollLeft)
ApplyRoll(-rollSpeed * dt);
if (moveLeft)
MoveAlongSideAxis(sideSpeed * dt);
if (moveRight)
MoveAlongSideAxis(-sideSpeed * dt);
if (moveUp)
MoveAlongUpAxis(upSpeed * dt);
if (moveDown)
MoveAlongUpAxis(-upSpeed * dt);
if (moveForward)
MoveAlongForwardAxis(forwardSpeed * dt);
if (moveBack)
MoveAlongForwardAxis(-forwardSpeed * dt);
}
float PShip::DegToRad(float angle)
{
const float DEG_TO_RAD = (atanf(1.0f) * 4.0f) / 180.0f;
return angle * DEG_TO_RAD;
}
// --------------------------------------------------------------------------------------
float PShip::RadToDeg(float angle)
{
const float DEG_TO_RAD = 180.0f / (atanf(1.0f) * 4.0f);
return angle * DEG_TO_RAD;
}

void PShip::ChangeThrottle(int percent)
{
throttle+=percent;

if(throttle > 100)
throttle = 100;
if(throttle < -100)
throttle = -100;
}
void PShip::TakeDamage(float amount)
{
if(shieldson && currentshields > 0 && currenthp >= 0)
{
currentshields -= amount;

if(currentshields < 0)
{
currenthp += currentshields; //Transfer overflow to hull
currentshields = 0;
}
}
else if(!shieldson || currentshields == 0)
{
currenthp -= amount;
}
}

float PShip::GetCurrenthp(void)
{
return currenthp;
}
float PShip::GetMaxhp(void)
{
return maxhp;
}
float PShip::GetCurrentShields(void)
{
return currentshields;
}
float PShip::GetMaxShields(void)
{
return maxshields;
}
int PShip::GetThrottle(void)
{
return throttle;
}
int PShip::GetEnergy(void)
{
return energy;
}
int PShip::GetHeat(void)
{
return weaponheat;
}




and here is where the main scene is rendered


void MainScreen(void)
{
DrawOverlay(); // ----- THIS DRAWS THE HUD
glEnable(GL_LIGHTING);
gluPerspective(45,1024/768,0.01,1000);
pShip.Draw(); // --- Doesnt actually draw a ship on the screen, rather it is where the rotations are updated
starfield.Draw();
glDisable(GL_LIGHTING);
}



[Edited by - medevilenemy on June 8, 2007 2:32:10 PM]

Share this post


Link to post
Share on other sites
I'm pretty sure the oddness I mentioned in my last post is being caused by applying the rotation code from the openglobject class for the camera... I know... dumb mistake.

Share this post


Link to post
Share on other sites
ok, after hunting through my code, I'm pretty sure the oddness can be settled if I put in a proper 6dof camera (which I have to find). While I'm at that it may be a good idea to replace the openglobject class with something simpler, or at least simplify it (while adding a way to extract angular x,y, and z rotations and an actual xyz coordinate set for position). Does anyone know of any freely usable classes or whatnot to do this?

Any help is greatly appreciated, I'd like to finally be able to move on to other things like weapons and ships (which shouldn't be a problem if I can just get rotation and such working properly [wink]).

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
ok, after hunting through my code, I'm pretty sure the oddness can be settled if I put in a proper 6dof camera (which I have to find). While I'm at that it may be a good idea to replace the openglobject class with something simpler, or at least simplify it (while adding a way to extract angular x,y, and z rotations and an actual xyz coordinate set for position). Does anyone know of any freely usable classes or whatnot to do this?

Any help is greatly appreciated, I'd like to finally be able to move on to other things like weapons and ships (which shouldn't be a problem if I can just get rotation and such working properly [wink]).
I can say with only minimal bias that you should just stick with the code from the OpenGLObject class. It does everything you need, and you're unlikely to find a simpler or more straightforward class offering the same functionality.

The OpenGLObject class fully supports 6DOF motion (perhaps you overlooked this when adapting the code). Take another look at the original source. You'll see that the class supports three modes: FPS, FPS-spectator, and 6DOF. The latter mode will give you the 'space sim' behavior that you seem to be looking for.

The OpenGLObject class has been used a lot (by me and others), and I'm 99.999% sure that it's bug-free and works as advertised. If you run into problems, it's likely that you're just using it incorrectly. If you really get stuck, you can PM me - I might be able to take a look at your code. Keep in mind though that although the OpenGLObject class makes it quite easy to manage simple object and view transforms, you still have to have a decent grasp of 3-D math to use it effectively.

As for getting the info you're asking about, you don't need to extract the position from the transform matrix - the OpenGLObject class has a GetPos() function that returns the position directly. I would also ask, why do you need the xyz rotation angles? My guess is that you don't - you only think you do :)

Sorry I've been a little slow to respond to this thread. I hope the above will clear things up for you a bit, but post back if you have other questions.

Share this post


Link to post
Share on other sites
My code is as posted above. I'm pretty sure the bug I have is being caused by my use of the class as a camera. That, and there is a good chance I messed something up when adapting the code. Basically, I'm trying to use the class as both a camera and as an actual object class and I'm probably doing it wrong.

As for the rotation angles, I admit I'm not really sure the best way to figure out if something is facing something with the code as-is. I bet it involves comparing the vectors directly, but I'd prefer to have a more automatic function (so that I don't have to worry about breaking something while trying to write some otherwise simple targeting code. Angles I can understand in rather natural terms... I'm used to them.

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
My code is as posted above. I'm pretty sure the bug I have is being caused by my use of the class as a camera. That, and there is a good chance I messed something up when adapting the code. Basically, I'm trying to use the class as both a camera and as an actual object class and I'm probably doing it wrong.
Yeah, I can't really tell from your posted code where the problem might be. I see a bunch of stuff that might be wrong, but there's not enough context to say for sure (for example, you haven't shown where the OpenGL matrices are initialized on a per-frame basis, and there are also some places where it's not clear what the matrix mode is).
Quote:
As for the rotation angles, I admit I'm not really sure the best way to figure out if something is facing something with the code as-is. I bet it involves comparing the vectors directly, but I'd prefer to have a more automatic function (so that I don't have to worry about breaking something while trying to write some otherwise simple targeting code. Angles I can understand in rather natural terms... I'm used to them.
Well, I gotta tell you, however 'used to' working with Euler angles you might be, they're just not the right tool for this job. For the type of thing you're talking about (AI, target acquisition and alignment, and so on), it's generally best to start by transforming the target's position (and perhaps orientation) into the local space of the object in question. From there you can compute whatever information you need (for example, whether the target is within a certain field of view, or within the area of effect of a certain weapon) using simple vector math and/or trig.

Share this post


Link to post
Share on other sites
I'm not sure exactly what code you need, but I'll post everything that seems relevant below:


My Initialization Function...

void Initialize(void)
{
int itemstoload = 12;

srand(time(NULL));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);

glEnable(GL_BLEND); // allows blending (transparency)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // allows smooth shading (gradients)

LoadBitmap(".\\bmp\\LoadingScreen.bmp", 36);
listBase[0] = InitFont("Trebuchet MS", 36);
LoadingScreen(1, itemstoload);
listBase[1] = InitFont("Trebuchet MS", 28);
LoadingScreen(2, itemstoload);
listBase[2] = InitFont("Arial",20);
LoadingScreen(3, itemstoload);
listBase[3] = InitFont("Arial Black", 26);
LoadingScreen(4, itemstoload);
listBase[4] = InitFont("Trebuchet MS", 100);
LoadingScreen(5, itemstoload);
listBase[5] = InitFont("Trebuchet MS", 16);
LoadingScreen(6, itemstoload);

LoaderClass.LoadObj(".\\obj\\PShip.obj"); // Load the Player's Ship Model
models[0] = LoaderClass.ReturnObj();
LoadingScreen(7, itemstoload);
LoaderClass.LoadObj(".\\obj\\KEW_Round.obj"); // Load the Kinetic Energy Weapon Round
models[1] = LoaderClass.ReturnObj();
LoadingScreen(8, itemstoload);
LoaderClass.LoadObj(".\\obj\\MPO_Round.obj"); // Load the Magnetically Propelled Ordinance Round
models[2] = LoaderClass.ReturnObj();
LoadingScreen(9, itemstoload);

LoadBitmap(".\\bmp\\PShip.bmp", 0); LoadingScreen(10, itemstoload);
LoadBitmap(".\\bmp\\KEW_Round.bmp", 1); LoadingScreen(11, itemstoload);
LoadBitmap(".\\bmp\\MPO_Round.bmp", 2); LoadingScreen(12, itemstoload);

glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
glMaterialfv(GL_FRONT, GL_SPECULAR, MaterialShiny);
glMateriali(GL_FRONT, GL_SHININESS, 128);

//pShip.Init(100, 100, 100, 100, 10);
pShip.Init(100, 100, 100, 100, 10);
starfield.InitStarfield(MAX_PARTICLE_COUNT, 0.001);

return;

}



My render control function...

void Render(void)
{
int i;
int j = 0;

glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

if(timeGetTime()-lastsec >= 1000)
{
fps = framesthissec;
framesthissec = 0;
lastsec = timeGetTime();
}

timer3 = time(&timer3);
if(difftime(timer3, timer4) >= 1)
{
timer4 = time(&timer4);
}

switch(scrnum)
{
case 0:
MainMenu();
break;
case 1:
MainScreen();
break;
}

frames++;
framesthissec++;

return;
}



And here is the implementation of the openglobject class, modified for use as the camera/player's ship.


class PShip
{
private:
// There are no position coordinates, because the player is always at 0, 0, 0, on the screen
// and dispx, dispy, dispz in the game world

void UpdateFromPitchYaw();
void Orthonormalize();
float DegToRad(float angle);
float RadToDeg(float angle);
Vector3 m_pos;
Vector3 m_side;
Vector3 m_up;
Vector3 m_forward;
Vector3 m_upMove;
Vector3 m_forwardMove;
float m_pitch;
float m_yaw;
float acceleration;
float maxvelocity;
float damage; // Damage Dealt Per Bullet
int throttle; // keep between -100 and 100
int energy; // keep between 0 and 100
int weaponheat; // keep between 0 and 100
float currenthp;
float maxhp;
float currentshields;
float maxshields;
bool engineson;
bool shieldson;
bool weaponson;

public:
void Init(float hpc, float hpt, float shieldsc, float shieldst, float dmg);
void Draw(); // Draws the ship model with the appropriate texture at the appropriate angles

Vector3 GetPos() const;
Vector3 GetSide() const;
Vector3 GetUp() const;
Vector3 GetForward() const;
Vector3 GetUpMove() const;
Vector3 GetForwardMove() const;
void SetPos(const Vector3& pos);
void SetMode(int mode);
void Identity();
void ApplyYaw(float angle);
void ApplyPitch(float angle);
void ApplyRoll(float angle);
void MoveAlongSideAxis(float t);
void MoveAlongUpAxis(float t);
void MoveAlongForwardAxis(float t);
void LookAt(const Vector3& pos, const Vector3& target, const Vector3& up);
void SetOpenGLModelMatrix();
void SetOpenGLViewMatrix();
void MultOpenGLModelMatrix();
void MultOpenGLViewMatrix();
void GetModelMatrix(float m[16]) const;
void GetViewMatrix(float m[16]) const;
void Move(
bool yawLeft, bool yawRight,
bool pitchDown, bool pitchUp,
bool rollRight, bool rollLeft,
bool moveLeft, bool moveRight,
bool moveUp, bool moveDown,
bool moveForward, bool moveBack,
float yawSpeed, float pitchSpeed, float rollSpeed,
float sideSpeed, float upSpeed, float forwardSpeed,
float dt);
void ChangeThrottle(int percent); // Changes the value of throttle by percent
void TakeDamage(float amount); // Applies damage to the ship
float GetDamage(void); // Returns the current value of the variable 'Damage'
float GetCurrenthp(void);
float GetMaxhp(void);
float GetCurrentShields(void);
float GetMaxShields(void);
int GetThrottle(void);
int GetEnergy(void);
int GetHeat(void);
void Increasehp(void);
void IncreaseShields(void);
bool IsDead(); // Returns true if the ship is dead or false if it is not
} pShip;

void PShip::Init(float hpc, float hpt, float shieldsc, float shieldst, float dmg)
{
Identity();
m_upMove = m_up;
m_forwardMove = m_forward;
acceleration = 0.01;
acceleration = 0;
maxvelocity = 0;
throttle = 0;
energy = 100;
weaponheat = 0;
damage = dmg;
currenthp = hpc;
maxhp = hpt;
currentshields = shieldsc;
maxshields = shieldst;
engineson = true;
shieldson = true;
weaponson = true;
}

void PShip::Draw()
{
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHT1);
//DrawObj(models[0], 0, 0, 0, -2.0); // Draw Ship Model
glColor4d(1.0, 0.0, 0.0, 1.0);
/*glBegin(GL_QUADS);
glVertex3d(-1, 1, zz);
glVertex3d(1, 1, zz);
glVertex3d(1, -1, zz);
glVertex3d(-1,-1, zz);
glEnd();*/

glPushMatrix();
MultOpenGLModelMatrix();
starfield.Draw();
glPopMatrix();
glDisable(GL_LIGHT1);

}
// INSERT FUNCTIONS HERE

Vector3 PShip::GetPos() const {return m_pos;}
Vector3 PShip::GetSide() const {return m_side;}
Vector3 PShip::GetUp() const {return m_up;}
Vector3 PShip::GetForward() const {return m_forward;}
Vector3 PShip::GetUpMove() const {return m_upMove;}
Vector3 PShip::GetForwardMove() const {return m_forwardMove;}
void PShip::SetPos(const Vector3& pos) {m_pos = pos;}
void PShip::Identity()
{
m_pos.set(0.0f, 0.0f, 0.0f);
m_side.set(1.0f, 0.0f, 0.0f);
m_up.set(0.0f, 1.0f, 0.0f);
m_forward.set(0.0f, 0.0f, 1.0f);
m_upMove = m_up;
m_forwardMove = m_forward;
m_pitch = 0.0f;
m_yaw = 0.0f;
}
void PShip::ApplyYaw(float angle)
{
// Rotate side and forward about up

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 forward = c * m_forward + s * m_side;
Vector3 side = c * m_side - s * m_forward;

m_side = side;
m_forward = forward;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::ApplyPitch(float angle)
{
// Rotate up and forward about side

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 up = c * m_up + s * m_forward;
Vector3 forward = c * m_forward - s * m_up;

m_up = up;
m_forward = forward;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::ApplyRoll(float angle)
{
// Rotate side and up about forward

float s = sinf(DegToRad(angle));
float c = cosf(DegToRad(angle));

Vector3 side = c * m_side + s * m_up;
Vector3 up = c * m_up - s * m_side;

m_side = side;
m_up = up;

m_upMove = m_up;
m_forwardMove = m_forward;

Orthonormalize();
}
void PShip::MoveAlongSideAxis(float t)
{
m_pos += m_side * t;
}
void PShip::MoveAlongUpAxis(float t)
{
m_pos += m_upMove * t;
}
void PShip::MoveAlongForwardAxis(float t)
{
m_pos += m_forwardMove * t;
}
void PShip::LookAt(const Vector3& pos, const Vector3& target, const Vector3& up)
{
m_forward = target - pos;
m_forward.normalize();
m_side = up.cross(m_forward);
m_side.normalize();
m_up = m_forward.cross(m_side);
m_pos = pos;
}
void PShip::SetOpenGLModelMatrix()
{
float m[16];
GetModelMatrix(m);
glLoadMatrixf(m);
}
void PShip::SetOpenGLViewMatrix()
{
float m[16];
GetViewMatrix(m);
glLoadMatrixf(m);
}
void PShip::MultOpenGLModelMatrix()
{
float m[16];
GetModelMatrix(m);
glMultMatrixf(m);
}
void PShip::MultOpenGLViewMatrix()
{
float m[16];
GetViewMatrix(m);
glMultMatrixf(m);
}
void PShip::GetModelMatrix(float m[16]) const
{
m[0] = m_side[0];
m[1] = m_side[1];
m[2] = m_side[2];
m[3] = 0.0f;

m[4] = m_up[0];
m[5] = m_up[1];
m[6] = m_up[2];
m[7] = 0.0f;

m[8] = m_forward[0];
m[9] = m_forward[1];
m[10] = m_forward[2];
m[11] = 0.0f;

m[12] = m_pos[0];
m[13] = m_pos[1];
m[14] = m_pos[2];
m[15] = 1.0f;
}
void PShip::GetViewMatrix(float m[16]) const
{
m[0] = -m_side[0];
m[1] = m_up[0];
m[2] = -m_forward[0];
m[3] = 0.0f;

m[4] = -m_side[1];
m[5] = m_up[1];
m[6] = -m_forward[1];
m[7] = 0.0f;

m[8] = -m_side[2];
m[9] = m_up[2];
m[10] = -m_forward[2];
m[11] = 0.0f;

m[12] = m_pos.dot(m_side);
m[13] = -m_pos.dot(m_up);
m[14] = m_pos.dot(m_forward);
m[15] = 1.0f;
}
void PShip::UpdateFromPitchYaw()
{
float sp = sinf(DegToRad(m_pitch));
float cp = cosf(DegToRad(m_pitch));
float sy = sinf(DegToRad(m_yaw));
float cy = cosf(DegToRad(m_yaw));

m_side.set(cy, 0.0f, -sy);
m_forward.set(sy * cp, -sp, cy * cp);
m_up = m_forward.cross(m_side);

m_upMove.set(0.0f, 1.0f, 0.0f);
m_forwardMove = m_forward;
}
void PShip::Orthonormalize()
{
m_forward.normalize();
m_side = m_up.cross(m_forward);
m_side.normalize();
m_up = m_forward.cross(m_side);
}
void PShip::Move(
bool yawLeft, bool yawRight,
bool pitchDown, bool pitchUp,
bool rollRight, bool rollLeft,
bool moveLeft, bool moveRight,
bool moveUp, bool moveDown,
bool moveForward, bool moveBack,
float yawSpeed, float pitchSpeed, float rollSpeed,
float sideSpeed, float upSpeed, float forwardSpeed,
float dt)
{
if (yawLeft)
ApplyYaw(yawSpeed * dt);
if (yawRight)
ApplyYaw(-yawSpeed * dt);
if (pitchDown)
ApplyPitch(pitchSpeed * dt);
if (pitchUp)
ApplyPitch(-pitchSpeed * dt);
if (rollRight)
ApplyRoll(rollSpeed * dt);
if (rollLeft)
ApplyRoll(-rollSpeed * dt);
if (moveLeft)
MoveAlongSideAxis(sideSpeed * dt);
if (moveRight)
MoveAlongSideAxis(-sideSpeed * dt);
if (moveUp)
MoveAlongUpAxis(upSpeed * dt);
if (moveDown)
MoveAlongUpAxis(-upSpeed * dt);
if (moveForward)
MoveAlongForwardAxis(forwardSpeed * dt);
if (moveBack)
MoveAlongForwardAxis(-forwardSpeed * dt);
}
float PShip::DegToRad(float angle)
{
const float DEG_TO_RAD = (atanf(1.0f) * 4.0f) / 180.0f;
return angle * DEG_TO_RAD;
}
// --------------------------------------------------------------------------------------
float PShip::RadToDeg(float angle)
{
const float DEG_TO_RAD = 180.0f / (atanf(1.0f) * 4.0f);
return angle * DEG_TO_RAD;
}

void PShip::ChangeThrottle(int percent)
{
throttle+=percent;

if(throttle > 100)
throttle = 100;
if(throttle < -100)
throttle = -100;
}
void PShip::TakeDamage(float amount)
{
if(shieldson && currentshields > 0 && currenthp >= 0)
{
currentshields -= amount;

if(currentshields < 0)
{
currenthp += currentshields; //Transfer overflow to hull
currentshields = 0;
}
}
else if(!shieldson || currentshields == 0)
{
currenthp -= amount;
}
}

float PShip::GetCurrenthp(void)
{
return currenthp;
}
float PShip::GetMaxhp(void)
{
return maxhp;
}
float PShip::GetCurrentShields(void)
{
return currentshields;
}
float PShip::GetMaxShields(void)
{
return maxshields;
}
int PShip::GetThrottle(void)
{
return throttle;
}
int PShip::GetEnergy(void)
{
return energy;
}
int PShip::GetHeat(void)
{
return weaponheat;
}


It isn't finished yet, I've been working on other things. I hope what you need is in there somewhere. (this and what I posted earlier is everything that relates to the openglobject code)

Share this post


Link to post
Share on other sites
Hm, it's not immediately clear where the problem is, and I may not have time to look through the code in more detail - sorry about that :-/

I'll at least try to offer a few tips though:

1. Make sure you have the right matrix mode set for all OpenGL matrix operations.

2. Make sure you understand the difference between the 'view' matrix and the 'model' matrix, and are using them in the right places.

3. Be sure to use glLoadIdentity(), glPushMatrix(), and glPopMatrix() where appropriate to set up the correct transform for whatever you're rendering at the moment.

There are a lot of details to get right in a 3D game, even a simple one, and unfortunately getting just one of them wrong can throw everything off. Again, developing a good understanding of the underlying transforms will make it much easier to identify and correct such errors.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this