Guess who just made some hitboxes?
by Josh Albrecht · in Torque Game Engine · 08/31/2001 (1:38 pm) · 23 replies
ME! :)
It is currently a bit (read very) unrefined. I only have one hitbox right now (though I could add more in about 3 seconds). The hitbox can be on whatever bone I want it to be, but the dimensions need to be guessed at... :( That is the major problem with this edition of my hitboxes. Anyway, since you probably care, here is how I did it:
1. I implemented the weapon mod from these forums.
2. I upped the rate of fire to about 10 or 20 times a second.
3. I opened up the cContainerRayCast function in sim/sceneObject.cc at line 203.
4. Add this code:
After:
Ray rinfo
I added:
S32 ret = 0;
U32 sloth = 0;
MatrixF transform;
MatrixF transform2;
MatrixF mat;
After:
ret = rinfo.object->getId();
I added:
sloth = rinfo.object->getTypeMask();
(be sure to add brackets around the if statement this is in!!!!! <--- VERY IMPORTANT. Otherwise it crashes if you dont hit)
After:
// add the hit position and normal?
I added (er, changed the end of the function to):
if (sloth & PlayerObjectType)
{
Player *pPlayer = (Player *) rinfo.object;
transform = pPlayer->getNodeTransform("Bip01 Pelvis");
Box3F convexBox;
convexBox.min.x = -0.2;
convexBox.min.y = -0.2;
convexBox.min.z = -0.2;
convexBox.max.x = 0.2;
convexBox.max.y = 0.2;
convexBox.max.z = 0.2;
transform2 = pPlayer->getRenderTransform();
mat.mul(transform2, transform);
mat.mul(convexBox);
if(convexBox.isContained(end))
{
if(ret)
{
dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g", ret, rinfo.point.x, rinfo.point.y, rinfo.point.z, rinfo.normal.x, rinfo.normal.y, rinfo.normal.z);
}
else
{
returnBuffer[0] = '0';
returnBuffer[1] = '\0';
}
}
}
else
{
returnBuffer[0] = '0';
returnBuffer[1] = '\0';
}
return(returnBuffer);
}
} // namespace {}
Now let me explain this. The ending point of your ray fired by the gun is going to be the important thing here beacuse of isContained. If the point is inside the box, then it sends back the info and the bot dies. Otherwise, he lives. The target is kind of small right now, so to hit it, stand far away, then move toward the bot while holding the fire button and pointing it at the pelvis. That is the reason I changed the firing rate of the gun. It is in the script datablock (recoil and reload time and such).
This could easily be modified to check for a line and box collision I think. So there you go! Now you have hitboxes! :)
It is currently a bit (read very) unrefined. I only have one hitbox right now (though I could add more in about 3 seconds). The hitbox can be on whatever bone I want it to be, but the dimensions need to be guessed at... :( That is the major problem with this edition of my hitboxes. Anyway, since you probably care, here is how I did it:
1. I implemented the weapon mod from these forums.
2. I upped the rate of fire to about 10 or 20 times a second.
3. I opened up the cContainerRayCast function in sim/sceneObject.cc at line 203.
4. Add this code:
After:
Ray rinfo
I added:
S32 ret = 0;
U32 sloth = 0;
MatrixF transform;
MatrixF transform2;
MatrixF mat;
After:
ret = rinfo.object->getId();
I added:
sloth = rinfo.object->getTypeMask();
(be sure to add brackets around the if statement this is in!!!!! <--- VERY IMPORTANT. Otherwise it crashes if you dont hit)
After:
// add the hit position and normal?
I added (er, changed the end of the function to):
if (sloth & PlayerObjectType)
{
Player *pPlayer = (Player *) rinfo.object;
transform = pPlayer->getNodeTransform("Bip01 Pelvis");
Box3F convexBox;
convexBox.min.x = -0.2;
convexBox.min.y = -0.2;
convexBox.min.z = -0.2;
convexBox.max.x = 0.2;
convexBox.max.y = 0.2;
convexBox.max.z = 0.2;
transform2 = pPlayer->getRenderTransform();
mat.mul(transform2, transform);
mat.mul(convexBox);
if(convexBox.isContained(end))
{
if(ret)
{
dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g", ret, rinfo.point.x, rinfo.point.y, rinfo.point.z, rinfo.normal.x, rinfo.normal.y, rinfo.normal.z);
}
else
{
returnBuffer[0] = '0';
returnBuffer[1] = '\0';
}
}
}
else
{
returnBuffer[0] = '0';
returnBuffer[1] = '\0';
}
return(returnBuffer);
}
} // namespace {}
Now let me explain this. The ending point of your ray fired by the gun is going to be the important thing here beacuse of isContained. If the point is inside the box, then it sends back the info and the bot dies. Otherwise, he lives. The target is kind of small right now, so to hit it, stand far away, then move toward the bot while holding the fire button and pointing it at the pelvis. That is the reason I changed the firing rate of the gun. It is in the script datablock (recoil and reload time and such).
This could easily be modified to check for a line and box collision I think. So there you go! Now you have hitboxes! :)
#2
You might also want to check out the Head, Torso, Lshoulder, Rshoulder, Lbicep, Rbicep, Larm, Rarm, Lhand, Rhand, Waist, Pelvis, Lthigh, Rthigh, Lknee, Rknee, Lleg, Rleg, Lankle, Rankle, Lfoot, Rfoot.
09/02/2001 (7:46 pm)
Cool.You might also want to check out the Head, Torso, Lshoulder, Rshoulder, Lbicep, Rbicep, Larm, Rarm, Lhand, Rhand, Waist, Pelvis, Lthigh, Rthigh, Lknee, Rknee, Lleg, Rleg, Lankle, Rankle, Lfoot, Rfoot.
#3
09/02/2001 (8:12 pm)
Since you updated the code for more features, could you show us what you did? Having multiple hitboxes per model is going to be important for what I'm working on. I think my V12 adventure game is going to use a "weapon" to target things with multiple hitboxes so you can context click on all different parts of the scene.
#4
Okay fixed it, make sure to include:
#include "game/player.h"
09/02/2001 (8:26 pm)
BTW, sceneObject.cc won't compile for me. Doesn't know where Player class is.. I'm going to look around for it.Okay fixed it, make sure to include:
#include "game/player.h"
#5
09/02/2001 (10:10 pm)
Hm, I can't get the hitboxes to work. I tried Bip01 Pelvis and I couldn't shoot the dummy in the pelvis so I changed Pelvis to Head and I couldn't shoot the head either. What am I doing wrong?
#6
Cus then the hitboxes could be places properly by your artists.. it would also be useful as more detailed collision models (rather than bounding box).
Phil.
09/03/2001 (3:53 am)
Josh... why not just get the modeller to add boxes for each part of the model as "hitbox_" and then the partname...Cus then the hitboxes could be places properly by your artists.. it would also be useful as more detailed collision models (rather than bounding box).
Phil.
#7
Phil: That is a great idea! However, how would I get the box dimensions if it was assigned to a bone? I really have no clue how to do that...
Plus, I think this way, it would be more efficient, correct? I will probably have 16 or so hitboxes, wihch is an additional 128 polys that need to be on a player model. Would this slow the game down as much as having 128 extra visible polys? I doubt it, but would the slowdown be almost insignificant? I intend on keeping this as optimized as possible, because my game is going to be stretching people's computers already, without added inefficiency.
I didnt post my new code for three reasons:
1. I didnt have time.
2. It is essentially just a hack right now, so the new version is just a less ugly hack.
3. It is very easy to make my changes if you understand what I did.
I will post updated code when I create it. I am going to try to do what Phil suggested today.
09/03/2001 (9:04 am)
Sorry everyone, I did forget about the #include "player.h" oops. :)Phil: That is a great idea! However, how would I get the box dimensions if it was assigned to a bone? I really have no clue how to do that...
Plus, I think this way, it would be more efficient, correct? I will probably have 16 or so hitboxes, wihch is an additional 128 polys that need to be on a player model. Would this slow the game down as much as having 128 extra visible polys? I doubt it, but would the slowdown be almost insignificant? I intend on keeping this as optimized as possible, because my game is going to be stretching people's computers already, without added inefficiency.
I didnt post my new code for three reasons:
1. I didnt have time.
2. It is essentially just a hack right now, so the new version is just a less ugly hack.
3. It is very easy to make my changes if you understand what I did.
I will post updated code when I create it. I am going to try to do what Phil suggested today.
#8
MatrixF transform2;
MatrixF transform;
MatrixF mat;
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 Head");
mat.mul(transform2, transform);
mat.mul(mHeadHitbox);
glPushMatrix();
glColor3f(1, 0, 0);
wireCube(Point3F(mHeadHitbox.max.x-mHeadHitbox.min.x,mHeadHitbox.max.y-mHeadHitbox.min.y,mHeadHitbox.max.z-mHeadHitbox.min.z),Point3F(0,0,0));
glPopMatrix();
This is a function created by the T2 guys that draws the bounding box around the player, and it works:
Point3F box;
Box3F convexBox = mConvex.getBoundingBox(getRenderTransform(), getScale());
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 1, 0);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
I have tried the PushMatrix at the beginning of my code too, but that didnt help. ANy suggestions? Once I get this working, I will release my new version.
09/03/2001 (8:06 pm)
Here is some code. I wrote this function to draw hitboxes in the game, but it doesnt work, and I dont know why. mHeadHitbox.min.x y and z are -0.4 and mHeadHitbox.max.x y and z are 0.4. Here is the code:MatrixF transform2;
MatrixF transform;
MatrixF mat;
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 Head");
mat.mul(transform2, transform);
mat.mul(mHeadHitbox);
glPushMatrix();
glColor3f(1, 0, 0);
wireCube(Point3F(mHeadHitbox.max.x-mHeadHitbox.min.x,mHeadHitbox.max.y-mHeadHitbox.min.y,mHeadHitbox.max.z-mHeadHitbox.min.z),Point3F(0,0,0));
glPopMatrix();
This is a function created by the T2 guys that draws the bounding box around the player, and it works:
Point3F box;
Box3F convexBox = mConvex.getBoundingBox(getRenderTransform(), getScale());
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 1, 0);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
I have tried the PushMatrix at the beginning of my code too, but that didnt help. ANy suggestions? Once I get this working, I will release my new version.
#9
The wireCube function is in game.cc if you want to take a look at what it does.
Hope this helps.
09/04/2001 (7:51 am)
Well you're missing the translation. glTranslatef sets the position of the box at (X, Y, Z). Also, you should probably use glScalef to size the box instead of passing the size to wireCube. From the looks of the T2 code, this is what they do. Notice that wireCube is passed 1,1,1 for size and 0,0,0 for position and that the translation and scaling are OpenGL calls. Make sure you do the translation and scaling inside the glPushMatrix()/glPopMatrix.The wireCube function is in game.cc if you want to take a look at what it does.
Hope this helps.
glPushMatrix();
glColor3f(1, 0, 0);
glTranslatef(mHeadHitbox.x,mHeadHitbox.y,mHeadHitbox.z);
glScalef(mHeadHitbox.max.x-mHeadHitbox.min.x,mHeadHitbox.max.y-mHeadHitbox.min.y,
mHeadHitbox.max.z-mHeadHitbox.min.z);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
#10
Thanks,
Jake
09/04/2001 (8:14 am)
Now I'm curious. I thought the v12 engine supported both direct3d and opengl. But it seems to me if you add that above code (with the opengl calls) then you'll be restricted to just opengl only. Is that the case? What am I missing here?Thanks,
Jake
#11
09/04/2001 (9:01 am)
THere is an OpenGL wrapper. Meaning you do everything in OpenGL, and the engine interprets it for anyone who wants to use that crappy DirectX language. :)
#12
09/04/2001 (9:54 am)
Ok, I have a hitbox now, but it doesnt rotate correctly because fo the way the boxes are drawn. Once I get that, I PROMISE I will put it up.
#14
The getNodeTransform and my other transform bring the hitbox to the node, but it is not rotated ever. It needs to be rotated so that it stays around the node. For example (using the thigh hitbox), if someone lifted their knee from a standing position ( where the hitbox is vertical) to a straight out position, the hitbox should rotate to take that into account and still enclose the limb. However, as of now, it does not. In the example, the hitbox would remain vertical and stick oddly "up and down" through the thigh.
This cant happen.
So, I get the rotation from the below code and change it into a QuatF:
TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Calf" );
Quat16 myrot = mShapeInstance->mNodeReferenceRotations[node];
QuatF myQuat;
myrot.getQuatF(&myQuat);
Now HOW do I use this!!?!?! That has been puzzling me for so long! What do I do to use this rotation!? What is this rotation?
09/04/2001 (4:02 pm)
It all comes down to this:The getNodeTransform and my other transform bring the hitbox to the node, but it is not rotated ever. It needs to be rotated so that it stays around the node. For example (using the thigh hitbox), if someone lifted their knee from a standing position ( where the hitbox is vertical) to a straight out position, the hitbox should rotate to take that into account and still enclose the limb. However, as of now, it does not. In the example, the hitbox would remain vertical and stick oddly "up and down" through the thigh.
This cant happen.
So, I get the rotation from the below code and change it into a QuatF:
TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Calf" );
Quat16 myrot = mShapeInstance->mNodeReferenceRotations[node];
QuatF myQuat;
myrot.getQuatF(&myQuat);
Now HOW do I use this!!?!?! That has been puzzling me for so long! What do I do to use this rotation!? What is this rotation?
#15
09/04/2001 (6:02 pm)
It seems, after hours of struggle, that this method in fact DOES NOT give me the rotation, which is very annoying. I can apply the rotations now, I just need the data. How would I find the rotation transformation for a bone (node) ??!
#16
09/04/2001 (6:53 pm)
Well, it gives me something, though I am not sure it is what I need. I have the box rotating, and even at the right speed, but it doesnt go in the right direction. :(
#17
TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Calf" );
QuatF myQuat = mShapeInstance->smNodeCurrentRotations[node];
I use this code to convert it to and Angle Axis:
AngAxisF Ang_Ax;
F32 scale, tw;
tw = (F32)acos(myQuat.w) * 2;
scale = (F32)sin(tw / 2.0);
Ang_Ax.axis.x = myQuat.x / scale;
Ang_Ax.axis.y = myQuat.y / scale;
Ang_Ax.axis.z = myQuat.z / scale;
Ang_Ax.angle = 2.0 * acos(myQuat.w);
I use this code to rotate the box (after it has been translated to the "Bip01 R Calf" node):
glRotatef((Ang_Ax.angle*180.0/3.1415), Ang_Ax.axis.z, Ang_Ax.axis.y, Ang_Ax.axis.x);
Note that the x y z is reversed in glRotatef. If it is the other way (normal) then it rotates on the wrong axis. Any clues why? (The angle is converted from radians to euler and it works like this)
My real question is: Why are two of the Ang_Ax.axis.* variables empty? When I use this code, the box only rotates in one direction. When the player strafes, the box SHOULD tilt sideways, but it does not. It only responds to the bending of the knee.
Please help me! I have literally spent all day working on this hitbox stuff, learning about quats, etc. I didnt even eat breakfast or lunch... :(
09/04/2001 (8:39 pm)
I use this code to get the rotation:TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Calf" );
QuatF myQuat = mShapeInstance->smNodeCurrentRotations[node];
I use this code to convert it to and Angle Axis:
AngAxisF Ang_Ax;
F32 scale, tw;
tw = (F32)acos(myQuat.w) * 2;
scale = (F32)sin(tw / 2.0);
Ang_Ax.axis.x = myQuat.x / scale;
Ang_Ax.axis.y = myQuat.y / scale;
Ang_Ax.axis.z = myQuat.z / scale;
Ang_Ax.angle = 2.0 * acos(myQuat.w);
I use this code to rotate the box (after it has been translated to the "Bip01 R Calf" node):
glRotatef((Ang_Ax.angle*180.0/3.1415), Ang_Ax.axis.z, Ang_Ax.axis.y, Ang_Ax.axis.x);
Note that the x y z is reversed in glRotatef. If it is the other way (normal) then it rotates on the wrong axis. Any clues why? (The angle is converted from radians to euler and it works like this)
My real question is: Why are two of the Ang_Ax.axis.* variables empty? When I use this code, the box only rotates in one direction. When the player strafes, the box SHOULD tilt sideways, but it does not. It only responds to the bending of the knee.
Please help me! I have literally spent all day working on this hitbox stuff, learning about quats, etc. I didnt even eat breakfast or lunch... :(
#18
A few problems I noticed that will probably help increase efficiency a bit to fix.
The first I noticed is that you're calling (acos(myQuat.w) * 2.0) twice. This can be reduced to a single variable which can be used in the scale calculation and the angle. I know why you're seperating them, to get a round off effect, but I think this can be done with a cast to an integer in the calculation instead. Since this replicated calculation occurs every frame this could be a big performance hit. At least one worth handling anyways.
The other I noticed is that you're using 3.1415 as PI, however in math/mConstants.h M_PI is a constant which declares PI much more accurately as 3.14159265358979323846.
I don't have your full code so I can't really help you figure out what is wrong with your particular implementation.
However, glRotatef is prototyped in platformGL.h as:
extern void ( GLAPIENTRY * glRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
So, there's something wrong with the way you are getting the axes that they end up reversed.
If you could post what you have thus far I'm sure more people would be able to respond with something useful. Maybe even Tim would help out.
I think though what might help is to seperate the glRotatef calls per axis.
myangle = Ang_Ax.angle*180.0/3.1415;
glRotatef(myangle, Ang_Ax.axis.x, 0.0f, 0.0f);
glRotatef(myangle, 0.0f, Ang_Ax.axis.y, 0.0f);
glRotatef(myangle, 0.0f, 0.0f, Ang_Ax.axis.z);
I could be wrong, as I usually am, but I think this is the way glRotatef works. Or maybe that has to be conditional, I don't know. Maybe I'm just shooting my mouth off again.
Hope my babble helps.
09/05/2001 (7:32 am)
You are amazing. ;-)A few problems I noticed that will probably help increase efficiency a bit to fix.
The first I noticed is that you're calling (acos(myQuat.w) * 2.0) twice. This can be reduced to a single variable which can be used in the scale calculation and the angle. I know why you're seperating them, to get a round off effect, but I think this can be done with a cast to an integer in the calculation instead. Since this replicated calculation occurs every frame this could be a big performance hit. At least one worth handling anyways.
The other I noticed is that you're using 3.1415 as PI, however in math/mConstants.h M_PI is a constant which declares PI much more accurately as 3.14159265358979323846.
I don't have your full code so I can't really help you figure out what is wrong with your particular implementation.
However, glRotatef is prototyped in platformGL.h as:
extern void ( GLAPIENTRY * glRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
So, there's something wrong with the way you are getting the axes that they end up reversed.
If you could post what you have thus far I'm sure more people would be able to respond with something useful. Maybe even Tim would help out.
I think though what might help is to seperate the glRotatef calls per axis.
myangle = Ang_Ax.angle*180.0/3.1415;
glRotatef(myangle, Ang_Ax.axis.x, 0.0f, 0.0f);
glRotatef(myangle, 0.0f, Ang_Ax.axis.y, 0.0f);
glRotatef(myangle, 0.0f, 0.0f, Ang_Ax.axis.z);
I could be wrong, as I usually am, but I think this is the way glRotatef works. Or maybe that has to be conditional, I don't know. Maybe I'm just shooting my mouth off again.
Hope my babble helps.
#19
This is the function:
inline QuatF & TSShape::getRotation(const Sequence & seq, S32 keyframeNum, S32 rotNum, QuatF * quat) const
{
return nodeRotations[seq.baseRotation + rotNum*seq.numKeyframes + keyframeNum].getQuatF(quat);
}
09/05/2001 (7:46 am)
Additionally, in tsShape.h the TSShape class has a function for getting particular rotations of a node. Perhaps you're only getting one directional rotation because you aren't getting each specific sequence/frame/rotation. This also might be why you're getting the reversed values. Of course I don't know anything about this stuff so this could be completely off.This is the function:
inline QuatF & TSShape::getRotation(const Sequence & seq, S32 keyframeNum, S32 rotNum, QuatF * quat) const
{
return nodeRotations[seq.baseRotation + rotNum*seq.numKeyframes + keyframeNum].getQuatF(quat);
}
#20
The reason I didnt post the full code is that no one would care enough to try to understand it. I have tried SO many different approaches (converting to a rotation matrix, applying the quat as it is, changing it to an axis angle, and more) that the code is no longer comprehensible. And I fear if I try to clean it up, it will stop working. :(
But, because you have shown me that someone actually DOES care, I will post it:
//Raistlin's code! (hack :)
glPushMatrix();
Point3F box;
MatrixF transform2;
MatrixF transform;
MatrixF mat;
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 Pelvis"); //R Calf
Box3F convexBox;
convexBox = mHeadHitbox;
TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Thigh" );
QuatF myQuat = mShapeInstance->smNodeCurrentRotations[node];
AngAxisF Ang_Ax;
F32 scale, tw;
tw = (F32)acos(myQuat.w) * 2;
scale = (F32)sin(tw / 2.0);
Ang_Ax.axis.x = myQuat.x / scale;
Ang_Ax.axis.y = myQuat.y / scale;
Ang_Ax.axis.z = myQuat.z / scale;
Ang_Ax.angle = 2.0 * acos(myQuat.w);
MatrixF m;
F32 fW = myQuat.w;
F32 fX = myQuat.x;
F32 fY = myQuat.y;
F32 fZ = myQuat.z;
F32 fXX = fX * fX;
F32 fYY = fY * fY;
F32 fZZ = fZ * fZ;
m[0] = 1.0f - 2.0f * (fYY + fZZ);
m[1] = 2.0f * (fX * fY + fW * fZ);
m[2] = 2.0f * (fX * fZ - fW * fY);
m[3] = 0.0f;
m[4] = 2.0f * (fX * fY - fW * fZ);
m[5] = 1.0f - 2.0f * (fXX + fZZ);
m[6] = 2.0f * (fY * fZ + fW * fX);
m[7] = 0.0f;
m[8] = 2.0f * (fX * fZ + fW * fY);
m[9] = 2.0f * (fX * fZ - fW * fX);
m[10] = 1.0f - 2.0f * (fXX + fYY);
m[11] = 0.0f;
m[12] = 0.0f;
m[13] = 0.0f;
m[14] = 0.0f;
m[15] = 1.0f;
mat.mul(transform2, transform);
mat.mul(m);
mat.mul(convexBox);
glColor3f(1, 0, 0);
glDisable(GL_CULL_FACE);
//the first box is drawn here, but it isnt really a box, just some lines so that I can tell it works. They almost make a box.
glBegin(GL_LINES);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.min.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.min.x,convexBox.min.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.min.z);
glEnd();
glPopMatrix();
//The second box, around the Thigh
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 R Thigh");
mat.mul(transform2, transform);
convexBox = mPelvicHitbox;
mat.mul(convexBox);
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
glRotatef((Ang_Ax.angle*180.0/3.1415), Ang_Ax.axis.x, Ang_Ax.axis.y, Ang_Ax.axis.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 0, 0);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
//The third box. The player bounding box. This is V12 code, to show that it works.
convexBox = mConvex.getBoundingBox(getRenderTransform(), getScale());
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 1, 1);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
glEnable(GL_DEPTH_TEST);
It would probably be best to copy paste this out of the forums, so it is inteligible.
Note that mPelvicHitbox and mHeadHitbox must be defined somewhere. You could easily just define them at the top of the code like this:
Box3F mPelvicHitbox;
mPelvicHitbox.max.x = 0.4;
mPelvicHitbox.max.y = 0.4;
mPelvicHitbox.max.z = 0.4;
mPelvicHitbox.min.x = -0.4;
mPelvicHitbox.min.y = -0.4;
mPelvicHitbox.min.z = -0.4;
Same for the head one. There you go everyone! My code! Though it doesnt work right... :(
Bip01 R Thigh can be changed to:
Bip01 R Calf
Bip01 R Forearm
Bip01 R UpperArm
Bip01 Pelvis
Bip01 Head
or any other node you want.
The current problems with my code:
- The rotations arent right.
- ALL THE BOXES stay alignedone the y axis (up and down) with the STUPID bounding box. They never rotate. The bounding box always stays aligned with the world grid. So when the player turns 30 degrees, the box doesnt turn. If he turned 45 degrees, he would be facing a corner. If he turned 90, he would face a side. The hitboxes NEED to turn like this. This is all rotational problems.
Some one please help me! :)
Thanks for the idea Nelson, I will try it.
EDIT: I cant really get your idea to work Nelson, thanks for the suggestion though.
EDIT #2: Please note that the matrix method DOES NOT ROTATE the box.
09/05/2001 (9:19 am)
That could help ALOT. I had almost given up on it.The reason I didnt post the full code is that no one would care enough to try to understand it. I have tried SO many different approaches (converting to a rotation matrix, applying the quat as it is, changing it to an axis angle, and more) that the code is no longer comprehensible. And I fear if I try to clean it up, it will stop working. :(
But, because you have shown me that someone actually DOES care, I will post it:
//Raistlin's code! (hack :)
glPushMatrix();
Point3F box;
MatrixF transform2;
MatrixF transform;
MatrixF mat;
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 Pelvis"); //R Calf
Box3F convexBox;
convexBox = mHeadHitbox;
TSShape *shape = mShapeInstance->getShape();
S32 node = shape->findNode( "Bip01 R Thigh" );
QuatF myQuat = mShapeInstance->smNodeCurrentRotations[node];
AngAxisF Ang_Ax;
F32 scale, tw;
tw = (F32)acos(myQuat.w) * 2;
scale = (F32)sin(tw / 2.0);
Ang_Ax.axis.x = myQuat.x / scale;
Ang_Ax.axis.y = myQuat.y / scale;
Ang_Ax.axis.z = myQuat.z / scale;
Ang_Ax.angle = 2.0 * acos(myQuat.w);
MatrixF m;
F32 fW = myQuat.w;
F32 fX = myQuat.x;
F32 fY = myQuat.y;
F32 fZ = myQuat.z;
F32 fXX = fX * fX;
F32 fYY = fY * fY;
F32 fZZ = fZ * fZ;
m[0] = 1.0f - 2.0f * (fYY + fZZ);
m[1] = 2.0f * (fX * fY + fW * fZ);
m[2] = 2.0f * (fX * fZ - fW * fY);
m[3] = 0.0f;
m[4] = 2.0f * (fX * fY - fW * fZ);
m[5] = 1.0f - 2.0f * (fXX + fZZ);
m[6] = 2.0f * (fY * fZ + fW * fX);
m[7] = 0.0f;
m[8] = 2.0f * (fX * fZ + fW * fY);
m[9] = 2.0f * (fX * fZ - fW * fX);
m[10] = 1.0f - 2.0f * (fXX + fYY);
m[11] = 0.0f;
m[12] = 0.0f;
m[13] = 0.0f;
m[14] = 0.0f;
m[15] = 1.0f;
mat.mul(transform2, transform);
mat.mul(m);
mat.mul(convexBox);
glColor3f(1, 0, 0);
glDisable(GL_CULL_FACE);
//the first box is drawn here, but it isnt really a box, just some lines so that I can tell it works. They almost make a box.
glBegin(GL_LINES);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.min.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.max.z);
glVertex3f(convexBox.min.x,convexBox.min.y,convexBox.max.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.min.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.max.y,convexBox.min.z);
glVertex3f(convexBox.max.x,convexBox.min.y,convexBox.min.z);
glEnd();
glPopMatrix();
//The second box, around the Thigh
transform2 = getRenderTransform();
transform = getNodeTransform("Bip01 R Thigh");
mat.mul(transform2, transform);
convexBox = mPelvicHitbox;
mat.mul(convexBox);
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
glRotatef((Ang_Ax.angle*180.0/3.1415), Ang_Ax.axis.x, Ang_Ax.axis.y, Ang_Ax.axis.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 0, 0);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
//The third box. The player bounding box. This is V12 code, to show that it works.
convexBox = mConvex.getBoundingBox(getRenderTransform(), getScale());
glPushMatrix();
box = (convexBox.min + convexBox.max) * 0.5;
glTranslatef(box.x,box.y,box.z);
box = (convexBox.max - convexBox.min) * 0.5;
glScalef(box.x,box.y,box.z);
glColor3f(1, 1, 1);
wireCube(Point3F(1,1,1),Point3F(0,0,0));
glPopMatrix();
glEnable(GL_DEPTH_TEST);
It would probably be best to copy paste this out of the forums, so it is inteligible.
Note that mPelvicHitbox and mHeadHitbox must be defined somewhere. You could easily just define them at the top of the code like this:
Box3F mPelvicHitbox;
mPelvicHitbox.max.x = 0.4;
mPelvicHitbox.max.y = 0.4;
mPelvicHitbox.max.z = 0.4;
mPelvicHitbox.min.x = -0.4;
mPelvicHitbox.min.y = -0.4;
mPelvicHitbox.min.z = -0.4;
Same for the head one. There you go everyone! My code! Though it doesnt work right... :(
Bip01 R Thigh can be changed to:
Bip01 R Calf
Bip01 R Forearm
Bip01 R UpperArm
Bip01 Pelvis
Bip01 Head
or any other node you want.
The current problems with my code:
- The rotations arent right.
- ALL THE BOXES stay alignedone the y axis (up and down) with the STUPID bounding box. They never rotate. The bounding box always stays aligned with the world grid. So when the player turns 30 degrees, the box doesnt turn. If he turned 45 degrees, he would be facing a corner. If he turned 90, he would face a side. The hitboxes NEED to turn like this. This is all rotational problems.
Some one please help me! :)
Thanks for the idea Nelson, I will try it.
EDIT: I cant really get your idea to work Nelson, thanks for the suggestion though.
EDIT #2: Please note that the matrix method DOES NOT ROTATE the box.
Torque Owner Josh Albrecht
I added alot. Now the size of the hitbox is read in from the scripts, and it there are two different hitboxes (one for head, one for groin, the only two names of nodes that I found with a quick search, besides spine. I will get more from my modeler)
It is also much cleaner, and can return a value to signal which box was hit. I suppose I could script in new death anims depending on where the player was hit, but I think I will wait until I have all the node names.
Collision is now based on whether the line (from the muzzle point to the end of the ray) intersects the box.
I am going to try to find a better method than manually guessing and checking the size for creating the hitbox.