//------------------------------------------------------------------------------- // @ ::BarycentricCoordinates() //------------------------------------------------------------------------------- // Returns barycentric coordinates for point inside triangle (3D version) // Assumes triangle is not degenerate //------------------------------------------------------------------------------- void BarycentricCoordinates( float &r, float &s, float& t, const IvVector3& point, const IvVector3& P0, const IvVector3& P1, const IvVector3& P2 ) { // get difference vectors IvVector3 u = P1 - P0; IvVector3 v = P2 - P0; IvVector3 w = point - P0; // compute cross product to get area of parallelograms IvVector3 a = u.Cross(w); IvVector3 b = v.Cross(w); IvVector3 c = u.Cross(v); // compute barycentric coordinates as ratios of areas float denom = 1.0f/c.Length(); s = b.Length()*denom; t = a.Length()*denom; r = 1.0f - s - t; }
//------------------------------------------------------------------------------- // @ ::TriangleIntersect() //------------------------------------------------------------------------------- // Returns true if ray intersects triangle //------------------------------------------------------------------------------- bool TriangleIntersect( float& t, const IvVector3& P0, const IvVector3& P1, const IvVector3& P2, const IvRay3& ray ) { // test ray direction against triangle IvVector3 e1 = P1 - P0; IvVector3 e2 = P2 - P0; IvVector3 p = ray.GetDirection().Cross(e2); float a = e1.Dot(p); // if result zero, no intersection or infinite intersections // (ray parallel to triangle plane) if ( IvIsZero(a) ) return false; // compute denominator float f = 1.0f/a; // compute barycentric coordinates IvVector3 s = ray.GetOrigin() - P0; float u = f*s.Dot(p); // ray falls outside triangle if (u < 0.0f || u > 1.0f) return false; IvVector3 q = s.Cross(e1); float v = f*ray.GetDirection().Dot(q); // ray falls outside triangle if (v < 0.0f || u+v > 1.0f) return false; // compute line parameter t = f*e2.Dot(q); return (t >= 0.0f); }
//------------------------------------------------------------------------------- // @ IvQuat::Set() //------------------------------------------------------------------------------- // Set quaternion based on start and end vectors //------------------------------------------------------------------------------- void IvQuat::Set( const IvVector3& from, const IvVector3& to ) { // Ensure that our vectors are unit ASSERT( from.IsUnit() && to.IsUnit() ); // get axis of rotation IvVector3 axis = from.Cross( to ); // get cos of angle between vectors float costheta = from.Dot( to ); // if vectors are 180 degrees apart if ( costheta <= -1.0f ) { // find orthogonal vector IvVector3 orthoVector; orthoVector.Normalize(); w = 0.0f; x = orthoVector.x; y = orthoVector.y; z = orthoVector.z; return; } // use trig identities to get the values we want float factor = IvSqrt( 2.0f*(1.0f + costheta) ); float scaleFactor = 1.0f/factor; // set values w = 0.5f*factor; x = scaleFactor*axis.x; y = scaleFactor*axis.y; z = scaleFactor*axis.z; } // End of IvQuat::Set()
//------------------------------------------------------------------------------- // @ Player::Update() //------------------------------------------------------------------------------- // Main update loop //------------------------------------------------------------------------------- void Player::Update( float dt ) { // update based on input if (IvGame::mGame->mEventHandler->IsKeyPressed(' ')) { if (mRun) { mTime = 0.0f; mRun = false; } else { mRun = true; } } if (IvGame::mGame->mEventHandler->IsKeyPressed('m')) { mMode = (mMode + 1)%4; } if (mRun) { mTime += dt; // stop just before end so we don't end up with zero vector // when we look ahead if ( mTime > 11.5f ) mTime = 11.5f; } // now we set up the camera // get eye position IvVector3 eye = mCurve.Evaluate( mTime ); IvVector3 viewDir; IvVector3 viewSide; IvVector3 viewUp; // set parameters depending on what mode we're in // Frenet frame if ( mMode == 3 ) { IvVector3 T = mCurve.Velocity( mTime ); IvVector3 a = mCurve.Acceleration( mTime ); IvVector3 B = T.Cross( a ); B.Normalize(); T.Normalize(); IvVector3 N = B.Cross( T ); viewDir = T; viewSide = -N; // have to negate to get from RH frame to LH frame viewUp = B; } else { IvVector3 lookAt; // look same direction all the time if ( mMode == 2 ) { viewDir = IvVector3::xAxis; } // look along tangent else if ( mMode == 1 ) { viewDir = mCurve.Velocity( mTime ); } // look ahead .5 in parameter else if ( mMode == 0 ) { viewDir = mCurve.Evaluate( mTime+0.5f ) - eye; } // compute view vectors viewDir.Normalize(); viewUp = IvVector3::zAxis - IvVector3::zAxis.Dot(viewDir)*viewDir; viewUp.Normalize(); viewSide = viewDir.Cross(viewUp); } // now set up matrices // build transposed rotation matrix IvMatrix33 rotate; if ( IvRenderer::mRenderer->GetAPI() == kOpenGL ) { rotate.SetRows( viewSide, viewUp, -viewDir ); } else { rotate.SetRows( viewSide, viewUp, viewDir ); } // transform translation IvVector3 eyeInv = -(rotate*eye); // build 4x4 matrix IvMatrix44 matrix(rotate); matrix(0,3) = eyeInv.x; matrix(1,3) = eyeInv.y; matrix(2,3) = eyeInv.z; ::IvSetViewMatrix( matrix ); } // End of Player::Update()