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; } } } }