Sign in to follow this  
Bru

awww, i could use a gun right now

Recommended Posts

yeah yeah i know what you might think, 'what didnt that asshole solve his problem already?' i have to agree, i am an asshole for still not being able to solve my collision problem. well, i thought i solved the hard part(the part where i create a function that shoots a ray into a triangle), even if i did solve this the right way , i still cant manage to check collision. here's what i am trying to do to make my collision work : 1)i retrieve the vertex and index lists from the buffers 2)i make a loop, length is number of vertices /3 3)i pass three vertices,direction of my movement and the origin point of the player to the function that checks collision. 4)if there's a collision, i just add it's information to a list(so that if there's more than one collision point, i'll check which is the closest). 5)after the loop is over, i make a check if there was collision at all, if there was not, i let my player move, if there was i just do nothing(for now). **)right now i only check collision if i move toward the collision object, and not if i hit it. but it still gives odd results, sometimes it finds collision with some parts of the collision model, while on some other parts or directions it will not find collision(same thing for when i am not moving toward the collision object). so i try to do that like this: get vertex & index lists from buffers:
void GetLists()
{
VerticesNum = new D3DXVECTOR3[Mesh->GetNumVertices()];
IndexNum = new short[Mesh->GetNumFaces()*3];
DWORD stride = Mesh->GetNumBytesPerVertex();
BYTE* vbptr = NULL;
BYTE* ibptr = NULL;
DWORD Istride = sizeof(short);
Mesh->LockIndexBuffer(0,(LPVOID*)&ibptr);
Mesh->LockVertexBuffer(0, (LPVOID*)&vbptr);
D3DXVECTOR3 *pos = VerticesNum;
short *pos2 = IndexNum;

for (DWORD i = 0; i < Mesh->GetNumVertices(); i++)
{
   memcpy(pos, vbptr, sizeof(D3DXVECTOR3));
   vbptr += stride; 
   pos++;
}
for (DWORD k = 0; k < Mesh->GetNumFaces()*3; k++)
{
   memcpy(pos2, ibptr, sizeof(short));
   ibptr += Istride; 
   pos2++;
}
Mesh->UnlockIndexBuffer();
Mesh->UnlockVertexBuffer();

up until here everything's fine? then here's the part when i press forward
 velx=-(float)cos(MainPlayer->rotz+rad_90)*sin(MainPlayer->rotx+rad_90) *10.5;
		 vely=-(float)sin(MainPlayer->rotz+rad_90) *sin(MainPlayer->rotx+rad_90) *10.5;
		 velz=-(float)sin(MainPlayer->rotx) *10.5;
		 D3DXVECTOR3 dir(velx,vely,velz);D3DXVECTOR3 origin(MainPlayer->x,MainPlayer->y,MainPlayer->z);
		 CollisionInfo lengthcount[3];short count =0;CollisionInfo max;max.length =0;bool cold=false;int countertwo=0;
//lengthcount holds  the information if there's a collision
//count is not important here. cold is false if there was no collision.
//true data(defined globaly) just makes sure the vertices' are transformed to world space.
		
		 
		 for(int i=0;i<rock->Mesh->GetNumVertices()/3;i++)
		 {
			 if(truedata == false){
rock->VerticesNum[rock->IndexNum[countertwo]].x+=rock->x;
rock->VerticesNum[rock->IndexNum[countertwo]].y+=rock->y;
rock->VerticesNum[rock->IndexNum[countertwo]].z+=rock->z;
rock->VerticesNum[rock->IndexNum[countertwo+1]].x+=rock->x;
rock->VerticesNum[rock->IndexNum[countertwo+1]].y+=rock->y;
rock->VerticesNum[rock->IndexNum[countertwo+1]].z+=rock->z;
rock->VerticesNum[rock->IndexNum[countertwo+2]].x+=rock->x;
rock->VerticesNum[rock->IndexNum[countertwo+2]].y+=rock->y;
rock->VerticesNum[rock->IndexNum[countertwo+2]].z+=rock->z;

			 }
//code block above transforms the list into world space from model space.
 CollisionInfo col = Intersect(&rock->VerticesNum[rock->IndexNum[countertwo]],&rock->VerticesNum[rock->IndexNum[countertwo+1]],rock->VerticesNum[rock->IndexNum[countertwo+2]],dir,origin);
		 if (col.intersected == true)
		 {
			//unimportant stuff
                 }
		   countertwo+=3;
			
		 }
	       
                    truedata = true;
		    if(cold)
			   {
                          //unimportant stuff
               			}else{

             MainPlayer->y+=vely;
	     MainPlayer->x+=velx;
	     MainPlayer->z+=velz;
	     SecondPlayer->y+=vely;
	     SecondPlayer->x+=velx;
	     SecondPlayer->z+=velz;
			}

whew, alot of code, i tryed to clean it a bit of unimportant stuff so it would look smaller. now the last part is the function that checks collision which is :
CollisionInfo Intersect(D3DXVECTOR3 *vVertex1, D3DXVECTOR3 *vVertex2, D3DXVECTOR3 vVertex3,D3DXVECTOR3 dir,D3DXVECTOR3 origin)
{

    D3DXVECTOR3 vNormal;
	D3DXVECTOR3 vNormal2;
    D3DXVECTOR3 v1;
    D3DXVECTOR3 v2;
	D3DXVECTOR3 r1;
    D3DXVECTOR3 r2;
    D3DXVECTOR3 r3;
	float d1;
	float d2;
    CollisionInfo cola;
	float arr[3];//will hold information to check if point is inside triangle
    D3DXVECTOR3 lol;
    D3DXVec3Subtract(&v1, vVertex2, vVertex1);
    D3DXVec3Subtract(&v2, &vVertex3, vVertex1);
 
    D3DXVec3Cross(&vNormal, &v1, &v2);

    D3DXVec3Normalize(&vNormal, &vNormal);
//above is a code to calculate normal
	float DotProduct = D3DXVec3Dot(&vNormal,&dir);
	if(DotProduct<=0){
		
		cola.intersected = false;return cola;}
	float d = -(vVertex2->x*vNormal.x+vVertex2->y*vNormal.y+vVertex2->z*vNormal.z);//plane equation
    cola.length = -((D3DXVec3Dot(&origin,&vNormal)+d)/DotProduct);//t = -(Rayorigin*planeNormal+d)\(planenormal*direction)
	
	
    D3DXVECTOR3 dirT = dir;
    dirT.x*=cola.length;dirT.y*=cola.length;dirT.z*=cola.length;
	D3DXVec3Add(&lol,&origin, &dirT);
    D3DXVECTOR3 IntersectionPoint =lol;//calculate where is the intersection point
//now to calculate if the point is inside the triangle

    D3DXVec3Subtract(&r1, vVertex1, &IntersectionPoint);
    D3DXVec3Subtract(&r2, vVertex2, &IntersectionPoint);
    D3DXVec3Subtract(&r3, &vVertex3, &IntersectionPoint);
    origin.x*=-1; origin.y*=-1; origin.z*=-1;//invert the origin for the 'point in triangle' check.
 //calculate side 1
    D3DXVec3Cross(&vNormal2, &r1, &r2);
 D3DXVec3Normalize(&vNormal2, &vNormal2);
    d1=D3DXVec3Dot( &vNormal2, &origin);
    d2=3DXVec3Dot( &vNormal2, &IntersectionPoint);
    arr[0] = d1+d2;
//calculate side 2
    D3DXVec3Cross(&vNormal2, &r3, &r2);
    D3DXVec3Normalize(&vNormal2, &vNormal2);
    d1=D3DXVec3Dot(&vNormal2, &origin);
    d2=D3DXVec3Dot( &vNormal2, &IntersectionPoint);
    arr[1] = d1+d2;
//calculate side 3
    D3DXVec3Cross(&vNormal2, &r1, &r3);
    D3DXVec3Normalize(&vNormal2, &vNormal2);
    d1=D3DXVec3Dot( &vNormal2, &origin);
    d2=D3DXVec3Dot( &vNormal2, &IntersectionPoint);
    arr[2] = d1+d2;

	if(arr[0]<0 || arr[1]<0 || arr[2]<0 ){cola.intersected=false;return cola;}else{
		cola.intersected=true;
		
		cola.normal=vNormal;
	return cola;
}
}
yes, code is not clean. i've been debugging this for almost 2 weeks and i still didnt manage to find out what i did wrong there. does anyone see something wrong here? i'll appreciate help very much, i cant wait to be done with this already. thanks in advance, Bru. [Edited by - Bru on March 16, 2009 11:47:22 AM]

Share this post


Link to post
Share on other sites
Use [source] tags please.

Looks like you are checking whether the ray caused by the player's movement will collide, not just the line segment that he is actually trying to move along. Try adding an argument to Intersect for how far along the ray to check for collisions. Or, check the value of cola.Length (which I think is the distance to a collision?).

Quote:
if(DotProduct<=0){ cola.intersected = false;return cola;}

This test looks wrong way round to me ... you would expect to collide with faces with a normal pointing towards the ray origin, where this product will be negative.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bob Janova
Use source-tags please.


Not only source-tags, but also tools like astyle (man). Additionally, you might be careful with statements containing things like "could use a gun now" these days, but maybe you have missed recent RL.

Share this post


Link to post
Share on other sites
source tags, so that's what i've been lookin for.
on the subject, yes cola.length is the length between the origin and the intersection point. right now it is more important for me to check if the player is moving toward the collision object rather than check if there is collision, which is easy and i'll take care of it later.

you say this check is not right? i thought it is to make sure the ray direction is into the plane and not parallel to it or moving in a direction that will never intersect the plane.
anyway, without the check the collision function always returns true(atleast for most directions).

Share this post


Link to post
Share on other sites
Quote:
Original post by phresnel
People, do not quote Bob Janova [smile]


eh... commenting bob makes it source?

Share this post


Link to post
Share on other sites
Don't bang your head on the wall. Collision detection ain't that easy if you try for the first time. Without reading all of your code due to the wierd formatting and the disturbing commenting of code blocks behind a block you should check for collisions like so


D3DXVECTOR3 cam_pos = ... whatever your camera position is
D3DXVECTOR3 cam_dir = ... whatever your camera direction is
FLOAT u = 0.0f;
FLOAT v = 0.0f;
FLOAT distance = 0.0f;
BOOL intersection = FALSE;

for (uint i=0; i<Mesh->getNumIndices () / 3; ++i)
{
ushort i0 = rock->IndexNum[i*3];
ushort i1 = rock->IndexNum[i*3+1];
ushort i2 = rock->IndexNum[i*3+2];

intersection = D3DXIntersectTri(&rock->VerticesNum[i0], // IN the triangle
&rock->VerticesNum[i1],
&rock->VerticesNum[i2],
&cam_pos, // IN the camera
&cam_dir,
&u, &v, // OUT texture coordinates of intersection
&distance); // OUT distance of intersection from camera
if ((intersection == TRUE) && distance < cam_radius))
{
break;
}
else
{
intersection = FALSE;
}
}

if (intersection)
{
... then handle it!
}

Again, you get the idea. Do not implement ray triangle intersection yourself for now. The DX SDK has a lot of functionality. Use that until it works and you can name a valid reason to replace it!

Using this code you would have a valid and functional collision detection. Just make sure that the camera and the vertices are in the same coordinate system (preferably world) and that you do not apply a transformation matrix when rendering (unless you apply this matrix as well to rock's vertices for the purpose of collision detection).

If this still does not work then your camera information (position and direction) is not correct.

Finally note that you would need some hierarchical collision detection when dealing with a lot of geometry. Looping through all of your triangles in your 3d scene would be too slow if your scene becomes more complex.

Share this post


Link to post
Share on other sites
Quote:
Original post by Waterwalker
Don't bang your head on the wall. Collision detection ain't that easy if you try for the first time. Without reading all of your code due to the wierd formatting and the disturbing commenting of code blocks behind a block you should check for collisions like so


D3DXVECTOR3 cam_pos = ... whatever your camera position is
D3DXVECTOR3 cam_dir = ... whatever your camera direction is
FLOAT u = 0.0f;
FLOAT v = 0.0f;
FLOAT distance = 0.0f;
BOOL intersection = FALSE;

for (uint i=0; i<Mesh->getNumIndices () / 3; ++i)
{
ushort i0 = rock->IndexNum[i*3];
ushort i1 = rock->IndexNum[i*3+1];
ushort i2 = rock->IndexNum[i*3+2];

intersection = D3DXIntersectTri(&rock->VerticesNum[i0], // IN the triangle
&rock->VerticesNum[i1],
&rock->VerticesNum[i2],
&cam_pos, // IN the camera
&cam_dir,
&u, &v, // OUT texture coordinates of intersection
&distance); // OUT distance of intersection from camera
if ((intersection == TRUE) && distance < cam_radius))
{
break;
}
else
{
intersection = FALSE;
}
}

if (intersection)
{
... then handle it!
}

Again, you get the idea. Do not implement ray triangle intersection yourself for now. The DX SDK has a lot of functionality. Use that until it works and you can name a valid reason to replace it!

Using this code you would have a valid and functional collision detection. Just make sure that the camera and the vertices are in the same coordinate system (preferably world) and that you do not apply a transformation matrix when rendering (unless you apply this matrix as well to rock's vertices for the purpose of collision detection).

If this still does not work then your camera information (position and direction) is not correct.

Finally note that you would need some hierarchical collision detection when dealing with a lot of geometry. Looping through all of your triangles in your 3d scene would be too slow if your scene becomes more complex.

wow, this is like the best reply i ever got! i am used to answers that are so complex and sound all einstein that i bearly understand the point. but your post cleared two things for me :
1)yeah, probably should use built in functions to do my work. i just felt like learning doing it myself.
2)something i didnt think about is the applying matrix transformation to the rock's vertices(only thing i did was manulay translating the coordinates), it sounds reasonble that this might be causing the problem, should i have also applied scale and rotation?.

i would like to ask another question if its not too rude. what are those u and v variables? i do know they are texture coordinates but this is nothing graphical, why do i need texture coordinates in this function?

also, i rate you as extremly helpfull :)

Share this post


Link to post
Share on other sites
1) First things first. Use build in functionality to make things work. If you are sure your program works as it should then start replacing those functions with your own implementation for the sake of learning how to do things.

2) It does not matter in which coordinate system you check for a collision as long as camera and vertices are in the same coodinate system. That means either apply the vertices' world transformation to the vertices when checking for collision (because that results in the position where your geometry is actually rendered and perceived) or apply inverse transformation to your camera position and direction. The latter is obviously faster since its just transformation two vectors as opposed to getNumVertices(). However, take care when transforming the camera direction vector. Do not apply translation or scaling, just rotation. If you go and transform all vertices apply the very same transformation matrix as you set for rendering.

3) thanks for rating me up :)

editThe u and v coordinates are more or less just garbage ... well not really. You could use this information for changing the triangles texture (if any) at this particular pixel. Its just that the algorithm used for the intersection detection does calculate u and v anyway so they are provided as output result, too. Just because they are already there and some people might used them for further analysing the collision.

Share this post


Link to post
Share on other sites
Wast of time dude, I did this years ago and it only resulted in collision detection that was so slow it was unusable. Just find a physics API and stop pounding your head on the table.

Share this post


Link to post
Share on other sites
Quote:
Original post by CodaKiller
I did this years ago and it only resulted in collision detection that was so slow it was unusable.

Well, that does not mean that implementing a custom collision detection system is generally bound to be slow and unusable, now does it?

After all Bru said he is doing this for learning and (at least I assume) for the sake of the fun of just doing it. Also, when done right you won't suffer any performance impact, e.g. when using hiearchies such as octrees or optimize in the right places such as inverse transformation of the camera position as opposed to transforming all vertices.

Share this post


Link to post
Share on other sites
If it was 'years ago' then even your code will be 50-100 times faster today. For a finished game I would recommend using the library but it is well worthwhile learning how things work in my opinion.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bob Janova
Wait, what?


Because if we quote your first post, then your mentioning of [ source ] will break all the layout [smile].

Quote:

And yeah, the code is not well written, but at least with a XXX tag it doesn't give me a horizontal scrollbar :p

Ah no, the astlye suggestion was targetted at the OP :D

edit: D'Oh, it happened again :/

Share this post


Link to post
Share on other sites
oh wow, it still doesnt work.
i mean i am pretty sure my direction is correct and so is my player's position data(i even manipulated the vertices with rock's world matrix,and vice versa i also later tryed entering 0,0,0 as the position) am i realy still doing something wrong?

Share this post


Link to post
Share on other sites
If you haven't already, my advice to you would be to distill the problem down to its most basic elements. Create a mesh with only 3 vertices and try to reproduce the problem there. If you can, you know something is specifically wrong with your line segment / triangle test. Otherwise you know to look elsewhere, such as at your vertex gathering (i.e. Are you generating actual triangles to check against).

The best way to go about programming is to compartmentalize everything, whether it be a function or class. Once you do that, you can test each chunk by itself and feel confident that once each chunk works you no longer need to worry about them.

The key is to divide and conquer - that can never be said enough!

Share this post


Link to post
Share on other sites
Quote:
Original post by earl
If you haven't already, my advice to you would be to distill the problem down to its most basic elements. Create a mesh with only 3 vertices and try to reproduce the problem there. If you can, you know something is specifically wrong with your line segment / triangle test. Otherwise you know to look elsewhere, such as at your vertex gathering (i.e. Are you generating actual triangles to check against).

The best way to go about programming is to compartmentalize everything, whether it be a function or class. Once you do that, you can test each chunk by itself and feel confident that once each chunk works you no longer need to worry about them.

The key is to divide and conquer - that can never be said enough!


i'll do that soon, but first i found something intresting that is causing the problem.

i printed VerticesNum into a textfile, and then compared with the original mesh. what i found out is that the x and z coordinates of every vertex are almost the same(probably not the same because in the mesh file it is printed as a double and probably in the buffer it is a float). yet the y coordinate in the VerticesNum buffer is completly diffrent than the one in the original mesh.
i've put the code that gets the vertex buffer on the first post. anybody knows what's wrong with it?

Share this post


Link to post
Share on other sites
Couple of things to check:

- Does GetNumBytesPerVertex( ) == sizeof(D3DXVECTOR3)?
- Are you comparing VerticesNum before or after you transform to world space?
- If you're comparing both in world space, are you transforming VerticesNum to world space correctly?

Share this post


Link to post
Share on other sites
Quote:
Original post by earl
Couple of things to check:

- Does GetNumBytesPerVertex( ) == sizeof(D3DXVECTOR3)?
- Are you comparing VerticesNum before or after you transform to world space?
- If you're comparing both in world space, are you transforming VerticesNum to world space correctly?

- Does GetNumBytesPerVertex( ) == sizeof(D3DXVECTOR3)? it seems like not.

- Are you comparing VerticesNum before or after you transform to world space?-before

- If you're comparing both in world space, are you transforming VerticesNum to world space correctly? - i think so, i use D3DXVec3TransformCoord to multiply each cell in the verticesnum array with rock's matrix(scale*rotation*translate);

Share this post


Link to post
Share on other sites
What values are returned by the GetNumBytesPerVertex( ) and sizeof(D3DXVECTOR3) calls?

You could try setting stride to sizeof(D3DXVECTOR3) rather than GetNumBytesPerVertex( ) and see if that helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by earl
What values are returned by the GetNumBytesPerVertex( ) and sizeof(D3DXVECTOR3) calls?

You could try setting stride to sizeof(D3DXVECTOR3) rather than GetNumBytesPerVertex( ) and see if that helps.


GetNumBytesPerVertex( ) is 32, the size of the d3dxvector3 is 12.
already tryed that, it didnt help.

Share this post


Link to post
Share on other sites
Well it will be much easier to debug with only 1 triangle in the mesh. I suggest that be your next step.

Share this post


Link to post
Share on other sites
Quote:
Original post by earl
Well it will be much easier to debug with only 1 triangle in the mesh. I suggest that be your next step.


i doubt that would help, i already found out the y coordinate is not copyed properly, so using a 1 triangle mesh would just bring me the same result.

Share this post


Link to post
Share on other sites
Unless you already know why it's not copying the y coordinate correctly, you have no way of knowing whether cutting it down to 1 triangle would help you debug or not.

You may even find it suddenly seems to copy correctly with only 1 triangle, in which case, adding another triangle into the mix would potentially shed more light on the problem.

It is generally a good idea when debugging to cut as much complexity out as you can until you've reduced the problem to its fundamental parts. Even if the problem vanishes and is only reproducible with the more complex scenario, you've still learned a valuable piece of information.

At any rate, cutting the mesh down to 1 triangle shouldn't be a very time consuming task, so isn't it worth just trying?

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