bool DDynamicActor::Collision_IntersectCheck( int ) { DLogWriteSystem(" Collision_IntersectCheck : %p", this ); SVector Location = m_Locus.Location; SVector Start = Physics::g_vStart; if( m_dwColFlag & CF_COLLIDEDBY_ROOT_INTERNAL ) { Location = GMath.ZeroVector; SMatrix Matrix = (this->m_matRootMatrixForCollision * m_Locus.LocalToWorld).Inverse(); Start = Matrix.TransformVector( Physics::g_vStart ); } SVector vExtent = Physics::g_vExtent + this->m_vExtent; SVector Delta = Start - Location; if( Abs(Delta.Y) >= vExtent.Y ) return false; float DeltaSquared2D = Delta.SizeSquared2D(); float RadiusSquared = Square(vExtent.X); if( DeltaSquared2D >= RadiusSquared ) return false; float Overlap = appSqrt( RadiusSquared ) - appSqrt( DeltaSquared2D ); if( Overlap <= Physics::g_SingleResult.m_fTime ) return false; Physics::g_SingleResult.m_nActorIndex = m_dwID; Physics::g_SingleResult.m_nMeshIndex = -1; Physics::g_SingleResult.m_fTime = Overlap; Delta.Y = 0.f; Physics::g_SingleResult.m_vNormal = Delta.SafeNormal(); Physics::g_SingleResult.m_vContactPoint= m_Locus.Location + this->m_vExtent.X * Physics::g_SingleResult.m_vNormal; Physics::g_SingleResult.m_ActorType = this->m_ActorType; return true; }
bool DDynamicActor::Collision_IncludeCheck( int ) { DLogWriteSystem(" Collision_IncludeCheck : %p", this ); SVector Location = m_Locus.Location; SVector Start = Physics::g_vStart; if( m_dwColFlag & CF_COLLIDEDBY_ROOT_INTERNAL ) { Location = GMath.ZeroVector; SMatrix Matrix = (this->m_matRootMatrixForCollision * m_Locus.LocalToWorld).Inverse(); Start = Matrix.TransformVector( Physics::g_vStart ); } // quick rejecct SVector MaxLocation = Location + m_vExtent; SVector MinLocation = Location - m_vExtent; if( Start.X > MaxLocation.X ) return false; if( Start.X < MinLocation.X ) return false; if( Start.Y > MaxLocation.Y ) return false; if( Start.Y < MinLocation.Y ) return false; if( Start.Z > MaxLocation.Z ) return false; if( Start.Z < MinLocation.Z ) return false; // check circle float RadiusSq = ( Start.X - Location.X ) * ( Start.X - Location.X ) + ( Start.Z - Location.Z ) * ( Start.Z - Location.Z ); if( RadiusSq > m_vExtent.X * m_vExtent.X ) return false; // return SColResult *Result = new(Physics::g_aMultiResult) SColResult; Result->m_nActorIndex = m_dwID; Result->m_nMeshIndex = -1; Result->m_ActorType = this->m_ActorType; return true; }
void CMoon::GetRisingTransformaion( SMatrix& matResult_ ) { // Rising Rate +Y (the zenith) // (0.25) // . | . // . | . // . | . // (0.5) | . // . | . (0) = (1) // ---------------------+----------------------- +X (east) // Transform Moon (Apply Rising Rate to Translated Moon) SMatrix matMoonRot; matMoonRot.SetRotation( SRotator( 0, 0, Rad2Angle(m_fRisingRate*fPi*2.0f - fPi/2.0f )) ); SMatrix matMoonPitch; matMoonPitch.SetRotation( SRotator( Rad2Angle(m_fPitch), 0, 0 ) ); matMoonRot = matMoonRot * matMoonPitch; SVector vMoonPos = matMoonRot.TransformVector( m_vTranslation ); matResult_.SetTranslation( vMoonPos ); Transform( matResult_ ); }
bool DDynamicActor::Collision_LineCheck( int ) { DLogWriteSystem(" Collision_LineCheck : %p", this ); SVector Location = m_Locus.Location; SVector StartTest = Physics::g_vStartTest; SVector End = Physics::g_vEnd; if( m_dwColFlag & CF_COLLIDEDBY_ROOT_INTERNAL ) { Location = GMath.ZeroVector; SMatrix Matrix = (this->m_matRootMatrixForCollision * m_Locus.LocalToWorld).Inverse(); StartTest = Matrix.TransformVector( StartTest ); End = Matrix.TransformVector( End ); } // quick rejecct SVector vExtent = Physics::g_vExtent + this->m_vExtent; SVector MaxLocation = Location + vExtent; SVector MinLocation = Location - vExtent; if( StartTest.X > MaxLocation.X && End.X > MaxLocation.X ) return false; if( StartTest.X < MinLocation.X && End.X < MinLocation.X ) return false; if( StartTest.Y > MaxLocation.Y && End.Y > MaxLocation.Y ) return false; if( StartTest.Y < MinLocation.Y && End.Y < MinLocation.Y ) return false; if( StartTest.Z > MaxLocation.Z && End.Z > MaxLocation.Z ) return false; if( StartTest.Z < MinLocation.Z && End.Z < MinLocation.Z ) return false; // top of cylinder Physics::g_fT0 = 0.f; Physics::g_fT1 = Physics::g_SingleResult.m_fTime; SVector Normal = GMath.YAxis; // DEBUG!! if( StartTest.Y > MaxLocation.Y && End.Y < MaxLocation.Y ) { float T = ( MaxLocation.Y - StartTest.Y ) / ( End.Y - StartTest.Y ); if( T > Physics::g_fT0 ) { Physics::g_fT0 = ::Max( Physics::g_fT0 , T ); Normal = GMath.YAxis; } } else if( StartTest.Y < MaxLocation.Y && End.Y > MaxLocation.Y ) Physics::g_fT1 = ::Min( Physics::g_fT1, ( MaxLocation.Y - StartTest.Y ) / ( End.Y - StartTest.Y ) ); // bottom of cylinder if( StartTest.Y < MinLocation.Y && End.Y > MinLocation.Y ) { float T = ( MinLocation.Y - StartTest.Y ) / ( End.Y - StartTest.Y ); if( T > Physics::g_fT0 ) { Physics::g_fT0 = ::Max( Physics::g_fT0, T ); Normal = -GMath.YAxis; } } else if( StartTest.Y > MinLocation.Y && End.Y < MinLocation.Y ) Physics::g_fT1 = ::Min( Physics::g_fT1, ( MinLocation.Y - StartTest.Y ) / ( End.Y - StartTest.Y ) ); if( Physics::g_fT0 >= Physics::g_fT1 ) return false; // Test float A, B, C; { float DX = End.X - StartTest.X; float DZ = End.Z - StartTest.Z; float TX = StartTest.X - Location.X; float TZ = StartTest.Z - Location.Z; A = DX*DX + DZ*DZ; B = 2.f * (TX*DX + TZ*DZ); C = TX*TX + TZ*TZ - vExtent.X*vExtent.X; } if( C < DYNAMIC_DIST_ERROR && StartTest.Y > MinLocation.Y && StartTest.Y < MaxLocation.Y ) { A = StartTest.X - Location.X; B = StartTest.Z - Location.Z; if( A * (End.X-StartTest.X) + B * (End.Z-StartTest.Z) < -0.1f ) { SColResult *Result = ( Physics::g_bMultiCheck ? new(Physics::g_aMultiResult) SColResult : &Physics::g_SingleResult ); Result->m_nActorIndex = m_dwID; Result->m_nMeshIndex = -1; Result->m_fTime = 0.f; Result->m_vNormal = SVector(A,0,B).SafeNormal(); Result->m_vLocation= Physics::g_vStart; Result->m_vContactPoint = Location + this->m_vExtent.X * Result->m_vNormal; return true; } else return false; } float D = B*B - 4.f*A*C; if( D < 0.f ) return false; if( A < DYNAMIC_DIST_ERROR*DYNAMIC_DIST_ERROR ) { if( C > 0.f ) return false; } else { A = 0.5f / A; D = appSqrt(D); Physics::g_fT1 = ::Min( Physics::g_fT1, (D-B) * A ); float T = -(D+B) * A; if( ::Max(T,Physics::g_fT0) >= Physics::g_fT1 ) return false; if( T > Physics::g_fT0 ) { Physics::g_fT0 = T; Normal.X = StartTest.X + (End.X-StartTest.X)*Physics::g_fT0 - Location.X; Normal.Y = 0; Normal.Z = StartTest.Z + (End.Z-StartTest.Z)*Physics::g_fT0 - Location.Z; Normal.Normalize(); } } SColResult *Result = ( Physics::g_bMultiCheck ? new(Physics::g_aMultiResult) SColResult : &Physics::g_SingleResult ); Result->m_nActorIndex = m_dwID; Result->m_nMeshIndex = -1; Result->m_fTime = Physics::g_fT0; Result->m_vLocation = CalcInterpolatedValue( Result->m_fTime, Physics::g_vStart, Physics::g_vEnd ); Result->m_vNormal = Normal; Result->m_vContactPoint = Location + this->m_vExtent.X * Normal; Result->m_ActorType = this->m_ActorType; return true; }