void CRigidBody::HandleSphereToSphereCollision(CCollisionMessage* ColMsg) { CVehicle* Car = (CVehicle*)ColMsg->GetEntity(); Vector3f CenterToCenter = *ColMsg->GetCenterToCenter(); // set translate m_vReflection = CenterToCenter*0.05f; m_vPosition = m_translate; m_vDirectionWhenDisturbed = m_vReflection; // set rotation if (CenterToCenter.Length() == 0.0f) CenterToCenter = Vector3f(1.0f, 0.0f, 0.0f); float theta1 = (CenterToCenter.Dot(Car->GetVehicleHeadingWC()))/(CenterToCenter.Length()*Car->GetVehicleHeadingWC().Length()); Vector3f CP = CenterToCenter.Cross(Vector3f(0.0f, 1.0f, 0.0f)); float theta2 = (CP.Dot(Car->GetVehicleHeadingWC()))/(CP.Length()*Car->GetVehicleHeadingWC().Length()); // CLog::GetLog().Write(LOG_DEBUGOVERLAY, 120, "theta1 = %f", theta1); // CLog::GetLog().Write(LOG_DEBUGOVERLAY, 121, "theta2 = %f", theta2); float spin; if (0.0f < theta1 && theta1 < 1.0f) { // LOWER-LEFT QUADRANT if (0.0f < theta2 && theta2 < 1.0f) { spin = theta2; } // LOWER-RIGHT QUADRANT else { spin = theta2; } } else { // UPPER-LEFT QUADRANT if (0.0f < theta2 && theta2 < 1.0f) { spin = -theta2; } // UPPER-RIGHT QUADRANT else { spin = -theta2; } } spin *= RIGIDBODY_SPIN_FACTOR; m_vRotation = Vector3f(0.0f, spin, 0.0f); // actually set it! Car->SetVehicleVelocityLC(0.0f); Car->SetVehiclePositionLC(Vector3f(m_vPosition.X(), m_vPosition.Z(), m_vPosition.Y())); disturbed = true; }
void CRigidBody::DeliverCollisionMessage(CCollisionMessage* ColMsg) { if (!ColMsg) return; if (ColMsg->GetCollisionType() == SPHERE_TO_SPHERE) { HandleSphereToSphereCollision(ColMsg); return; } /****** Deploy to HandlePushCollision() if this is the case ******/ // Push collision not working. Commenting this out for now. /* if (ColMsg->GetCollisionType() == PUSHED) { HandlePushCollision(ColMsg); return; } */ CVehicle* Car = (CVehicle*)ColMsg->GetEntity(); /************** set reflection motion ************/ m_vPosition = m_translate + (*ColMsg->GetReverse())*RIGIDBODY_SPACING_FACTOR; Vector3f velocityWC; if (disturbed) { velocityWC = m_vDirectionWhenDisturbed*80.0f; } else { velocityWC = Car->GetVehicleVelocityWC(); // if reversing, velocityWC will point in opposite direction as actual velocity if (Car->GetVehicleVelocityLC().X() < 0.0f) velocityWC *= -1.0f; } m_vReflection = velocityWC - 2.0f*(velocityWC.Dot(*ColMsg->GetNormal()))*(*ColMsg->GetNormal()); m_vReflection *= RIGIDBODY_REFLECTION_FACTOR; m_vDirectionWhenDisturbed = m_vReflection; Car->SetVehicleVelocityLC(0.0f); Car->SetVehiclePositionLC(Vector3f(m_vPosition.X(), m_vPosition.Z(), m_vPosition.Y())); /*************** set angular velocity ******************/ // Compute angle between vehicle heading and plane Vector3f PlaneEdge = ColMsg->GetPlane()->Edge0(); Vector3f CarHeading = Car->GetVehicleHeadingWC(); float angle = acos(CarHeading.Dot(PlaneEdge)/(PlaneEdge.Length()*CarHeading.Length())); // spin CW or CCW? float spin; // magnitude of spin about the y-axis if (angle > Math<float>::PI/2.0f) { // CCW spin = Math<float>::PI - angle; } else { // CW spin = -angle; } spin *= RIGIDBODY_SPIN_FACTOR; m_vRotation = Vector3f(0.0f, spin, 0.0f); /*************** set vectors that are actually used in renderer ************/ /*********************** to the values computed above **********************/ m_translate = m_vPosition; m_box.Center() = m_vPosition; m_sphere.Center() = m_vPosition; Car->GetRotationLC().Z() += spin; disturbed = true; /* CLog::GetLog().Write(LOG_MISC, "\n\n\nreflection = (%f, %f, %f)", m_vReflection.X(), m_vReflection.Y(), m_vReflection.Z()); CLog::GetLog().Write(LOG_MISC, "direction = (%f, %f, %f)\n\n", m_vDirectionWhenDisturbed.X(), m_vDirectionWhenDisturbed.Y(), m_vDirectionWhenDisturbed.Z()); */ }