Ejemplo n.º 1
0
bool CEntitySAInterface::IsOnScreen( void ) const
{
    // Bugfix: no col -> not visible
    if ( GetColModel() )
    {
        CVector pos;

        GetCollisionOffset( pos );

        CCameraSAInterface& camera = Camera::GetInterface();

        // MTA fix: get the real entity radius.
        float entityRadius = GetRadius();

        bool isVisible = camera.IsSphereVisible( pos, entityRadius, camera.m_matInverse );

        if ( isVisible )
        {
            return true;
        }

        // Are mirrors enabled?
        if ( *(unsigned char*)0x00B6F998 )
        {
            // Check if we are visible on the mirror.
            isVisible = camera.IsSphereVisible( pos, entityRadius, camera.m_matMirrorInverse );
            
            if ( isVisible )
            {
                return true;
            }
        }
    }

    return false;
}
void CCamera::CheckCameraCollision(CVector3 *pVertices, int numOfVerts)
{	
	// This function is pretty much a direct rip off of SpherePolygonCollision()
	// We needed to tweak it a bit though, to handle the collision detection once 
	// it was found, along with checking every triangle in the list if we collided.  
	// pVertices is the world data. If we have space partitioning, we would pass in 
	// the vertices that were closest to the camera. What happens in this function 
	// is that we go through every triangle in the list and check if the camera's 
	// sphere collided with it.  If it did, we don't stop there.  We can have 
	// multiple collisions so it's important to check them all.  One a collision 
	// is found, we calculate the offset to move the sphere off of the collided plane.

	// Go through all the triangles
	for(int i = 0; i < numOfVerts; i += 3)
	{
		// Store of the current triangle we testing
		CVector3 vTriangle[3] = { pVertices[i], pVertices[i+1], pVertices[i+2] };

		// 1) STEP ONE - Finding the sphere's classification
	
		// We want the normal to the current polygon being checked
		CVector3 vNormal = Normal(vTriangle);

		// This will store the distance our sphere is from the plane
		float distance = 0.0f;

		// This is where we determine if the sphere is in FRONT, BEHIND, or INTERSECTS the plane
		int classification = ClassifySphere(m_vPosition, vNormal, vTriangle[0], m_radius, distance);

		// If the sphere intersects the polygon's plane, then we need to check further
		if(classification == INTERSECTS) 
		{
			// 2) STEP TWO - Finding the psuedo intersection point on the plane

			// Now we want to project the sphere's center onto the triangle's plane
			CVector3 vOffset = vNormal * distance;

			// Once we have the offset to the plane, we just subtract it from the center
			// of the sphere.  "vIntersection" is now a point that lies on the plane of the triangle.
			CVector3 vIntersection = m_vPosition - vOffset;

			// 3) STEP THREE - Check if the intersection point is inside the triangles perimeter

			// We first check if our intersection point is inside the triangle, if not,
			// the algorithm goes to step 4 where we check the sphere again the polygon's edges.

			// We do one thing different in the parameters for EdgeSphereCollision though.
			// Since we have a bulky sphere for our camera, it makes it so that we have to 
			// go an extra distance to pass around a corner. This is because the edges of 
			// the polygons are colliding with our peripheral view (the sides of the sphere).  
			// So it looks likes we should be able to go forward, but we are stuck and considered 
			// to be colliding.  To fix this, we just pass in the radius / 2.  Remember, this
			// is only for the check of the polygon's edges.  It just makes it look a bit more
			// realistic when colliding around corners.  Ideally, if we were using bounding box 
			// collision, cylinder or ellipses, this wouldn't really be a problem.

			if(InsidePolygon(vIntersection, vTriangle, 3) ||
			   EdgeSphereCollision(m_vPosition, vTriangle, 3, m_radius / 2))
			{
				// If we get here, we have collided!  To handle the collision detection
				// all it takes is to find how far we need to push the sphere back.
				// GetCollisionOffset() returns us that offset according to the normal,
				// radius, and current distance the center of the sphere is from the plane.
				vOffset = GetCollisionOffset(vNormal, m_radius, distance);

				// Now that we have the offset, we want to ADD it to the position and
				// view vector in our camera.  This pushes us back off of the plane.  We
				// don't see this happening because we check collision before we render
				// the scene.
				m_vPosition = m_vPosition + vOffset;
				m_vView = m_vView + vOffset;
			}
		}
	}
}