Advertisement

Sphere - triangle intersections

Started by July 15, 2015 05:27 PM
15 comments, last by Pilpel 9 years, 6 months ago

I finished reading this paper, and I almost completely implemented the technique as well. I got a few questions:

(note that I'm still working with spheres, not ellipsoids)

1. In line 47, in the collision response algorithm:


// only update if we are not already very close
// and if so we only move very close to intersection..not
// to the exact spot.
if (collisionPackage->nearestDistance >= veryCloseDistance)
{
  VECTOR V = vel;
  V.SetLength(collisionPackage->nearestDistance - veryCloseDistance);
  newBasePoint = collisionPackage->basePoint + V;
  // Adjust polygon intersection point (so sliding
  // plane will be unaffected by the fact that we
  // move slightly less than collision tells us)
  V.normalize();
  collisionPackage->intersectionPoint -= veryCloseDistance * V;
}

Why is it needed to move close to the intersection point and not exactly to it?

2. I'm having an issue that causes my character (the sphere) to get into the triangle a little bit, before reaching the "desired" slide plane and stopping that bug. After some debugging, I'm almost sure that this is a floating-point precision issue.

Say the triangle is on the Z axis, in z = -5 , and my sphere (a unit sphere with radius=1) bums into it, its initial "stop" position is at z = -3.85~, and then it slowly reaches the desired -4 (and stops there, as desired) after a few seconds.

I'm working with floats, but I don't think that switching to doubles will fix the issue. Any idea?

Did you try to allow for some penetration? Usually it is a good idea not to resolve the penetration to the exact touching configuration since this will indeed lead to numerical issues. A good tolerance helps with numerical issues, but is visually not noticeable. A good start might be 0.005 (e.g. 0.5 cm) if you use meters as your unit. So in your example don't drive towards -4, but -3.995 and keep objects slightly touching.

Advertisement

You state two different approaches. When you say "allow some penetration" that should mean I go beyond -4, towards -4.005.

Afterwards you say I should drive towards -3.995. No?

Right, sorry I read your example the other way around. You should essentially stop after you made contact with your triangle (z <= -4) and then only resolve penetration if z < -4.005.

Why do you stop so early (z = -3.85)? This doesn't sound like a precision error, but like a bug. This looks like your are using a collision margin of 0.15 (which is 15% of the sphere radius).

First I stop at z = -3.85~, then over like 2 seconds I keep moving slowly towards -4.

It's like the precision first sets me at -3.85, and then as a result of working with smaller numbers it allows for more precise results, and gets me closer and closer to z = -4.

I'm confident that this is the case after debugging for some time.

Edit:

Here's an output of the camera position. Look at the z values.

This explains why I get the feeling that my character penetrates the triangle just a little bit before reaching the absolute stop at z = -4.

Untitled.png

Those values seem to be consistent with a multiplication by a power of 0.85.

-3.915 - 0.015 * 0.85^1 = -3.92775
-3.92775 - 0.015*0.85^2 = -3.9385875 (rounded of to -3.93859)
-3.93859 - 0.015*0.85^3 = -3.947801875 (rounded of to -3.9478)
-3.9478 - 0.015*0.85^4 = -3.95563009375 (rounded of to -3.95563)
etc...

That seems to indicate that you're not stopping a fixed distance from the intersection point, but use a percentage instead.

Advertisement

That's very weird. I don't use a percentage-based algorithm and so does the author of the article.

Nonetheless the problem you mentioned arises in the first function (the collision detection). It sets nearestDistance (can also call it distanceToIntersection) in the same way you noted.

Untitled.png

Here's the function itself. Most collisions occur in the std::cout << "collision inside the triangle!\n"; line.

Can you follow and tell me what's wrong? I can't find anything that may cause this problem.

Edit:

I'm still on this. The "mistake" is done in the very beginning, where the "t0" variable in my function is calculated.

It doesn't set the velocity to stop on the triangle, but rather a few steps before it, and then lets the sphere penetrate a little more over time.

The "t" calculation from the code I posted:


// N dot D is not 0. Calculate intersection interval:
t0=(-1.0f-signedDistToTrianglePlane)/normalDotVelocity;
t1=( 1.0f-signedDistToTrianglePlane)/normalDotVelocity;
 
// Swap so t0 < t1
if (t0 > t1) {
    float temp = t1;
    t1 = t0;
    t0 = temp;
}

Any idea?

glm::vec3 planeIntersectionPoint = (colPackage->basePoint - trianglePlane.normal()) + t0 * colPackage->velocity;

Why are you subtracting the triangle plane normal here? I would think the intersection point would be sphere position + t0 * velocity, where t0 is the fraction of the velocity to the plane.

It's explained on page 14.

Untitled.png

The sphere is a unit sphere, so subtracting the plane normal will get us exactly to the perimeter of the sphere.

By the way, I tried your approach and it gives buggy results.

Could it be related to my collisionResponse function?


void solveCollision(CollisionPacket *colPacket)
{
	//slide plane from point and normal
	Plane slidePlane(colPacket->intersectionPoint, colPacket->basePoint - colPacket->intersectionPoint);
	cout << "slidePlane: " << slidePlane << endl;

	//destination point as if there was no collision response
	glm::vec3 destinationPoint = colPacket->basePoint + colPacket->velocity;
	
	//new destination point
	glm::vec3 newDestinationPoint = destinationPoint - slidePlane.signedDistanceTo(destinationPoint) * slidePlane.normal();
	
	glm::vec3 intersectionToNewDestination = newDestinationPoint - colPacket->intersectionPoint;
	colPacket->velocity = colPacket->velocity * colPacket->nearestDistance + intersectionToNewDestination;
}

Edit:

I also switched from floats to doubles, still no good.

Ah I see, well I don't see anything pop out really. How do you calculate the signed distance to a plane?

What happens if you remove the collision response and just stop once you collide?

This topic is closed to new replies.

Advertisement