csMatrix3 operator/ (const csMatrix3& m, float f) { float inv_f = 1 / f; return csMatrix3 (m.m11*inv_f, m.m12*inv_f, m.m13*inv_f, m.m21*inv_f, m.m22*inv_f, m.m23*inv_f, m.m31*inv_f, m.m32*inv_f, m.m33*inv_f); }
void csCameraBase::Correct (int n) { if (n == 0) return; csVector3 w1, w2, w3; float *vals[5]; w3 = m_t2o.Col3 (); vals[0] = &w3.x; vals[1] = &w3.y; vals[2] = &w3.z; vals[4] = 0; Correct (n, vals); /* perform the snap-to operation on the forward vector */ /* Maybe w3 should be normalized. Only necessary if there is significant roundoff error: */ // w3 = csVector3::unit(w3); /* perhaps a snap-to should be performed on one of the other vectors as well */ w1 = m_t2o.Col2 (); w2 = csVector3::Unit (w3 % w1); w1 = w2 % w3; SetT2O (csMatrix3 (w1.x, w2.x, w3.x, w1.y, w2.y, w3.y, w1.z, w2.z, w3.z)); }
void RagdollAnimNode::BlendState (csSkeletalState2* state, float baseWeight) { if (!isActive) return; //printf ("RagdollAnimNode::BlendState\n"); // TODO: use baseWeight for (csHash<Bone, BoneID>::GlobalIterator it = bones.GetIterator (); it.HasNext(); ) { Bone bone = it.Next (); csOrthoTransform bodyTransform = bone.rigidBody->GetTransform (); // TODO: test for deactivation of rigid body BoneID parentBoneID = skeleton->GetFactory ()->GetBoneParent (bone.boneID); // if this bone is the root of the skeleton // TODO: valid also for root of dynamic node? if (parentBoneID == InvalidBoneID) { csQuaternion boneRotation; csVector3 boneOffset; skeleton->GetFactory ()->GetTransformBoneSpace (bone.boneID, boneRotation, boneOffset); csOrthoTransform boneTransform (csMatrix3 (boneRotation), boneOffset); csOrthoTransform newTransform = boneTransform.GetInverse () * bodyTransform; iMovable* movable = sceneNode->GetMovable (); movable->SetTransform (newTransform); movable->UpdateMove (); continue; } // if this bone is inside the ragdoll chain if (bones.Contains (parentBoneID)) { Bone nullBone; csOrthoTransform parentTransform = bones.Get (parentBoneID, nullBone) .rigidBody->GetTransform (); csReversibleTransform relativeTransform = bodyTransform * parentTransform.GetInverse (); state->SetBoneUsed (bone.boneID); state->GetVector (bone.boneID) = relativeTransform.GetOrigin (); csQuaternion quaternion; quaternion.SetMatrix (relativeTransform.GetT2O ()); state->GetQuaternion (bone.boneID) = quaternion; continue; } // else this bone is the root of the ragdoll chain, but not of the skeleton else { // TODO: use kinematic object if not the root of the animesh } } }
void csReversibleTransform::RotateThis (const csVector3 &v, float angle) { csVector3 u = v; float ca, sa, omcaux, omcauy, omcauz, uxsa, uysa, uzsa; u = csVector3::Unit (u); ca = (float)cos (angle); sa = (float)sin (angle); omcaux = (1 - ca) * u.x; omcauy = (1 - ca) * u.y; omcauz = (1 - ca) * u.z; uxsa = u.x * sa; uysa = u.y * sa; uzsa = u.z * sa; SetT2O ( GetT2O () * csMatrix3 ( u.x * omcaux + ca, u.y * omcaux - uzsa, u.z * omcaux + uysa, u.x * omcauy + uzsa, u.y * omcauy + ca, u.z * omcauy - uxsa, u.x * omcauz - uysa, u.y * omcauz + uxsa, u.z * omcauz + ca)); }
void SelfShadowDemo::Frame () { csTicks elapsed_time = vc->GetElapsedTicks (); float speed = (elapsed_time / 1000.0) * (0.03 * 20); float rotateFactor = speed; // Translucent objects become dynamic by being rotated if (rotateGrass) { // Search for mesh named 'Hair' csRef<iMeshWrapper> objectfact = engine->FindMeshObject ("Hair"); if (objectfact) { objectfact->GetMovable()->SetTransform( objectfact->GetMovable()->GetTransform() * csMatrix3(cos(rotateFactor), 0, sin(rotateFactor), 0, 1, 0, -sin(rotateFactor), 0, cos(rotateFactor)) ); objectfact->GetMovable()->UpdateMove(); } } // Default behavior from DemoApplication DemoApplication::Frame (); }
//--------------------------------------------------------------------------- csTransform csTransform::GetReflect (const csPlane3 &pl) { // Suppose that n is the plane normal in the direction of th reflection. // Suppose that u is the unit vector in the direction of the reflection // normal. For any vector v, the component of v in the direction of // u is equal to (v * u) * u. Thus, if v is reflected across a plane // through the origin with the given normal, the resulting vector is // v' = v - 2 * [ (v * u) * u ] = v - 2 [ (v * n) * n ] / (n * n) // // x = <1,0,0> => x' = <1,0,0> - 2 ( n.x * n ) / (n*n) // y = <0,1,0> => y' = <0,1,0> - 2 ( n.y * n ) / (n*n) // z = <0,0,1> => z' = <0,0,1> - 2 ( n.z * n ) / (n*n) // // 3x3 transformation matrix = [x' y' z'] float i_normsq = 1 / (pl.norm * pl.norm); csVector3 xvec = (-2 * pl.norm.x * i_normsq) * pl.norm; csVector3 yvec = (-2 * pl.norm.y * i_normsq) * pl.norm; csVector3 zvec = (-2 * pl.norm.z * i_normsq) * pl.norm; xvec.x += 1; yvec.y += 1; zvec.z += 1; return csTransform ( csMatrix3 ( xvec.x, yvec.x, zvec.x, xvec.y, yvec.y, zvec.y, xvec.z, yvec.z, zvec.z), /* neworig = */(-2 * pl.DD * i_normsq) * pl.norm); }
void psLinearMovement::SetPosition (const csVector3& pos, float yrot, const iSector* sector) { if (!sector) { StackTrace("Setting position without sector"); } // Debug4(LOG_CELPERSIST,0,"DEBUG: psLinearMovement::SetPosition %s current transform: %s scale %f \n", mesh->QueryObject()->GetName(), mesh->GetMovable()->GetTransform().Description().GetData(),scale); // Position and Sector mesh->GetMovable ()->SetPosition ((iSector *)sector,pos); // at first loading scale may not be yet set if (scale>0) { // Rotation and scale csMatrix3 rotMatrix = (csMatrix3) csYRotMatrix3 (yrot); csMatrix3 scaleMatrix = csMatrix3 (1/scale,0,0, 0,1/scale,0, 0,0,1/scale); mesh->GetMovable ()->GetTransform ().SetO2T (scaleMatrix*rotMatrix); } else { // Rotation only csMatrix3 rotMatrix = (csMatrix3) csYRotMatrix3 (yrot); mesh->GetMovable ()->GetTransform ().SetO2T (rotMatrix); } mesh->GetMovable ()->UpdateMove (); }
void FrankieScene::ResetScene () { // Reset the position of the animesh csRef<iMeshObject> animeshObject = scfQueryInterface<iMeshObject> (animesh); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->SetTransform (csOrthoTransform (csMatrix3 (), csVector3 (0.0f))); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->UpdateMove (); if (hairTest->physicsEnabled) { // Set the ragdoll state of the 'body' and 'tail' chains as kinematic ragdollNode->SetBodyChainState (bodyChain, CS::Animation::STATE_KINEMATIC); ragdollNode->SetBodyChainState (tailChain, CS::Animation::STATE_KINEMATIC); ragdollNode->SetPlaybackPosition(0); // Update the display of the dynamics debugger if (hairTest->dynamicsDebugMode == DYNDEBUG_COLLIDER || hairTest->dynamicsDebugMode == DYNDEBUG_MIXED) hairTest->dynamicsDebugger->UpdateDisplay (); } // Reset morphing animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("smile.B"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("eyebrows_down.B"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("wings_in"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("eyelids_closed"), 0.0f); if (furMesh) furMesh->ResetMesh(); }
void KrystalScene::ResetScene () { if (hairTest->physicsEnabled) { // Reset the position of the animesh csRef<iMeshObject> animeshObject = scfQueryInterface<iMeshObject> (animesh); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->SetTransform (csOrthoTransform (csMatrix3 (), csVector3 (0.0f))); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->UpdateMove (); // Set the ragdoll state of the 'body' chain as kinematic ragdollNode->SetBodyChainState (bodyChain, CS::Animation::STATE_KINEMATIC); ragdollNode->SetPlaybackPosition(0); // Update the display of the dynamics debugger if (hairTest->dynamicsDebugMode == DYNDEBUG_COLLIDER || hairTest->dynamicsDebugMode == DYNDEBUG_MIXED) hairTest->dynamicsDebugger->UpdateDisplay (); // There are still big unlinerarities in the transition of Krystal's animations. // These gaps create a bad behavior of the simulation of the hairs, this is // better with lower step parameters. hairTest->bulletDynamicSystem->SetStepParameters (0.016667f, 1, 10); if (furMesh) furMesh->ResetMesh (); } isDead = false; }
csVector3 KrystalScene::GetCameraTarget () { // The target of the camera is the hips of Krystal when we are far away, // and the head when we are close csQuaternion boneRotation; csVector3 boneOffset; csRef<iMeshObject> animeshObject = scfQueryInterface<iMeshObject> (animesh); // Compute the position of the hips animesh->GetSkeleton ()->GetTransformAbsSpace (animeshFactory->GetSkeletonFactory ()->FindBone ("Hips"), boneRotation, boneOffset); csOrthoTransform hipsTransform (csMatrix3 (boneRotation.GetConjugate ()), boneOffset); csVector3 hipsPosition = (hipsTransform * animeshObject->GetMeshWrapper ()->QuerySceneNode () ->GetMovable ()->GetTransform ()).GetOrigin (); // Compute the position of the head animesh->GetSkeleton ()->GetTransformAbsSpace (animeshFactory->GetSkeletonFactory ()->FindBone ("Head"), boneRotation, boneOffset); csOrthoTransform headTransform (csMatrix3 (boneRotation.GetConjugate ()), boneOffset); csVector3 headPosition = (headTransform * animeshObject->GetMeshWrapper ()->QuerySceneNode () ->GetMovable ()->GetTransform ()).GetOrigin (); // Compute the distance between the camera and the head float distance = (hairTest->view->GetCamera ()->GetTransform ().GetOrigin () - headPosition).Norm (); // Compute the camera target csVector3 cameraTarget; if (distance >= CAMERA_HIPS_DISTANCE) cameraTarget = hipsPosition; else if (distance <= CAMERA_MINIMUM_DISTANCE) cameraTarget = headPosition; else cameraTarget = hipsPosition + (headPosition - hipsPosition) * (CAMERA_HIPS_DISTANCE - distance) / (CAMERA_HIPS_DISTANCE - CAMERA_MINIMUM_DISTANCE); return cameraTarget; }
void csQuaternion::SetMatrix (const csMatrix3& matrix) { // Ken Shoemake's article in 1987 SIGGRAPH course notes csMatrix3 mat = csMatrix3( matrix.m11, matrix.m21, matrix.m31, matrix.m12, matrix.m22, matrix.m32, matrix.m13, matrix.m23, matrix.m33); const float trace = mat.m11 + mat.m22 + mat.m33; if (trace >= 0.0f) { // Quick-route float s = sqrtf (trace + 1.0f); w = 0.5f * s; s = 0.5f / s; v.x = (mat.m32 - mat.m23) * s; v.y = (mat.m13 - mat.m31) * s; v.z = (mat.m21 - mat.m12) * s; } else { //Check biggest diagonal elmenet if (mat.m11 > mat.m22 && mat.m11 > mat.m33) { //X biggest float s = sqrtf (1.0f + mat.m11 - mat.m22 - mat.m33); v.x = 0.5f * s; s = 0.5f / s; w = (mat.m32 - mat.m23) * s; v.y = (mat.m12 + mat.m21) * s; v.z = (mat.m31 + mat.m13) * s; } else if (mat.m22 > mat.m33) { //Y biggest float s = sqrtf (1.0f + mat.m22 - mat.m11 - mat.m33); v.y = 0.5f * s; s = 0.5f / s; w = (mat.m13 - mat.m31) * s; v.x = (mat.m12 + mat.m21) * s; v.z = (mat.m23 + mat.m32) * s; } else { //Z biggest float s = sqrtf (1.0f + mat.m33 - mat.m11 - mat.m22); v.z = 0.5f * s; s = 0.5f / s; w = (mat.m21 - mat.m12) * s; v.x = (mat.m31 + mat.m13) * s; v.y = (mat.m23 + mat.m32) * s; } } }
bool csReversibleTransform::LookAt ( const csVector3 &v, const csVector3 &upNeg) { if (!LookAtZUpY (v, upNeg)) { SetT2O (csMatrix3 ()); return false; } return true; }
csMatrix3 operator* (const csMatrix3& m1, const csMatrix3& m2) { return csMatrix3 ( m1.m11*m2.m11 + m1.m12*m2.m21 + m1.m13*m2.m31, m1.m11*m2.m12 + m1.m12*m2.m22 + m1.m13*m2.m32, m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13*m2.m33, m1.m21*m2.m11 + m1.m22*m2.m21 + m1.m23*m2.m31, m1.m21*m2.m12 + m1.m22*m2.m22 + m1.m23*m2.m32, m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23*m2.m33, m1.m31*m2.m11 + m1.m32*m2.m21 + m1.m33*m2.m31, m1.m31*m2.m12 + m1.m32*m2.m22 + m1.m33*m2.m32, m1.m31*m2.m13 + m1.m32*m2.m23 + m1.m33*m2.m33 ); }
csVector3 psGameObject::DisplaceTargetPos(const iSector* mySector, const csVector3& myPos, const iSector* targetSector, const csVector3& targetPos , float offset, float angle) { csVector3 displace; // This prevents NPCs from wanting to occupy the same physical space as something else if(mySector == targetSector) { csVector3 displacement = targetPos - myPos; displacement.y = 0; csTransform transform; displacement = csMatrix3 (0.0,1.0,0.0,angle)*displacement; displace = offset*displacement.Unit(); } return displace; }
void FrankieScene::ResetScene () { // Reset the position of the animesh csRef<iMeshObject> animeshObject = scfQueryInterface<iMeshObject> (animesh); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->SetTransform (csOrthoTransform (csMatrix3 (), csVector3 (0.0f))); animeshObject->GetMeshWrapper ()->QuerySceneNode ()->GetMovable ()->UpdateMove (); frankieDead = false; if (avatarTest->physicsEnabled) { // Set the ragdoll state of the 'body' and 'tail' chains as kinematic ragdollNode->SetBodyChainState (bodyChain, CS::Animation::STATE_KINEMATIC); ragdollNode->SetBodyChainState (tailChain, CS::Animation::STATE_KINEMATIC); // Update the display of the dynamics debugger if (avatarTest->dynamicsDebugMode == DYNDEBUG_COLLIDER || avatarTest->dynamicsDebugMode == DYNDEBUG_MIXED) avatarTest->dynamicsDebugger->UpdateDisplay (); } // Reset the 'LookAt' animation node alwaysRotate = false; lookAtNodeFactory->SetAlwaysRotate (alwaysRotate); targetMode = LOOKAT_CAMERA; lookAtNode->SetTarget (avatarTest->view->GetCamera(), csVector3 (0.0f)); rotationSpeed = ROTATION_NORMAL; lookAtNodeFactory->SetMaximumSpeed (5.0f); lookAtNode->Play (); // Reset the 'speed' animation node currentSpeed = 0; speedNode->SetSpeed (((float) currentSpeed) / 10.0f); // Reset morphing smileWeight = 1.0f; animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("smile.B"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("eyebrows_down.B"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("wings_in"), 1.0f); animesh->SetMorphTargetWeight (animeshFactory->FindMorphTarget ("eyelids_closed"), 0.0f); }
void SoftBodyControl::SetSoftBody (CS::Physics::Bullet::iSoftBody* body, bool doubleSided) { CS_ASSERT (body); // Reset the data softBody = body; this->doubleSided = doubleSided; vertices.SetSize (doubleSided ? softBody->GetVertexCount () * 2 : softBody->GetVertexCount ()); normals.SetSize (doubleSided ? softBody->GetVertexCount () * 2 : softBody->GetVertexCount ()); anchors.DeleteAll (); // Initialize the vertices and mesh position meshPosition.Set (0.0f); for (size_t i = 0; i < softBody->GetVertexCount (); i++) meshPosition += softBody->GetVertexPosition (i); meshPosition /= softBody->GetVertexCount (); mesh->GetMeshWrapper ()->GetMovable ()->SetTransform (csMatrix3 ()); Update (0, 0, 0); }
csMatrix3 csQuaternion::GetMatrix () const { const float x2 = v.x*2.0f; const float y2 = v.y*2.0f; const float z2 = v.z*2.0f; const float xx2 = v.x*x2; const float xy2 = v.y*x2; const float xz2 = v.z*x2; const float xw2 = w*x2; const float yy2 = v.y*y2; const float yz2 = v.z*y2; const float yw2 = w*y2; const float zz2 = v.z*z2; const float zw2 = w*z2; return csMatrix3 ( 1.0f - (yy2+zz2), xy2 - zw2, xz2 + yw2, xy2 + zw2, 1.0f - (xx2+zz2), yz2 - xw2, xz2 - yw2, yz2 + xw2, 1.0f - (xx2+yy2)); }
int psLinearMovement::MoveSprite (float delta) { int ret = PS_MOVE_SUCCEED; csReversibleTransform fulltransf = mesh->GetMovable () ->GetFullTransform (); // const csMatrix3& transf = fulltransf.GetT2O (); // Calculate the total velocity (body and world) in OBJECT space. csVector3 bodyVel (fulltransf.Other2ThisRelative (velWorld) + velBody); float local_max_interval = csMin(csMin((bodyVel.y==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.y/bodyVel.y), (bodyVel.x==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.x/bodyVel.x) ),(bodyVel.z==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.z/bodyVel.z) ); // Err on the side of safety (95% error margin) local_max_interval *= 0.95f; //printf("local_max_interval=%f, bodyVel is %1.2f, %1.2f, %1.2f\n",local_max_interval, bodyVel.x, bodyVel.y, bodyVel.z); //printf("velWorld is %1.2f, %1.2f, %1.2f\n", velWorld.x, velWorld.y, velWorld.z); //printf("velBody is %1.2f, %1.2f, %1.2f\n", velBody.x, velBody.y, velBody.z); // Sanity check on time interval here. Something is messing it up. -KWF //local_max_interval = csMax(local_max_interval, 0.1F); if (colldet) { while (delta > local_max_interval) { csVector3 oldpos(mesh->GetMovable ()->GetFullTransform ().GetOrigin()); // Perform brutal optimisation here for falling with no obstacles if(velWorld.y < -20.0f && mesh->GetMovable()->GetSectors()->GetCount() > 0) { csVector3 worldVel (fulltransf.This2OtherRelative (velBody) + velWorld); bool hit = false; // We check for other meshes at the start and end of the box with radius * 2 to be on the safe side { csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), oldpos + boundingBox.GetCenter(), boundingBox.GetSize().Norm() * 2); if(objectIter->HasNext()) hit = true; } if(!hit) { csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), oldpos + worldVel * delta + boundingBox.GetCenter(), boundingBox.GetSize().Norm() * 2); if(objectIter->HasNext()) hit = true; } if(!hit) { csOrthoTransform transform_newpos(csMatrix3(), oldpos + worldVel * delta); csBox3 fullBox(fulltransf.This2OtherRelative(boundingBox.Min()), fulltransf.This2OtherRelative(boundingBox.Max())); csBox3 newBox( transform_newpos.This2OtherRelative(boundingBox.Min()), transform_newpos.This2OtherRelative(boundingBox.Max())); fullBox.AddBoundingBox(newBox); csRef<iMeshWrapperIterator> objectIter = engine->GetNearbyMeshes(mesh->GetMovable()->GetSectors()->Get(0), fullBox); if(objectIter->HasNext()) hit = true; } if(!hit) local_max_interval = delta; } ret = MoveV (local_max_interval); csVector3 displacement(fulltransf.GetOrigin() - oldpos); displacement = fulltransf.Other2ThisRelative(displacement); // Check the invariants still hold otherwise we may jump walls if(!(fabs(displacement.x) <= intervalSize.x)) { printf("X (%g) out of bounds when performing CD > %g!\n", fabs(displacement.x), intervalSize.x); CS_ASSERT(false); } if(!(fabs(displacement.z) <= intervalSize.z)) { printf("Z (%g) out of bounds when performing CD > %g!\n", fabs(displacement.y), intervalSize.y); CS_ASSERT(false); } if(!(fabs(displacement.y) <= intervalSize.y)) { printf("Y (%g) out of bounds when performing CD > %g!\n", fabs(displacement.z), intervalSize.z); CS_ASSERT(false); } RotateV (local_max_interval); // We must update the transform after every rotation! fulltransf = mesh->GetMovable ()->GetFullTransform (); if (ret == PS_MOVE_FAIL) return ret; // The velocity may have changed by now bodyVel = fulltransf.Other2ThisRelative(velWorld) + velBody; delta -= local_max_interval; local_max_interval = csMin(csMin((bodyVel.y==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.y/bodyVel.y), (bodyVel.x==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.x/bodyVel.x)), (bodyVel.z==0.0f) ? MAX_CD_INTERVAL : ABS (intervalSize.z/bodyVel.z)); // Err on the side of safety (95% error margin) local_max_interval *= 0.95f; // Sanity check on time interval here. Something is messing it up. -KWF // local_max_interval = csMax(local_max_interval, 0.1F); } } if (!colldet || delta) { ret = MoveV (delta); RotateV(delta); } return ret; }
csMatrix3 psEffectObj::BuildRotMatrix(const csVector3 &up) const { csVector3 forward = csVector3(0, 0, 1); csVector3 right = up % forward; return csMatrix3(right.x, right.y, right.z, up.x, up.y, up.z, forward.x, forward.y, forward.z); }
bool SelfShadowDemo::OnKeyboard (iEvent &ev) { // Default behavior from csDemoApplication DemoApplication::OnKeyboard (ev); // First get elapsed time from the virtual clock. csTicks elapsed_time = vc->GetElapsedTicks (); float speed = (elapsed_time / 1000.0) * (0.03 * 20); // Only moves the first light csRef<iLight> light = engine->GetSectors()->Get(0)->GetLights()->Get(0); float moveFactor = 0; csMatrix3 rotateMatrix = csMatrix3(); float rotateFactor = speed; csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev); if (eventtype == csKeyEventTypeDown) { if (csKeyEventHelper::GetCookedCode (&ev) == 'w') { rotateMatrix = csMatrix3(1, 0, 0, 0, cos(rotateFactor), -sin(rotateFactor), 0, sin(rotateFactor), cos(rotateFactor)); } else if (csKeyEventHelper::GetCookedCode (&ev) == 's') { rotateMatrix = csMatrix3(1, 0, 0, 0, cos(rotateFactor), sin(rotateFactor), 0, -sin(rotateFactor), cos(rotateFactor)); } else if (csKeyEventHelper::GetCookedCode (&ev) == 'a') { rotateMatrix = csMatrix3(cos(rotateFactor), -sin(rotateFactor), 0, sin(rotateFactor), cos(rotateFactor), 0, 0, 0, 1); } else if (csKeyEventHelper::GetCookedCode (&ev) == 'd') { rotateMatrix = csMatrix3(cos(rotateFactor), sin(rotateFactor), 0, -sin(rotateFactor), cos(rotateFactor), 0, 0, 0, 1); } // Recomputed the split ratio else if (csKeyEventHelper::GetCookedCode (&ev) == 'r') { rm_dbg->DebugCommand("reset_split_ratio"); return true; } // Switch between showing the render textures else if (csKeyEventHelper::GetCookedCode (&ev) == 't') { rm_dbg->DebugCommand("show_render_textures"); return true; } // Load next scene else if (csKeyEventHelper::GetCookedCode (&ev) == 'n') { sceneNumber = ( sceneNumber + 1 ) % numberOfScenes; CreateScene(); return true; } // Load previous scene else if (csKeyEventHelper::GetCookedCode (&ev) == 'p') { sceneNumber = ( sceneNumber - 1 ); if (sceneNumber < 0) sceneNumber += numberOfScenes; CreateScene(); return true; } // Start dynamic scene else if (csKeyEventHelper::GetCookedCode (&ev) == 'g') { rotateGrass = !rotateGrass; return true; } // Rotate light light->GetMovable()->Transform(rotateMatrix); csVector3 oldDirection = light->GetMovable()->GetPosition(); float oldLength = oldDirection.Norm(); oldDirection.Normalize(); csVector3 newDirection = (rotateMatrix * oldDirection); float newLength = oldLength + moveFactor; newDirection.Normalize(); csVector3 position = newDirection * newLength; light->GetMovable()->SetPosition(position); light->GetMovable()->UpdateMove(); return true; } return false; }
bool RagdollAnimNode::CreateRigidBodyNode (iBodyChainNode* node, iRigidBody* parentBody) { iBodyBone* bodyBone = node->GetBodyBone (); // check availability of collider if (!bodyBone->GetBoneColliderCount ()) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No colliders for bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } // check availability of joint if (parentBody && !bodyBone->GetBoneJoint ()) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No joint for bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } // create bone reference Bone bone; bone.boneID = bodyBone->GetAnimeshBone (); // create rigid body csRef<iRigidBody> rigidBody = factory->dynSys->CreateBody (); bone.rigidBody = rigidBody; // set body position csQuaternion rotation; csVector3 offset; skeleton->GetTransformAbsSpace (bone.boneID, rotation, offset); // TODO: we shouldn't have to use the conjugate of the quaternion, isn't it? csOrthoTransform boneTransform (csMatrix3 (rotation.GetConjugate ()), offset); csOrthoTransform animeshTransform = sceneNode->GetMovable ()->GetTransform (); csOrthoTransform bodyTransform = boneTransform * animeshTransform; rigidBody->SetTransform (bodyTransform); // set body properties if they are defined // (with the Bullet plugin, it is more efficient to define it before the colliders) iBodyBoneProperties* properties = bodyBone->GetBoneProperties (); if (properties) rigidBody->SetProperties (properties->GetMass (), properties->GetCenter (), properties->GetInertia ()); // attach bone colliders for (uint index = 0; index < bodyBone->GetBoneColliderCount (); index++) { iBodyBoneCollider* collider = bodyBone->GetBoneCollider (index); switch (collider->GetGeometryType ()) { case BOX_COLLIDER_GEOMETRY: { csVector3 boxSize; collider->GetBoxGeometry (boxSize); rigidBody->AttachColliderBox (boxSize, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CYLINDER_COLLIDER_GEOMETRY: { float length, radius; collider->GetCylinderGeometry (length, radius); rigidBody->AttachColliderCylinder (length, radius, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CAPSULE_COLLIDER_GEOMETRY: { float length, radius; collider->GetCapsuleGeometry (length, radius); rigidBody->AttachColliderCapsule (length, radius, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CONVEXMESH_COLLIDER_GEOMETRY: { iMeshWrapper* mesh; collider->GetConvexMeshGeometry (mesh); rigidBody->AttachColliderConvexMesh (mesh, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case TRIMESH_COLLIDER_GEOMETRY: { iMeshWrapper* mesh; collider->GetMeshGeometry (mesh); rigidBody->AttachColliderMesh (mesh, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case PLANE_COLLIDER_GEOMETRY: { csPlane3 plane; collider->GetPlaneGeometry (plane); // TODO: add transform rigidBody->AttachColliderPlane (plane, collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case SPHERE_COLLIDER_GEOMETRY: { csSphere sphere; collider->GetSphereGeometry (sphere); rigidBody->AttachColliderSphere (sphere.GetRadius (), sphere.GetCenter () + collider->GetTransform ().GetOrigin (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } default: factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No geometry for collider in bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } } // TODO: remove bodies if problem // create dynamic joint if (parentBody) bone.joint = CreateDynamicJoint (bodyBone->GetBoneJoint (), parentBody, rigidBody); // store bone bones.Put (bone.boneID, bone); // create child nodes for (uint i = 0; i < node->GetChildCount (); i++) if (!CreateRigidBodyNode (node->GetChild (i), rigidBody)) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "Problem creating ragdoll body for bone %i\n", bodyBone->GetAnimeshBone ()); return false; } return true; }
csMatrix3 operator+ (const csMatrix3& m1, const csMatrix3& m2) { return csMatrix3 (m1.m11+m2.m11, m1.m12+m2.m12, m1.m13+m2.m13, m1.m21+m2.m21, m1.m22+m2.m22, m1.m23+m2.m23, m1.m31+m2.m31, m1.m32+m2.m32, m1.m33+m2.m33); }
void IKPhysicalNode::AddConstraint (CS::Animation::EffectorID effectorID, ConstraintData& constraint) { // Find the effector data EffectorData* effector = factory->effectors[effectorID]; // Check if this chain has already some constraints ChainData chainData; if (!chains.Contains (effector->chain)) { // Create a new entry for the chain chainData.previousState = ragdollNode->GetBodyChainState (effector->chain); chainData.constraintCount = 1; chains.Put (effector->chain, chainData); // Set the chain as dynamic ragdollNode->SetBodyChainState (effector->chain, CS::Animation::STATE_DYNAMIC); } else { chainData = chains.Get (effector->chain, chainData); chainData.constraintCount++; } // Compute the world transform of the effector csQuaternion boneRotation; csVector3 boneOffset; skeleton->GetTransformAbsSpace (effector->bone, boneRotation, boneOffset); csOrthoTransform boneTransform (csMatrix3 (boneRotation.GetConjugate ()), boneOffset); csOrthoTransform effectorTransform = effector->transform * boneTransform * sceneNode->GetMovable ()->GetFullTransform (); // Compute the world transform of the constraint target csOrthoTransform targetTransform; switch (constraint.type) { case CONSTRAINT_FIXED: targetTransform = constraint.offset; break; case CONSTRAINT_MOVABLE: targetTransform = constraint.offset * constraint.movable->GetFullTransform (); break; case CONSTRAINT_CAMERA: targetTransform = constraint.offset * constraint.camera->GetTransform (); break; default: break; } // Create a pivot joint constraint.dragJoint = bulletDynamicSystem->CreatePivotJoint (); constraint.dragJoint->Attach (ragdollNode->GetBoneRigidBody (effector->bone), effectorTransform.GetOrigin ()); constraint.dragJoint->SetPosition (targetTransform.GetOrigin ()); constraints.PutUnique (effectorID, constraint); }
csMatrix3 operator- (const csMatrix3& m1, const csMatrix3& m2) { return csMatrix3 (m1.m11-m2.m11, m1.m12-m2.m12, m1.m13-m2.m13, m1.m21-m2.m21, m1.m22-m2.m22, m1.m23-m2.m23, m1.m31-m2.m31, m1.m32-m2.m32, m1.m33-m2.m33); }
csMatrix3 operator* (float f, const csMatrix3& m) { return csMatrix3 (m.m11*f, m.m12*f, m.m13*f, m.m21*f, m.m22*f, m.m23*f, m.m31*f, m.m32*f, m.m33*f); }