•      Sign In
• Create Account

# Mesh - Elipse Collision Detection and Response Problem

No replies to this topic

### #1BlueSpud  Members   -  Reputation: 342

Like
0Likes
Like

Posted 05 February 2014 - 03:27 PM

Hi,

So for hours Ive been working on collision detection with triangle meshes and ellipses. The paper I've been using for reference can be found here:

http://www.peroxide.dk/papers/collision/collision.pdf

After a few hours of toiling, I've gotten the collision detection piece working pretty well, I just haven't implemented the collision detection for checking the edges, but this shouldn't be effecting the collision results when it is ellipse to triangle collision. When it comes to the response step, the thing just kind of falls apart. It kind of works, but it seems to be moving the ellipse back away from the triangle as well as sliding it, so obviously something is wrong. I've read the papers several times over and tried many different things, but I haven't been able to figure out quite whats going on with this strange problem. Here is the assorted code that goes with the collision detection and response:

The detection code, this is run for each mesh and then the results are reported back to the physics class

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));
if (abs(distance) < 2)
{
//normal dot velocity
float ndv = glm::dot(normal, velocity);
//times of intersection
float time1 = (1.0f - distance)/ndv;
float time2 = (-1.0f - 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 > 1)
time2 = 1;
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));
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));

float closest = 0;
int triangle = 0;
bool initial = false;
//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)
{

//get the distance to the collision
float distanceToCollision = results[0].time0*glm::length(velocity);
if (initial == false || distanceToCollision < closest )
{
//this one was less than the previos one
initial = true;
closest = distanceToCollision;
triangle = i;
}

}
}
//we store the information for the closest collision here
closestResults.i = triangle;
closestResults.distance = closest;
closestResults.packet = results[triangle];
results.clear();

}


The response code:

void physics::collisions()
{
if (pysObjs.size() > 0)
{
//here we're going to test all the collision objects and apply the collision response to the nearest collision
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));
int object = 0;
float distance = 0;
bool initial = false;
std::vector<collisionResultsPacket>results;
for (int i = 0; i < pysObjs.size(); i++)
{
//we need to test each mesh and see which is the closest triangle from all the meshes
pysObjs[i].testCollisionMeshWithElipsoid(0);
//we just got the closest result for that mesh
//now we test if that is closer than the one we already have
if (initial == false || pysObjs[i].closestResults.distance < distance )
{
initial = true;
distance = pysObjs[i].closestResults.distance;
object = i;
}
}

//now we have the colsest collision point and we can calculate the collision response properly
if (pysObjs[object].closestResults.packet.collided == true)
{
glm::vec3 newPosition = basePos + (glm::normalize(velocity)*(pysObjs[object].closestResults.distance - 0.005f));
glm::vec3 intersectionPoint = pysObjs[object].closestResults.packet.intersectionPoint; //- (glm::normalize(velocity)*0.005f);
glm::vec3 slingingPlaneOrigin = intersectionPoint;
glm::vec3 slidingPlaneNormal = glm::normalize(newPosition - intersectionPoint);
float distanceCollision = glm::dot(slidingPlaneNormal, destination) - ((slidingPlaneNormal.x*slingingPlaneOrigin.x)+(slidingPlaneNormal.y*slingingPlaneOrigin.y)+(slidingPlaneNormal.z*slingingPlaneOrigin.z));
destination = destination - (distanceCollision)*slidingPlaneNormal;

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

}
}


I've been working at this for hours, and if theres some obvious or not so obvious mistake in here, I would greatly appreciate anyone pointing it out. Thanks.

Sponsor:

PARTNERS