Jump to content
  • Advertisement
Sign in to follow this  
BlueSpud

Collision Response Jerky

This topic is 2068 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've been implementing the collision detection and response detailed in this paper:http://www.peroxide.dk/papers/collision/collision.pdf I've got it mostly working now, but the collision response is a bit jumpy. I've only implemented collision inside the triangle but for what I've testing it against, it doesn't make a difference. Here is my code:

bool physicsObject::onSameSide(glm::vec3 point, glm::vec3 p1, glm::vec3 p2, glm::vec3 p3)
{
glm::vec3 cross1 = glm::cross(p3-p2, point-p2);
glm::vec3 cross2 = glm::cross(p3-p2, p1-p2);
if (glm::dot(cross1, cross2) >= 0.0)
return true;
else return false;

}

collisionResponsePacket physicsObject::checkTriangle(unsigned int i)
{
collisionResponsePacket packetToReturn;
glm::vec3 velocity = playerESpace.vecInElipsoidSpace( glm::vec3(-camx,-camy,-camz)-glm::vec3(-lcamx,-lcamy,-lcamz));
glm::vec3 basePos = playerESpace.vecInElipsoidSpace(glm::vec3(-lcamx,-lcamy,-lcamz));

//for now, we're just going to check the one triangle.
//.obj stores vertexes in counter-clockwise order, so we're going to swap the positions.
glm::vec3 p1 =playerESpace.vecInElipsoidSpace( (glm::vec3(ModelRegistry.models[model].m.obj[i].x3,ModelRegistry.models[model].m.obj[i].y3,ModelRegistry.models[model].m.obj[i].z3)));
glm::vec3 p2 = playerESpace.vecInElipsoidSpace((glm::vec3(ModelRegistry.models[model].m.obj[i].x2,ModelRegistry.models[model].m.obj[i].y2,ModelRegistry.models[model].m.obj[i].z2)));
glm::vec3 p3 = playerESpace.vecInElipsoidSpace((glm::vec3(ModelRegistry.models[model].m.obj[i].x1,ModelRegistry.models[model].m.obj[i].y1,ModelRegistry.models[model].m.obj[i].z1)));

//get the normal
glm::vec3 normal = glm::normalize(glm::cross(p2-p1, p3-p1));

//get signed distance
float distance = glm::dot(normal, basePos) - ((normal.x*p1.x)+(normal.y*p1.y)+(normal.z*p1.z));
//normal dot velocity
float ndv = glm::dot(normal, velocity);
//times of intersection
float time1 = (1.0 - distance)/ndv;
float time2 = (-1.0 - distance)/ndv;

if (time1 > time2)
{
float temp = time2;
time2 = time1;
time1 = temp;
}
if (time1 > 1.0 || time2 < 0.0)
{
//do something to say there wasn't a collision here
}
else
{
if (time2 > 10)
time2 = 0;
if (time1 < 0.0)
time1 = 0;

//get the point where we think that the sphere is going to collide
glm::vec3 intersectionPoint = (basePos + (time1*velocity*(float)0.95)) - normal;

//now we need to check if this collided
if (onSameSide(intersectionPoint, p1, p2, p3) && onSameSide(intersectionPoint, p2, p1, p3) && onSameSide(intersectionPoint, p3, p1, p2))
{
//there was a collision inside the triangle, so wer're done here.
packetToReturn.intersectionPoint = intersectionPoint;
packetToReturn.time0 = time1;
packetToReturn.time1 = time2;
packetToReturn.collided = true;
}
else
{
//temp, I just want to be able to check more complex meshes
return packetToReturn;
//there wasn't a collision inside the triangle so now for the fin stuff, we get to check the collision for the edges and points.
//this is also called the sweep test

//first we check collisions with the vertexes
}
}

return packetToReturn;
}


void physicsObject::testCollisionMeshWithElipsoid(double time)
{
//some of the vectors we require for the response
glm::vec3 velocity = playerESpace.vecInElipsoidSpace( glm::vec3(-camx,-camy,-camz)-glm::vec3(-lcamx,-lcamy,-lcamz));
glm::vec3 basePos = playerESpace.vecInElipsoidSpace(glm::vec3(-lcamx,-lcamy,-lcamz));
glm::vec3 destination = playerESpace.vecInElipsoidSpace(glm::vec3(-camx,-camy,-camz));

std::vector<collisionResponsePacket>results;
for (int i = 0; i < ModelRegistry.models[model].m.obj.size(); i++)
//we chech each triangle
results.push_back(checkTriangle(i));

//now we find which one we are going to respond against, then do it
for (int i = 0; i < results.size(); i++)
{
if (results[i].collided == true)
{

//we found the droids we are looking for ;)
glm::vec3 newPosition = basePos + (velocity*results[i].time0*0.9f);
glm::vec3 intersectionPoint = results[i].intersectionPoint - (velocity*results[i].time0*0.9f);
glm::vec3 slingingPlaneOrigin = intersectionPoint;
glm::vec3 slidingPlaneNormal = glm::normalize(newPosition - intersectionPoint);
float distance = glm::dot(slidingPlaneNormal, destination) - ((slidingPlaneNormal.x*slingingPlaneOrigin.x)+(slidingPlaneNormal.y*slingingPlaneOrigin.y)+(slidingPlaneNormal.z*slingingPlaneOrigin.z));
destination = destination - (distance)*slidingPlaneNormal;


//convert the new point back into what the camera will take
// lcamx = results[i].intersectionPoint.x;
//lcamy = results[i].intersectionPoint.y;
//lcamz = results[i].intersectionPoint.z;
//now we can update everything
camx = -destination.x*ELIPSE_X;
camz = -destination.z*ELIPSE_Z;
camy = -destination.y*ELIPSE_Y;

break;
}
}
results.clear();
}

I know its very inefficient, but I want the functionality there first. I've looked at the sample code in the paper but I haven't been able to work out whats wrong. I'm not recursing, but when I do, the camera warps to different places. What I want to know what is wrong with the length of the velocities, etc that would cause this kind of problem. Any help or information would be appreciated.

 

EDIT:

I've tried dividing the distance variable, this one: "destination - (distance)*slidingPlaneNormal;" and that seems to smooth it out but it seems to cause inaccuracies in the response and causing the camera to clip through the world.

Share this post


Link to post
Share on other sites
Advertisement

Formatting of your code is messed up there?

 

Anyway, this looks bad

 

if (time2 > 10)
time2 = 0;
if (time1 < 0.0)
time1 = 0;

 

Dunno why 10 turns up there do you mean 1.0? And if it's bigger than 10 (or 1.0) don't set it to zero set it to 1.0 or 10.

Share this post


Link to post
Share on other sites

Formatting of your code is messed up there?

 

Anyway, this looks bad

 

if (time2 > 10)
time2 = 0;
if (time1 < 0.0)
time1 = 0;

 

Dunno why 10 turns up there do you mean 1.0? And if it's bigger than 10 (or 1.0) don't set it to zero set it to 1.0 or 10.

Thanks for pointing that out. I'm pretty sure that that shouldn't matter because, after that line nothing is being done with time2 because the collision is not fully implemented.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!