//---------------------------------------------------------------------------- HPlane::HPlane (const AVector& normal, const APoint& p) { mTuple[0] = normal[0]; mTuple[1] = normal[1]; mTuple[2] = normal[2]; mTuple[3] = -p.Dot(normal); }
//---------------------------------------------------------------------------- void HMatrix::MakeReflection (const APoint& origin, const AVector& normal) { // +- -+ // M = | I-2*N*N^T 2*Dot(N,P)*N | // | 0^T 1 | // +- -+ // // where P is a point on the plane and N is a unit-length plane normal. float twoDotNO = 2.0f*origin.Dot(normal); mEntry[ 0] = 1.0f - 2.0f*normal[0]*normal[0]; mEntry[ 1] = -2.0f*normal[0]*normal[1]; mEntry[ 2] = -2.0f*normal[0]*normal[2]; mEntry[ 3] = twoDotNO*normal[0]; mEntry[ 4] = -2.0f*normal[1]*normal[0]; mEntry[ 5] = 1.0f - 2.0f*normal[1]*normal[1]; mEntry[ 6] = -2.0f*normal[1]*normal[2]; mEntry[ 7] = twoDotNO*normal[1]; mEntry[ 8] = -2.0f*normal[2]*normal[0]; mEntry[ 9] = -2.0f*normal[2]*normal[1]; mEntry[10] = 1.0f - 2.0f*normal[2]*normal[2]; mEntry[11] = twoDotNO*normal[2]; mEntry[12] = 0.0f; mEntry[13] = 0.0f; mEntry[14] = 0.0f; mEntry[15] = 1.0f; }
//---------------------------------------------------------------------------- void HMatrix::MakePerspectiveProjection (const APoint& origin, const AVector& normal, const APoint& eye) { // +- -+ // M = | Dot(N,E-P)*I - E*N^T -(Dot(N,E-P)*I - E*N^T)*E | // | -N^t Dot(N,E) | // +- -+ // // where E is the eye point, P is a point on the plane, and N is a // unit-length plane normal. float dotND = normal.Dot(eye - origin); mEntry[ 0] = dotND - eye[0]*normal[0]; mEntry[ 1] = -eye[0]*normal[1]; mEntry[ 2] = -eye[0]*normal[2]; mEntry[ 3] = -(mEntry[0]*eye[0] + mEntry[1]*eye[1] + mEntry[2]*eye[2]); mEntry[ 4] = -eye[1]*normal[0]; mEntry[ 5] = dotND - eye[1]*normal[1]; mEntry[ 6] = -eye[1]*normal[2]; mEntry[ 7] = -(mEntry[4]*eye[0] + mEntry[5]*eye[1] + mEntry[6]*eye[2]); mEntry[ 8] = -eye[2]*normal[0]; mEntry[ 9] = -eye[2]*normal[1]; mEntry[10] = dotND- eye[2]*normal[2]; mEntry[11] = -(mEntry[8]*eye[0] + mEntry[9]*eye[1] + mEntry[10]*eye[2]); mEntry[12] = -normal[0]; mEntry[13] = -normal[1]; mEntry[14] = -normal[2]; mEntry[15] = eye.Dot(normal); }
//---------------------------------------------------------------------------- HPlane::HPlane (const APoint& p0, const APoint& p1, const APoint& p2) { AVector edge1 = p1 - p0; AVector edge2 = p2 - p0; AVector normal = edge1.UnitCross(edge2); mTuple[0] = normal[0]; mTuple[1] = normal[1]; mTuple[2] = normal[2]; mTuple[3] = -p0.Dot(normal); }
//---------------------------------------------------------------------------- void HMatrix::MakeObliqueProjection (const APoint& origin, const AVector& normal, const AVector& direction) { // The projection plane is Dot(N,X-P) = 0 where N is a 3-by-1 unit-length // normal vector and P is a 3-by-1 point on the plane. The projection // is oblique to the plane, in the direction of the 3-by-1 vector D. // Necessarily Dot(N,D) is not zero for this projection to make sense. // Given a 3-by-1 point U, compute the intersection of the line U+t*D // with the plane to obtain t = -Dot(N,U-P)/Dot(N,D). Then // // projection(U) = P + [I - D*N^T/Dot(N,D)]*(U-P) // // A 4-by-4 homogeneous transformation representing the projection is // // +- -+ // M = | D*N^T - Dot(N,D)*I -Dot(N,P)D | // | 0^T -Dot(N,D) | // +- -+ // // where M applies to [U^T 1]^T by M*[U^T 1]^T. The matrix is chosen so // that M[3][3] > 0 whenever Dot(N,D) < 0 (projection is onto the // "positive side" of the plane). float dotND = normal.Dot(direction); float dotNO = origin.Dot(normal); mEntry[ 0] = direction[0]*normal[0] - dotND; mEntry[ 1] = direction[0]*normal[1]; mEntry[ 2] = direction[0]*normal[2]; mEntry[ 3] = -dotNO*direction[0]; mEntry[ 4] = direction[1]*normal[0]; mEntry[ 5] = direction[1]*normal[1] - dotND; mEntry[ 6] = direction[1]*normal[2]; mEntry[ 7] = -dotNO*direction[1]; mEntry[ 8] = direction[2]*normal[0]; mEntry[ 9] = direction[2]*normal[1]; mEntry[10] = direction[2]*normal[2] - dotND; mEntry[11] = -dotNO*direction[2]; mEntry[12] = 0.0f; mEntry[13] = 0.0f; mEntry[14] = 0.0f; mEntry[15] = -dotND; }
//---------------------------------------------------------------------------- void Culler::SetFrustum (const float* frustum) { if (!mCamera) { assertion(false, "SetFrustum requires the existence of a camera\n"); return; } // Copy the frustum values. mFrustum[Camera::VF_DMIN] = frustum[Camera::VF_DMIN]; mFrustum[Camera::VF_DMAX] = frustum[Camera::VF_DMAX]; mFrustum[Camera::VF_UMIN] = frustum[Camera::VF_UMIN]; mFrustum[Camera::VF_UMAX] = frustum[Camera::VF_UMAX]; mFrustum[Camera::VF_RMIN] = frustum[Camera::VF_RMIN]; mFrustum[Camera::VF_RMAX] = frustum[Camera::VF_RMAX]; float dMin2 = mFrustum[Camera::VF_DMIN]*mFrustum[Camera::VF_DMIN]; float uMin2 = mFrustum[Camera::VF_UMIN]*mFrustum[Camera::VF_UMIN]; float uMax2 = mFrustum[Camera::VF_UMAX]*mFrustum[Camera::VF_UMAX]; float rMin2 = mFrustum[Camera::VF_RMIN]*mFrustum[Camera::VF_RMIN]; float rMax2 = mFrustum[Camera::VF_RMAX]*mFrustum[Camera::VF_RMAX]; // Get the camera coordinate frame. APoint position = mCamera->GetPosition(); AVector dVector = mCamera->GetDVector(); AVector uVector = mCamera->GetUVector(); AVector rVector = mCamera->GetRVector(); float dirDotEye = position.Dot(dVector); // Update the near plane. mPlane[Camera::VF_DMIN].SetNormal(dVector); mPlane[Camera::VF_DMIN].SetConstant( dirDotEye + mFrustum[Camera::VF_DMIN]); // Update the far plane. mPlane[Camera::VF_DMAX].SetNormal(-dVector); mPlane[Camera::VF_DMAX].SetConstant( -(dirDotEye + mFrustum[Camera::VF_DMAX])); // Update the bottom plane float invLength = Mathf::InvSqrt(dMin2 + uMin2); float c0 = -mFrustum[Camera::VF_UMIN]*invLength; // D component float c1 = +mFrustum[Camera::VF_DMIN]*invLength; // U component AVector normal = c0*dVector + c1*uVector; float constant = position.Dot(normal); mPlane[Camera::VF_UMIN].SetNormal(normal); mPlane[Camera::VF_UMIN].SetConstant(constant); // Update the top plane. invLength = Mathf::InvSqrt(dMin2 + uMax2); c0 = +mFrustum[Camera::VF_UMAX]*invLength; // D component c1 = -mFrustum[Camera::VF_DMIN]*invLength; // U component normal = c0*dVector + c1*uVector; constant = position.Dot(normal); mPlane[Camera::VF_UMAX].SetNormal(normal); mPlane[Camera::VF_UMAX].SetConstant(constant); // Update the left plane. invLength = Mathf::InvSqrt(dMin2 + rMin2); c0 = -mFrustum[Camera::VF_RMIN]*invLength; // D component c1 = +mFrustum[Camera::VF_DMIN]*invLength; // R component normal = c0*dVector + c1*rVector; constant = position.Dot(normal); mPlane[Camera::VF_RMIN].SetNormal(normal); mPlane[Camera::VF_RMIN].SetConstant(constant); // Update the right plane. invLength = Mathf::InvSqrt(dMin2 + rMax2); c0 = +mFrustum[Camera::VF_RMAX]*invLength; // D component c1 = -mFrustum[Camera::VF_DMIN]*invLength; // R component normal = c0*dVector + c1*rVector; constant = position.Dot(normal); mPlane[Camera::VF_RMAX].SetNormal(normal); mPlane[Camera::VF_RMAX].SetConstant(constant); // All planes are active initially. mPlaneState = 0xFFFFFFFF; }