예제 #1
0
/*-<==>-----------------------------------------------------------------
/ 
/----------------------------------------------------------------------*/
bool CSphere::hits (const CLine &line, SCALAR &t_hit) {
  // Pendiente de implementar correctamente
	
	// REVISADA

	VECTOR aux = line.loc - loc;
	SCALAR b = aux.dot(line.dir);
	SCALAR c = aux.dot(aux) - radius*radius;
	SCALAR d = b*b - c;
	if (d<0)
			return false; // Noqueremos negativos pq no toca linea con esfera
	else{
		SCALAR tm = -b - sqrt(d); // -b - SQRT(b^2 -4ac)
		SCALAR tM = -b + sqrt(d);// -b + SQRT(b^2 -4ac)
		if(tm > 0)	{
			t_hit = tm;
			return true;
		}
		
		if(tM > 0){
			t_hit = tM;
			return true;
		}
	}
	  return false;
}
예제 #2
0
/*
--------------------------------------------------------------------------------------------------
- check collision with stairs
--------------------------------------------------------------------------------------------------
*/
bool PlanesPhysicHandler::ColisionWithStair(const AABB & actorBB, const VECTOR &Speed, VECTOR &ModifiedSpeed)
{
    float moveX = Speed.x;
    float moveZ = Speed.z;

    // calculate norm of speed
    VECTOR speedNorm = Speed.unit();

    float startX = (actorBB.P.x+actorBB.E.x)/2.0f;
    float startZ = (actorBB.P.z+actorBB.E.z)/2.0f;

    std::vector<StairPlane>::const_iterator it = _stairs.begin();
    std::vector<StairPlane>::const_iterator end = _stairs.end();

    // for each stairs
    for(int i=0; it != end; ++it, ++i)
    {
        // project point to plane and check if we cross it
        float DotProduct=speedNorm.dot(it->Normal);

        // Determine If Ray Parallel To Plane
        if (abs(DotProduct) > 0.000001f)
        {
            // Find Distance To Collision Point
            float l2=(it->Normal.dot(it->C1-VECTOR(startX, actorBB.P.y, startZ)))/DotProduct;

            // Test If Collision Behind Start or after end
            if (l2 > 0 && l2 < Speed.length())
            {
                float collionsX = startX + (speedNorm.x * l2);
                float collionsZ = startZ + (speedNorm.z * l2);

                if((collionsX >= it->minX) && (collionsX <= it->maxX))
                {
                    if((collionsZ >= it->minZ) && (collionsZ <= it->maxZ))
                    {
                        VECTOR spmY(Speed.x, 0, Speed.z);
                        VECTOR Vt(it->Normal.dot(spmY)*it->Normal);
                        VECTOR Vn(spmY - Vt);
                        ModifiedSpeed = Vn;
                        return true;
                    }
                }
            }
        }
    }

    return false;
}
예제 #3
0
// Assumes: p1,p2 and p3 are given in ellisoid space:
void checkTriangle(CollisionPacket* colPackage,VECTOR p1,VECTOR p2,VECTOR p3)
{
    #ifndef __GNUC__
	// Make the plane containing this triangle.
	PLANE trianglePlane(p1,p2,p3);

	// Is triangle front-facing to the velocity vector?
	// We only check front-facing triangles
	if (trianglePlane.isFrontFacingTo(colPackage->normalizedVelocity) || (! isBackCulling)) 
	{
		// Get interval of plane intersection:
		double t0, t1;
		bool embeddedInPlane = false;
	
		// Calculate the signed distance from sphere
		// position to triangle plane
		double signedDistToTrianglePlane =	trianglePlane.signedDistanceTo(colPackage->basePoint);
		
		// cache this as we're going to use it a few times below:
		float normalDotVelocity =	trianglePlane.normal.dot(colPackage->velocity);
		
		// if sphere is travelling parrallel to the plane:
		if (normalDotVelocity == 0.0f) 
		{
			if (fabs(signedDistToTrianglePlane) >= 1.0f) 
			{
				// Sphere is not embedded in plane.
				// No collision possible:
				return;
			}
			else 
			{
				// sphere is embedded in plane.
				// It intersects in the whole range [0..1]
				embeddedInPlane = true;
				t0 = 0.0;
				t1 = 1.0;
			}
		}
		else 
		{
			// N dot D is not 0. Calculate intersection interval:
			t0=(-1.0-signedDistToTrianglePlane)/normalDotVelocity;
			t1=( 1.0-signedDistToTrianglePlane)/normalDotVelocity;
		
			// Swap so t0 < t1
			if (t0 > t1) {
				double temp = t1;
				t1 = t0;
				t0 = temp;
			}
			
			// Check that at least one result is within range:
			if (t0 > 1.0f || t1 < 0.0f) 
			{
				// Both t values are outside values [0,1]
				// No collision possible:
				return;
			}
			
			// Clamp to [0,1]
			if (t0 < 0.0) t0 = 0.0;
			if (t1 < 0.0) t1 = 0.0;
			if (t0 > 1.0) t0 = 1.0;
			if (t1 > 1.0) t1 = 1.0;
		}

		// OK, at this point we have two time values t0 and t1
		// between which the swept sphere intersects with the
		// triangle plane. If any collision is to occur it must
		// happen within this interval.
		VECTOR collisionPoint;
		bool foundCollison = false;
		float t = 1.0;

		// First we check for the easy case - collision inside
		// the triangle. If this happens it must be at time t0
		// as this is when the sphere rests on the front side
		// of the triangle plane. Note, this can only happen if
		// the sphere is not embedded in the triangle plane.		
		if (!embeddedInPlane) 
		{
			VECTOR planeIntersectionPoint =	(colPackage->basePoint-trianglePlane.normal) + colPackage->velocity*t0;
			if (checkPointInTriangle(planeIntersectionPoint,p1,p2,p3))
			{
				foundCollison = true;
				t = t0;
				collisionPoint = planeIntersectionPoint;
			}
		}

		// if we haven't found a collision already we'll have to
		// sweep sphere against points and edges of the triangle.
		// Note: A collision inside the triangle (the check above)
		// will always happen before a vertex or edge collision!
		// This is why we can skip the swept test if the above
		// gives a collision!
		if (foundCollison == false) 
		{
			// some commonly used terms:
			VECTOR velocity = colPackage->velocity;
			VECTOR base = colPackage->basePoint;
			float velocitySquaredLength = velocity.squaredLength();
			float a,b,c; // Params for equation
			float newT;
		
			// For each vertex or edge a quadratic equation have to
			// be solved. We parameterize this equation as
			// a*t^2 + b*t + c = 0 and below we calculate the
			// parameters a,b and c for each test.
			// Check against points:
			a = velocitySquaredLength;
			
			// P1
			b = 2.0*(velocity.dot(base-p1));
			c = (p1-base).squaredLength() - 1.0;
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				t = newT;
				foundCollison = true;
				collisionPoint = p1;
			}
			
			// P2
			b = 2.0*(velocity.dot(base-p2));
			c = (p2-base).squaredLength() - 1.0;
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				t = newT;
				foundCollison = true;
				collisionPoint = p2;
			}
			
			// P3
			b = 2.0*(velocity.dot(base-p3));
			c = (p3-base).squaredLength() - 1.0;
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				t = newT;
				foundCollison = true;
				collisionPoint = p3;
			}
			
			// Check agains edges:
			// p1 -> p2:
			VECTOR edge = p2-p1;
			VECTOR baseToVertex = p1 - base;
			float edgeSquaredLength = edge.squaredLength();
			float edgeDotVelocity = edge.dot(velocity);
			float edgeDotBaseToVertex = edge.dot(baseToVertex);
			
			// Calculate parameters for equation
			a = edgeSquaredLength*-velocitySquaredLength +	edgeDotVelocity*edgeDotVelocity;
			b = edgeSquaredLength*(2*velocity.dot(baseToVertex)) - 2.0*edgeDotVelocity*edgeDotBaseToVertex;
			c = edgeSquaredLength*(1-baseToVertex.squaredLength()) + edgeDotBaseToVertex*edgeDotBaseToVertex;

			// Does the swept sphere collide against infinite edge?
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				// Check if intersection is within line segment:
				float f=(edgeDotVelocity*newT-edgeDotBaseToVertex) / edgeSquaredLength;

				if (f >= 0.0 && f <= 1.0) 
				{
					// intersection took place within segment.
					t = newT;
					foundCollison = true;
					collisionPoint = p1 + edge*f;
				}
			}

			// p2 -> p3:
			edge = p3-p2;
			baseToVertex = p2 - base;
			edgeSquaredLength = edge.squaredLength();
			edgeDotVelocity = edge.dot(velocity);
			edgeDotBaseToVertex = edge.dot(baseToVertex);
			a = edgeSquaredLength*-velocitySquaredLength + edgeDotVelocity*edgeDotVelocity;
			b = edgeSquaredLength*(2*velocity.dot(baseToVertex)) - 2.0*edgeDotVelocity*edgeDotBaseToVertex;
			c = edgeSquaredLength*(1-baseToVertex.squaredLength()) + edgeDotBaseToVertex*edgeDotBaseToVertex;
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				float f=(edgeDotVelocity*newT-edgeDotBaseToVertex) / edgeSquaredLength;
				
				if (f >= 0.0 && f <= 1.0) 
				{
					t = newT;
					foundCollison = true;
					collisionPoint = p2 + edge*f;
				}
			}

			// p3 -> p1:
			edge = p1-p3;
			baseToVertex = p3 - base;
			edgeSquaredLength = edge.squaredLength();
			edgeDotVelocity = edge.dot(velocity);
			edgeDotBaseToVertex = edge.dot(baseToVertex);
			a = edgeSquaredLength*-velocitySquaredLength + edgeDotVelocity*edgeDotVelocity;
			b = edgeSquaredLength*(2*velocity.dot(baseToVertex)) - 2.0*edgeDotVelocity*edgeDotBaseToVertex;
			c = edgeSquaredLength*(1-baseToVertex.squaredLength()) + edgeDotBaseToVertex*edgeDotBaseToVertex;
			if (getLowestRoot(a,b,c, t, &newT)) 
			{
				float f=(edgeDotVelocity*newT-edgeDotBaseToVertex) / edgeSquaredLength;
				
				if (f >= 0.0 && f <= 1.0) 
				{
					t = newT;
					foundCollison = true;
					collisionPoint = p3 + edge*f;
				}
			}
		}

		// Set result:
		if (foundCollison == true) 
		{
			// distance to collision: 't' is time of collision
			float distToCollision = t*colPackage->velocity.length();

			// Does this triangle qualify for the closest hit?
			if (distToCollision < colPackage->nearestDistance) 
			{
				// Collision information nessesary for sliding
				colPackage->nearestDistance = distToCollision;
				colPackage->intersectionPoint=collisionPoint;
				colPackage->foundCollision = true;

				// trigger collection of triangle index when leave
				colPackage->triangleindex = -2;
			}
		}
	} // if not backface
	#endif
}
예제 #4
0
double PLANE::signedDistanceTo(VECTOR point) 
{
	return (point.dot(normal)) + equation[3];
}