Jump to content
  • Advertisement

Archived

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

dirtbag

L.O.S-Casting a Ray-Collision- ..Olli? anyone?

This topic is 5202 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I hope Olli or someone that might be able to help is around because this has got me totally confused. I haven''t seen anything in any of my books that explains or covers any of this stuff in any detail,and my searches on the web has resulted in 0. I did find a site called Codercorner.com where a guy has a demo of what i am trying to do,Pierre Terdiman.Though there is only an .exe and its not really a place that has tutorials or anything like that. I''m pretty sure he is using his own collision library,i think called Opcode,so source code to that demo would probably be useless to me from a learning point of view anyway. In nearly all(or most) 3D games,i have come to the conclusion that collision detection is one of the most problematic and difficult problems(especially if you aren''t sure how to approach it,or done anything like this before) fighting games,shooters,whatever. I''m trying my hand at a 3rd-Person shooter. I have 2 animated characters(skeletal animation) 1 player character,and 1 NPC. I have a third object loaded,acting as a weapon for the player. BTW,these are all DirectX.x files,as i''m using D3D for rendering. I have attached the weapon to the players hand(its a seperate object,as mentioned above). How could i cast a visable ray(think ONI) from the static weapon .x file model,to be able to test if an intersection occurs between the weapon and the NPC? PC RAY NPC | | | ^ ^ ^ 0 weapon 0 |_= -------------- | | | |_ _| If anyone know of any Direct3D based demo source example,or could provide me with any help or an example,i''d be eternally grateful. It doesn''t have to be anything advanced,anything will do. or any comments or advice. Cheers.

Share this post


Link to post
Share on other sites
Advertisement
in some shooters, the bullet if fired not from the gun, but from the inside of the player (like the torso). Then some special effect is done on the gun (muzzle flash), to give the impression that the bullet was fired from the gun. Most of the time, the gun animation isn''t accurate anough to fire a bullet from the muzzle anyway. The gun moves way too much to be accurate enough. It''s like the camera in FPS. The camera is not attached to the head of the animation, but it''s faked as being somewhere inside the bounding box of the player, and a sway effect is done to give the impression of walking / running.

So, you have a crosshair from the camera, if you raycast from the camera towards the camera direction, that will give you the point underneath the crosshair (don''t forget to disable the player himself for raycast), Then you can cast the bullet trajectory from either the end of the gun or the torso ofthe player towards that point. That should give a direction slightly off from the current direction of the gun.

if you really want to cast a ray from the gun towards wherever it''s pointing (like a laser sight, or really shoot the bullet from the gun), you can have marker points in the gun model, like two points, on at the end of the barrel, one at the chamber, these will define a segment, and consequently a line, that you can use for firing the bullet / laser. you can just use two vertices of the model, which you know are aligned in the direction of the gun, calculate their world position, and cast a ray through them.

you can kind of have the two system work in sync (firing from the gun towards the real gun direction, and also aiming where the crosshair is pointing to), by using inverse kinematics to a certain point, but that''s pushing it, although it would look really cool.

It''s good to keep markers objects on the models, stored in a file as an extension to the .x file, or if you can, stored in the .x model file (dunno if the .x file system allows for extra private data structures). If you have markers for say, hands, muzzle flash particle effect, ray position and direction, shell casing ejections, scope or grenade launcher attachements and whatnot, it''s a lot easier to add stuff to your gun model. Then markers, (or anchors), should have a position and an orientation matrix or quaternion, that''s quite useful to orientate stuff the right way. You can do the same for the player models as well, and add attachements to his hip bones or torso, to add ammo belts and attach other items to his body (helmets, armour, armour parts...). That''s if you use bone hierarchies. And it''s also very useful for stuff like vehicles, like attaching players to the seat of the vehicle, putting rotating gunturrets on the vehicle, rocket launchers and missile emplacements, headlights, ect...

but I''m disgressing.... now, for the collision detection part, there should be plenty of code around that would give you the intersection point of a ray against a triangle/box/sphere/cylinder. If your world geometry has an octree of some sort, then it should not be hard to adapt it to work with the tree. apart from that, to test against another model, the model should be surrounded by a large axis aligned box / sphere that encompass the model geometry (and all the possible animations of that model), and once you found the ray intersecting with that rough volume, do further checks, like testing the ray against all triangles of the model, or if you have the bones of the model surrounded by a bounding volume (boxes, cylinders, or spheres), obviously test the bones volumes first, then the triangles connected to the bone.

for things like barb wire quads, fences, or flora, that can be tricky. a simple way is to have a random number to let a few bullets through once in a while.

for intersection tests, check out

http://www.realtimerendering.com/int/

hope that helps.

Share this post


Link to post
Share on other sites
Thanks olli,
though i''m afraid some of what youv''e explained here has gone over my head,so would you mind if i ask a few more ''simpler'' questions.

I''m using Bounding Sphere''s for detection with my world geomitry,which has no problems at all so far,with a skinned mesh,using some of the D3DX helper functions.
e.g..

D3DXFrameCalculateBoundingSphere(m_pFrameRoot,
&m_vObjectCenter,
&m_fObjectRadius);

I have also just a static(non-animated) mesh(X.File) that moves with my player,and is approx where the torus of the animated player is.

I have looked through(only briefly as the books belong to a friend of mine and i don''t own those books)Graphics Gems,and i have to admit,i didn''t understand it properly.

I have Game Programming Gems here,though becuase those examples are in OpenGL(i don''t know the API at all,only DirectX)it has confused the hell out of me.

Because all i''m trying to do is cast a ray to see if it intersects with an NPC''s(animated)character''s bounding sphere or box,surely wouldn''t it be a good idea to just cast the ray from the static x.file,that moves with the player character? (at his torso).


The main problem i am having is knowing how to actually ''cast a ray''using DirectX,from a static .x file model,and then to test if it intersects or not.

These are the 2 steps i must learn how and what i have to do first,before anything else,then i can move to something more advanced.

So thats basiclly all i need to know(for now) but i''m lost with it.I have tried doing something like this as well...

struct CUSTOMVERTEX
{
float,x,y,z;
}

CUSTOMVERTEX Vertices[]=
{
{-5.0, -5.0, 0.0},
{ 0.0, 5.0, 0.0},
{ 5.0, -5.0, 0.0},
{10.0, 5.0, 0.0},
{15.0, -5.0, 0.0},
{20.0, 5.0, 0.0}
};

and then ...
lpD3D_Dev->DrawPrimitive(D3DPT_LINESTRIP,0,5);

for a beam-type thing..
and several other things,though its casting the actual '' ray '' and then checking for an intersection which has me confused.

I''m really surpised that i can''t find any resources on the web,for anything like this or an example in the DX SDK or in my books,becuase without knowing these basic things,a 3D shooter game is out the window.

Please help,if you can.
Thanks.

Share this post


Link to post
Share on other sites
well, a ray casting collision code would have nothing to do with DirectX or openGL, but if it''s simpler for you...

the first step is calculating the ray. as a first measure, you can approximate the ray totally. so, cast from the centre of the sphere towards the direction of the player, as a first try.

the ray can be defined by two parameters. an origin vector (from where the ray starts), and a direction vector (where the ray ends).

as for a start, the ray start can be the centre of the sphere, or a point slightly above.


D3DXVECTOR xRayStart = m_vObjectCenter;
xRayStart.y += 1.0f; // one meter above the centre of the sphere, approximately head high.


D3DXMATRIX xModelOrientation; // the orietnation of your NPC.

D3DXVECTOR xRayDir = D3DXVECTOR(xModelOrientation(2, 0), xModelOrientation(2, 1), xModelOrientation(2, 2));


not sure how the D3D matrices are column or row major, and which axis you consider being the forward axis for your characters, but basically, the forward direction is either the first 3 values of a row or a column of the orientation matrix. maybe you''ll even have to negate the direction as well. Basically, either check values in the debugger, render a 3D line to make sure the direction is OK. In this example, I consider the third row of the matrix as being the direction where the player is pointing to.

now, you have two vectors, raypos and raydir, which define the instantaneous bullet trajectory. all you have to do is test the ray against the spheres surrounding the NPCs.

note that, you have a function in direct3D, which tests if a ray intersects with a mesh.

HRESULT D3DXIntersect
(
LPD3DXBASEMESH pMesh,
CONST D3DXVECTOR3* pRayPos,
CONST D3DXVECTOR3* pRayDir,
BOOL* pHit,
DWORD* pFaceIndex,
FLOAT* pU,
FLOAT* pV,
FLOAT* pDist
);



you also have a function that ''probe'' with a ray to see if a ray intersects a sphere.

BOOL D3DXSphereBoundProbe
(
CONST D3DXVECTOR3* pCenter,
FLOAT Radius,
D3DXVECTOR3* pRayPosition,
D3DXVECTOR3* pRayDirection
);

but it does not return the distance of the intersection. Which is fine if you consider doing a per-poly test after (like using the D3DXIntersect()).

if you plan on doing a FPS, you can fire a ray from 2D position of the mouse on screen, you can do a standard picking algo, and fire the ray that way.

anyway, if you search for D3DXIntersect() on google, and other related stuff, you''ll find a lot of examples related to your problem. Since I''m not Direct3D expert, all I could give you is platform independent code, which you don''t like.

as an example
http://www.experts-exchange.com/Programming/Game_Development/3D_Programming/Q_20812666.html

http://www.mvps.org/directx/articles/improved_ray_picking.htm

as a side note, if you decide to do bullet trajectory which would be more like very fast particles (so not isntantenous, but rather, the bullets actually travel through time), the same code still applies. all you have to do is shorten the ray, so it''s aligned with the position of the particle at two consecutive frames, and possibly slightly larger than the trajectory length between two frames (just to make sure). you can do the same as well for rockets, or any projectiles, so once you have the code working, you can use it for a wide variety of projectiles-type things.

Make sure you reject the geometry very fast when you lots of do ray-casting, as it can be very costly.

Share this post


Link to post
Share on other sites
you also have a box test too

D3DXBoxBoundProbe()

and the ones you pointed out

D3DXComputeBoundingSphere()
D3DXComputeBoundingBox()

Share this post


Link to post
Share on other sites
I found an example of the D3DXIntersection() in my RPG book,but there is something seriously wrong with using a skinned mesh with it,in DX9 you use a derived D3DXMESHCONTAINER with..

LPD3DXFRAME m_pFrameRoot; // The player
LPD3DXANIMATIONCONTROLLER m_pAnimationController;

LPD3DXFRAME m_pFrameRoot2; // The NPC
LPD3DXANIMATIONCONTROLLER m_pAnimationController2;

and i load skinned(and static) meshes like this..
// Player
CAllocateHierachy Alloc(this);
hr = D3DXLoadMeshHierarchyFromX(FileName,D3DXMESH_MANAGED,
lpD3D_Dev,&Alloc,NULL,&m_pFrameRoot,
&m_pAnimationController);

// NPC
CAllocateHierachy Alloc2(this);
hr = D3DXLoadMeshHierarchyFromX(FileName2,D3DXMESH_MANAGED,
lpD3D_Dev,&Alloc,NULL,&m_pFrameRoot2,
&m_pAnimationController2);

I calculate both their bounding sphere''s with...
// Player
hr = D3DXFrameCalculateBoundingSphere(m_pFrameRoot,
&m_vObjectCenter,
&m_fObjectRadius);

// NPC
hr = D3DXFrameCalculateBoundingSphere(m_pFrameRoot,
&m_vObjectCenter2,
&m_fObjectRadius2);


Now comes the confusion..

This is the example of using a skinned mesh with an.xfile as a level
(i''m trying to use 2 skinned meshes,the player & NPC).

//********************************************************
// Intersection functions
float GetHeightBelow(float XPos, float YPos, float ZPos);
BOOL CheckIntersect(float XStart, float YStart, float ZStart,
float XEnd, float YEnd, float ZEnd,
float *Length);
/////////////////////////////////////////////////////////////////
// The Frame function....
/////////////////////////////////////////////////////////////////
BOOL cApp::Frame()
{
static DWORD Timer = timeGetTime();
static short LastAnim = -1;
unsigned long Elapsed;
long Dir, i, j;
float XMove, ZMove, XPos, YPos, ZPos;
float Dist;
float Angles[13] = {
0.0f, 4.71f, 0.0f, 5.495f, 1.57f, 0.0f,
0.785f, 0.0f, 3.14f, 3.925f, 0.0f, 0.0f, 2.355f
};

// Calculate elapsed time (plus speed boost)
Elapsed = (timeGetTime() - Timer);
Timer = timeGetTime();

// Get input
m_Keyboard.Read();

// Process input and update everything.
// ESC quits program
if(m_Keyboard.GetKeyState(KEY_ESC) == TRUE)
return FALSE;

// Get movement
Dir = 0;
if(m_Keyboard.GetKeyState(KEY_UP) == TRUE)
Dir |= 1;
if(m_Keyboard.GetKeyState(KEY_RIGHT) == TRUE)
Dir |= 2;
if(m_Keyboard.GetKeyState(KEY_DOWN) == TRUE)
Dir |= 4;
if(m_Keyboard.GetKeyState(KEY_LEFT) == TRUE)
Dir |= 8;
XMove = ZMove = 0.0f;
if(Dir) {
m_Objects.Rotate(0.0f, Angles[Dir], 0.0f);
XMove = (float)cos(Angles[Dir]) * ((float)Elapsed * 0.25f);
ZMove = -(float)sin(Angles[Dir]) * ((float)Elapsed * 0.25f);
}

// Get object coordinates in local variables (make it easier)
XPos = m_Objects.GetXPos();
YPos = m_Objects.GetYPos();
ZPos = m_Objects.GetZPos();

// Check for collision in movement (4 points)
// I hard-coded the bounding size of the object (25 radius)
// and added ability to climb up at most 32 units.
for(i=0;i<4;i++) {
float XAdd[4] = { 0.0f, 25.0f, 0.0f, -25.0f };
float ZAdd[4] = { 25.0f, 0.0f, -25.0f, 0.0f };

if(CheckIntersect(XPos+XAdd,YPos+32.0f, ZPos+ZAdd[i],
XPos+XAdd[i]+XMove, YPos+32.0f, ZPos+ZAdd[i]+ZMove,
&Dist) == TRUE) {
// Clear out movement and break
XMove = ZMove = 0.0f;
break;
}
}

// Get object height
m_Objects.Move(XPos, GetHeightBelow(XPos, YPos+32.0f, ZPos), ZPos);

// Move object and set new animations as needed
if(XMove != 0.0f || ZMove != 0.0f) {
m_Objects.MoveRel(XMove, 0.0f, ZMove);

if(LastAnim != 1) {
LastAnim = 1;
m_Objects.SetAnimation(&m_Animations, "Walk", timeGetTime()/20);
}
} else {
if(LastAnim != 2) {
LastAnim = 2;
m_Objects.SetAnimation(&m_Animations, "Idle", timeGetTime()/20);
}
}

// Update object animations
m_Objects.UpdateAnimation(timeGetTime()/20, TRUE);

// Render everything
m_Graphics.ClearZBuffer();
if(m_Graphics.BeginScene() == TRUE) {
// Render simplified mesh for z-values
m_Graphics.EnableZBuffer(TRUE);
m_SceneObject.Render();

// Draw the backdrop (composed of six textures)
m_Graphics.EnableZBuffer(FALSE);
m_Graphics.BeginSprite();
for(i=0;i<2;i++) {
for(j=0;j<3;j++)
m_BDTextures[i*3+j].Blit(j*256,i*256);
}
m_Graphics.EndSprite();

// Draw the 3-D objects
m_Graphics.EnableZBuffer(TRUE);
m_Objects.Render();

m_Graphics.EndScene();
}
m_Graphics.Display();

return TRUE;
}
////////////////////////////////////////////////////////////////////
///////////// OTHER INTERSECT REL FUNCTIONS //////////////////////

float cApp::GetHeightBelow(float XPos, float YPos, float ZPos)
{
BOOL Hit;
float u, v, Dist;
DWORD FaceIndex;

D3DXIntersect(m_SceneMesh.GetParentMesh()->m_Mesh,
&D3DXVECTOR3(XPos,YPos,ZPos),
&D3DXVECTOR3(0.0f, -1.0f, 0.0f),
&Hit, &FaceIndex, &u, &v, &Dist);
if(Hit == TRUE)
return YPos-Dist;
return YPos;
}

BOOL cApp::CheckIntersect(float XStart, float YStart, float ZStart,float XEnd, float YEnd, float ZEnd,float *Length)
{
BOOL Hit;
float u, v, Dist;
float XDiff, YDiff, ZDiff, Size;
DWORD FaceIndex;
D3DXVECTOR3 vecDir;

XDiff = XEnd - XStart;
YDiff = YEnd - YStart;
ZDiff = ZEnd - ZStart;

D3DXVec3Normalize(&vecDir, &D3DXVECTOR3(XDiff, YDiff, ZDiff));
D3DXIntersect(m_SceneMesh.GetParentMesh()->m_Mesh,
&D3DXVECTOR3(XStart,YStart,ZStart), &vecDir,
&Hit, &FaceIndex, &u, &v, &Dist);

if(Hit == TRUE) {
Size = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
if(Dist > Size)
Hit = FALSE;
else {
if(Length != NULL)
*Length = Dist;
}
}

return Hit;
}


I notice that the first param for the D3DXIntersect()
takes a mesh..

D3DXIntersect(m_SceneMesh.GetParentMesh()->m_Mesh,
&D3DXVECTOR3(XStart,YStart,ZStart), &vecDir,
&Hit, &FaceIndex, &u, &v, &Dist);


How on earth could i do this in D3D9 with the way you now
used skinned meshes???

Please tell me if iv''e missed the ''jist'' of it.
Thanks.


Share this post


Link to post
Share on other sites
So you can see the problems i''m having,any ideas what to pass as the first param to the function?
That''s why i thought it may be a good idea to use 2(simple)meshes
attached to the player + npc,to test against each other,and pass the mesh for the NPC??

Share this post


Link to post
Share on other sites
as I say, I''m not savvy with DirectX. But, I can see two solutions. either convert the skinned mesh into a compaatible mesh, or do it by hand.

anyway, google again, and I found these

http://www.gamedev.net/community/forums/topic.asp?topic_id=127514

http://home.att.net/~rpgbook/fixes.htm

My guess is, you''ll probably have to extract the vertex buffers yourself, and probably generate the triangles fromn the bones in software, if you do full hardware skinning. And do the intersection yourself. The pick example in the SDK has examples on how to do vertex buffer triangle/ray intersection. The skinned mesh example has example on how to extract the mesh from the bones, and the bone data.

Share this post


Link to post
Share on other sites
Thanks for all the advice youv'e already given olli,it IS very much appreciated the help you gave with the camera system was also great. Some forums help like that is rare.

Basiclly,i think i need to brush up on various things before i tackle these issues i'm having,for example i definately need to brush up on some of the more advanced 3D/math concepts,which i've actually started today.

I'll post the results of what i'm trying to do afterward,because it may be useful for others,or if you don't mind helping again,i'll reply to this post(mathematics) as you seem very well versed in this area.

Thanks again.

[edited by - dirtbag on April 19, 2004 10:57:06 AM]

[edited by - dirtbag on April 19, 2004 10:58:27 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!