Hit position on target
by Arkadiusz Dymek · in Torque Game Engine · 04/10/2005 (3:14 pm) · 19 replies
Hi,
I'd like to know exact hit position on target. For this question let's assume it's a flat wall with several painted squares (it's a bit more complicated in reality, but squares will make it easier to explain). Of course I can use %position of hit point and %position of the target and after some transformations I should get relative hit position which should allow me to tell where has the target been hit. Knowing hit position and square corner positions I should be able to tell which square has been hit. Now the question is - how to get square corner coordinates? I can shoot at them and write down the coords, but it seems like a bit troublesome and not too accurate method. There has to be some easier and quicker way - could I use ie ShowTool to read coords? I've been playing with it for while but I don't see such possibility. Any other ideas? Or maybe there's even simpler way than just calculating hit position already provided by the engine?
cheers,
Arkadesh
I'd like to know exact hit position on target. For this question let's assume it's a flat wall with several painted squares (it's a bit more complicated in reality, but squares will make it easier to explain). Of course I can use %position of hit point and %position of the target and after some transformations I should get relative hit position which should allow me to tell where has the target been hit. Knowing hit position and square corner positions I should be able to tell which square has been hit. Now the question is - how to get square corner coordinates? I can shoot at them and write down the coords, but it seems like a bit troublesome and not too accurate method. There has to be some easier and quicker way - could I use ie ShowTool to read coords? I've been playing with it for while but I don't see such possibility. Any other ideas? Or maybe there's even simpler way than just calculating hit position already provided by the engine?
cheers,
Arkadesh
#2
cheers,
Arkadesh
04/10/2005 (6:41 pm)
Thanks for help, but I'm not sure if that's what I look for. Basically what I need is a quick and easy way to map points on texture to torque coordinates. Above resource seems to deal with the part what to do after I know where the zones are and what's the hit point. And I don't know how to get areas coords :( I just have them painted on the texture and that's all. cheers,
Arkadesh
#3
04/10/2005 (7:07 pm)
Why do you need per pixel collision (which is basically what it sounds like you are saying)--is this on a 3-D model, or gui's? Especially if its a .dts model, that's some pretty hefty transformation stuff...
#4
I have a board placed flat in my world at a known location (for example, at <0,0,0>). If the user clicks his/her mouse and it intersects this object, I can get the position in the world where the mouse click hit the board. I then use my knowledge of the board's geometry to calculate where the hit was. (For example, I may know that the board goes from <0,0,0> to <5,5,0> and is gridded into 8x8 squares. I can then do some simple math to determine which square was hit.
Of course, this doesn't help at all if you need to know where on a specific texture you hit. If you need this, it sounds like some incredibly painful work will be needed.
04/10/2005 (7:42 pm)
I don't know if this will help your situation, but this is what I'm doing for a board game:I have a board placed flat in my world at a known location (for example, at <0,0,0>). If the user clicks his/her mouse and it intersects this object, I can get the position in the world where the mouse click hit the board. I then use my knowledge of the board's geometry to calculate where the hit was. (For example, I may know that the board goes from <0,0,0> to <5,5,0> and is gridded into 8x8 squares. I can then do some simple math to determine which square was hit.
Of course, this doesn't help at all if you need to know where on a specific texture you hit. If you need this, it sounds like some incredibly painful work will be needed.
#5
cheers,
Arkadesh
04/10/2005 (11:43 pm)
Yes, your approach is what I'm doing now. I'm just looking now for quick way to lookup my geometry points. Ie some way to tell in ShowTool what are coords of clicked point. Now I'm shooting at those points (square corners in my example) and writing down their coords, but that is painful and slow...cheers,
Arkadesh
#6
This is why most use the stock getDamageLocation() technique, because it handles all the transform manipulations in 3-Space for you.
04/11/2005 (5:07 am)
I'm not sure if you realize this, but once the model makes it into the engine (you are currently only mentioning ShowTool), all bets are off--the model may be translated, rotated, or otherwise transformed, and you'll need to handle the mathematical modifications to handle that transform change in your mapping of the point that was clicked.This is why most use the stock getDamageLocation() technique, because it handles all the transform manipulations in 3-Space for you.
#7
Btw what do you mean by getDamageLocation technique? How should the dts model be prepared so I can use it. Named boxes for each zone? Any resource for the modeller? I'd like to know what should I request from the artist :)
cheers,
Arkadesh
04/11/2005 (5:17 am)
Yeah.. I know about the transforms required. I keepi telling about ShowTool (or some equivalent) cause I need to get untransformed coords first somehow. Btw what do you mean by getDamageLocation technique? How should the dts model be prepared so I can use it. Named boxes for each zone? Any resource for the modeller? I'd like to know what should I request from the artist :)
cheers,
Arkadesh
#8
Honestly, I've not used the code much (or even looked at it), but my first guess is that it allows you to identify certain portions of the model by name, and returns that name to the code--in other words, pretty much exactly what you want to do (as Derk originally suggested).
My suggestion would be to take a good look at that portion of the code, find out exactly how it works, and then adapt it to what you need. It's probably pretty close!
04/11/2005 (5:34 am)
Long story short, the Damage Location functionality lets the code determine which -part- of a model is hit, and returns the appropriate identifier for that portion of the model.Honestly, I've not used the code much (or even looked at it), but my first guess is that it allows you to identify certain portions of the model by name, and returns that name to the code--in other words, pretty much exactly what you want to do (as Derk originally suggested).
My suggestion would be to take a good look at that portion of the code, find out exactly how it works, and then adapt it to what you need. It's probably pretty close!
#9
04/11/2005 (5:43 am)
I am guessing it returns the name of the collision mesh that it collided with. I think you can only have 10 collision meshes on any one model. So you can make your model with one collision mesh for it's head, one for the chest, two for each arm and leg.... Then when you call getDamageLocation(...) it returns that name and you can do what you like with the info.
#10
Actually, it allows you to define areas on a single collision mesh. I have broken the player box into 16 different areas.
Thanks.
04/11/2005 (6:04 am)
Chris,Actually, it allows you to define areas on a single collision mesh. I have broken the player box into 16 different areas.
Thanks.
#11
cheers,
Arkadesh
04/11/2005 (6:53 am)
Defining areas on collision mesh? Fits my needs then. Can you tell how this defining should be done on the artwork side? Ie should the artist write down some stuff from max or is it done some other way?cheers,
Arkadesh
#12
04/11/2005 (6:54 am)
Well, if you can model 10 different collision meshes to a single dts and 16 areas to a collision mesh... then you should be able to make 160 areas? Or were your 16 including the 10 different collision meshes?
#13
I have heavily modified the existing code, but the basics are in your system. Do not use this code as is, it won't work. It is for example only of how you can expand what is already in the engine.
Scripting /server/scripts/player.cs
04/11/2005 (7:15 am)
Dymek,I have heavily modified the existing code, but the basics are in your system. Do not use this code as is, it won't work. It is for example only of how you can expand what is already in the engine.
Scripting /server/scripts/player.cs
datablock PlayerData(Mech)
{
...
boundingBox = "2.4 2.9 4";
boxTorsoBottom = 2.75; // Bottom of Torso box
boxArmBottom = 3.125; // Bottom of Arm box
boxArmTop = 4.0; // Top of Arm box
boxArmWidth = 0.4; // Width of Arm box
boxTorsoWidth = 0.6; // Width of Side Torso
boxHeadBottom = 3.0; // Bottom of Head box
boxHeadTop = 3.25; // Top of Head box
boxHeadLeft = 0.4; // Left Side of Head box
boxHeadRight = -0.4; // Right Side of Head box
boxRear = -0.5; // Rear of entire box
...
}
...
function Armor::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
{
...
// Find hit location
%location = %obj.getDamageLocation(%position);
...
}Engine /engine/game/player.ccvoid Player::getDamageLocation(const Point3F& in_rPos, const char *&out_loc)
{
Point3F newPoint;
mWorldToObj.mulP(in_rPos, &newPoint);
F32 boxX = mDataBlock->boxSize.x / 2;
if (mDataBlock->sidestep) {
if (newPoint.z <= mDataBlock->boxTorsoBottom) {
// Hit Legs
if (newPoint.x <= 0.0f)
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "LLF";
else
out_loc = "LAF";
else
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "RLF";
else
out_loc = "RAF";
} else {
// Torso Hit
// Torso twisting coversion
if (mDataBlock->twist) {
// Get hit angle
F32 angle = mAtan( newPoint.x, newPoint.y );
// Get current rotation
Point3F headRotation = getHeadRotation();
// Subtract twist from angle (to move in opposite direction)
angle -= headRotation.z;
// Convert angle to -PI to PI
if(angle > M_PI )
angle -= M_2PI;
else if(angle < -M_PI )
angle += M_2PI;
// Get distance ratio
F32 ratio = mTan(angle);
// Calculate new location based on quadrant
if ((angle >= -M_PI/4) && (angle <= M_PI/4)) {
newPoint.y = mDataBlock->boxSize.y / 2;
newPoint.x = newPoint.y * ratio;
}
if ((angle > M_PI/4) && (angle < M_PI*0.75)) {
newPoint.x = mDataBlock->boxSize.x / 2;
newPoint.y = newPoint.x / ratio;
}
if ((angle <= -M_PI*0.75) || (angle >= M_PI*0.75)) {
newPoint.y = -mDataBlock->boxSize.y / 2;
newPoint.x = newPoint.y * ratio;
}
if ((angle > -M_PI*0.75) && (angle < -M_PI/4)) {
newPoint.x = -mDataBlock->boxSize.x / 2;
newPoint.y = newPoint.x / ratio;
}
}
if (newPoint.x <= (mDataBlock->boxTorsoWidth - boxX)) {
out_loc = "LTF";
} else if (newPoint.x >= (boxX - mDataBlock->boxTorsoWidth)) {
out_loc = "RTF";
} else {
out_loc = "CTF";
}
// Check Head
if ((newPoint.z >= mDataBlock->boxHeadBottom) && (newPoint.z <= mDataBlock->boxHeadTop)) {
if ((newPoint.x <= mDataBlock->boxHeadLeft) && (newPoint.x >= mDataBlock->boxHeadRight)) {
out_loc = "HF";
}
}
}
#14
Realize that some of the values are absolute (like boxTorsoBottom) while some are percentages (0 to 1 like boxRear). The original code in your system will probably be easier to understand as mine covers two kind of players and is rather convoluted.
HIH
04/11/2005 (7:15 am)
} else {
if (newPoint.z <= mDataBlock->boxTorsoBottom) {
// Hit Legs
if (newPoint.x <= 0.0f)
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "LLR";
else
out_loc = "LLF";
else
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "RLR";
else
out_loc = "RLF";
} else {
// Torso Hit
// Torso twisting coversion
if (mDataBlock->twist) {
// Get hit angle
F32 angle = mAtan( newPoint.x, newPoint.y );
// Get current rotation
Point3F headRotation = getHeadRotation();
// Subtract twist from angle (to move in opposite direction)
angle -= headRotation.z;
// Convert angle to -PI to PI
if(angle > M_PI )
angle -= M_2PI;
else if(angle < -M_PI )
angle += M_2PI;
// Get distance ratio
F32 ratio = mTan(angle);
// Calculate new location based on quadrant
if ((angle >= -M_PI/4) && (angle <= M_PI/4)) {
newPoint.y = mDataBlock->boxSize.y / 2;
newPoint.x = newPoint.y * ratio;
}
if ((angle > M_PI/4) && (angle < M_PI*0.75)) {
newPoint.x = mDataBlock->boxSize.x / 2;
newPoint.y = newPoint.x / ratio;
}
if ((angle <= -M_PI*0.75) || (angle >= M_PI*0.75)) {
newPoint.y = -mDataBlock->boxSize.y / 2;
newPoint.x = newPoint.y * ratio;
}
if ((angle > -M_PI*0.75) && (angle < -M_PI/4)) {
newPoint.x = -mDataBlock->boxSize.x / 2;
newPoint.y = newPoint.x / ratio;
}
}
if (newPoint.x <= (mDataBlock->boxTorsoWidth - boxX)) {
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "LTR";
else
out_loc = "LTF";
} else if (newPoint.x >= (boxX - mDataBlock->boxTorsoWidth)) {
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "RTR";
else
out_loc = "RTF";
} else {
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "CTR";
else
out_loc = "CTF";
}
// Check Arms
if ((newPoint.z >= mDataBlock->boxArmBottom) && (newPoint.z <= mDataBlock->boxArmTop)) {
if (newPoint.x <= (mDataBlock->boxArmWidth - boxX))
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "LAR";
else
out_loc = "LAF";
if (newPoint.x >= (boxX - mDataBlock->boxArmWidth))
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "RAR";
else
out_loc = "RAF";
}
// Check Head
if ((newPoint.z >= mDataBlock->boxHeadBottom) && (newPoint.z <= mDataBlock->boxHeadTop)) {
if ((newPoint.x <= mDataBlock->boxHeadLeft) && (newPoint.x >= mDataBlock->boxHeadRight)) {
if (mDataBlock->boxHeadTop == mDataBlock->boxSize.z)
if (newPoint.y <= mDataBlock->boxRear)
out_loc = "HR";
else
out_loc = "HF";
else
if (newPoint.y >= mDataBlock->boxRear)
out_loc = "HF";
}
}
}
}
}Realize that some of the values are absolute (like boxTorsoBottom) while some are percentages (0 to 1 like boxRear). The original code in your system will probably be easier to understand as mine covers two kind of players and is rather convoluted.
HIH
#15
04/11/2005 (7:18 am)
Can anyone say "resource" ? Hint hint...
#16
boxTorsoBottom = 2.75; // Bottom of Tors
How do you get them of the model on the artist side. Ie if I have 3 circles on the box face - how do I get their centerpoints?
cheers,
Arkadesh
04/11/2005 (7:31 am)
Tx again. On the code side it's pretty clear to me, but how do you get the values - like ie boxTorsoBottom = 2.75; // Bottom of Tors
How do you get them of the model on the artist side. Ie if I have 3 circles on the box face - how do I get their centerpoints?
cheers,
Arkadesh
#17
I have the models in MilkShape and I can measure the bounding box (which is the first line in my example code [x,y,z size]), then I measure (approximate) the various areas. I take by your question that ShowTool doesn't give you measurement info so you will need an art package to get it. If you don't have access to the original model, it's going to be difficult.
HIH
04/11/2005 (8:23 am)
Arkadesh,I have the models in MilkShape and I can measure the bounding box (which is the first line in my example code [x,y,z size]), then I measure (approximate) the various areas. I take by your question that ShowTool doesn't give you measurement info so you will need an art package to get it. If you don't have access to the original model, it's going to be difficult.
HIH
#18
cheers,
Arkadesh
04/12/2005 (12:25 pm)
While there's some interest in the topic I'll try another approach - what part of engine should I take a closer look if artist creates several collision boxes and puts them into the dts model. Is there any ready function returning name of collision box hit?cheers,
Arkadesh
Torque Owner Derk Adams
You should look at Player::getDamageLocation in the engine and where it is called in the script. Of course it is only for the player, you will have to figure out how to apply it to other objects, but it will get you started.
Thanks.