Getting distance of a point in a 2d triangle without calculating perpendicular..

@Eli Delventhal: how do you prevent a true response with infinitely far spheres that lie in the volume confined by the 3 planes? You have to check for the distance to a 4th plane too: the plane on which the triangle lies.

IMHO the method name ‘isPointInTriangle’ is incredibly misleading in 3D.

Eli, is the formula for

p.squaredDistance(a)

just


float dist = sqrt((p.x-a.x)^2 + (p.y-a.y)^2 + (p.y-a.y)^2
dist = dist * dist

?

Or simply remove the sqrt.


float xd = p.x-a.x, yd = p.y-a.y, zd = p.z-a.z;
float squaredDist = xd*xd + yd*yd + zd*zd;

Not sure exactly what you mean, Riven, but I’m sure this has issues in 3D. I was thinking in terms of 2D despite all the vectors being 3D vectors. If you can suggest specific code edits or be more clear that’d be handy for everyone.

What ra4king said. The point of using the squared distance is that you avoid needing to do square root calls, which are very costly. So it’s just: (p.x-a.x)^2 + (p.y-a.y)^2 + (p.z-a.z)^2.


public float squaredDistance( Vector3f other )
{
	Vector3f dist = other.subtract(this);
	return ( dist.x * dist.x + dist.y * dist.y + dist.z * dist.z );
}

Don’t copy and paste bugs :emo:

Don’t create new objects in code that is performance critical enough to get rid of a square root :emo:

Sad Riven is sad.

You’re always such a friendly person, Riven. I find the second part of your post to be purposelessly confrontational. This is not going to end up being a bottleneck in his code. First of all, he doesn’t use the vector class which has that function; the one I wrote in 30 seconds in an example java class (which you can see above if you were to scroll up). He uses the LWJGL vector class which just so happens forces you to instantiate extra vectors all over the place.

The entire point of posting that code snippet was to show him how to do what he needs to do, because clearly he doesn’t understand enough to be worrying about performance at this juncture. I considered not putting the squared magnitude up there (and using regular magnitude instead) because I figured he would get confused - because efficiency isn’t the point here. Looks like I should have done that, poor choice on my part.

Instead of your usual spiel of busting into a post and saying “you’re wrong, you’re wrong,” how about to respond to the question I posted above by clarifying what you meant when you pointed out the only actual bug in the code?

Here you go:


public float squaredDistance( Vector3f other )
{
   float xDiff = other.x - x;
   float yDiff = other.y - y;
   float zDiff = other.z - z;
   return ( xDiff * xDiff + yDiff * yDiff + zDiff * zDiff );
}

Not meant to be so rough on you, I thought that the emoticons revealed that I wasn’t too serious.

As per your request, here’s an image that shows the problem in 3D:

http://indiespot.net/files/temp/triangle-volume.png?v=3

From this, you can deduce that a sphere->triangle intersection works like this:
[x] ensure that the sphere either lies above or intersects plane A,B,C
[x] ensure that the sphere intersects plane D

Note that there is no need to calculate ‘is on same side’, which btw. contains a lot of redundant calculations, when you do it 3 times. The planes A,B,C already (should) have normals pointing towards the triangle.

Your code would have returned true for all spheres intersecting in the ‘triangle volume’ and those intersecting with the triangle edges.

Ah of course, I see what you mean. I’ll go in and edit this code at some point soon.

Sorry, I’ve had a bad day.

Alright, thank you all very much for your help so far. ;D ;D ;D

Is there anyway I can see if the point is facing the normal in this code (from Eli)? My player is getting stuck on corners.

Edit: I’m using the circle in triangle for ground collision, so it’s not going to waste. :>

public boolean isPointInTriangle( Vector3f p, Vector3f a, Vector3f b, Vector3f c )
	{
	    return ( pointsAreOnSameSide(p, a, b, c) && pointsAreOnSameSide(p, b, a, c) && pointsAreOnSameSide(p, c, a, b) );
	}

	public boolean pointsAreOnSameSide( Vector3f p1, Vector3f p2, Vector3f a, Vector3f b )
	{
	    Vector3f diffba = new Vector3f(0,0,0);
	    Vector3f.sub( b, a, diffba );
	    Vector3f diffp1a = new Vector3f(0,0,0);
	    Vector3f.sub( p1, a, diffp1a );
	    Vector3f diffp2a = new Vector3f(0,0,0);
	    Vector3f.sub( p2, a, diffp2a );

	    Vector3f cross1 = new Vector3f();
	    		Vector3f.cross(diffba, diffp1a, cross1);
	    Vector3f cross2 = new Vector3f(); 
	    		Vector3f.cross(diffba, diffp2a, cross2);

	    return ( Vector3f.dot( cross1, cross2 ) >= 0 );
	}

Not sure what you mean. Points do not have a direction, so they can’t face anything. And that code you pasted doesn’t have any normals in it. You shouldn’t need to redo anything to fix that bug - instead how you make your player react to collisions needs to be adjusted.