// calculates the bone matrices for the given mesh std::vector<aiMatrix4x4>& Animator::GetBoneMatrices(aiNode* node, int nodeMeshIndex) { if (nodeMeshIndex < node->mNumMeshes) { unsigned int meshIndex = node->mMeshes[nodeMeshIndex]; if ((mainScene != NULL) && (meshIndex < mainScene->mNumMeshes)) { const aiMesh* mesh = mainScene->mMeshes[meshIndex]; for (unsigned int i = 0; i < boneTransforms.size(); i++) { boneTransforms[i] = aiMatrix4x4(); } // resize array and initialise it with identity matrices boneTransforms.resize(mesh->mNumBones, aiMatrix4x4()); // calculate the mesh's inverse global transform aiMatrix4x4 mGlobalInverseMeshTransform = GetGlobalTransform(node); mGlobalInverseMeshTransform.Inverse(); // calculate transform from mesh coordinates in bind pose to mesh coordinates in skinned pose for (unsigned int i = 0; i < mesh->mNumBones; i++) { const aiBone* bone = mesh->mBones[i]; const aiMatrix4x4& mCurrentGlobalTransform = GetGlobalTransform(mapBoneNodesByName[bone->mName.data]); boneTransforms[i] = mGlobalInverseMeshTransform * mCurrentGlobalTransform * bone->mOffsetMatrix; } } } //and return the result return boneTransforms; }
// ------------------------------------------------------------------------------------------------ // Calculates the bone matrices for the given mesh. const std::vector<aiMatrix4x4>& SceneAnimator::GetBoneMatrices(const aiNode* pNode, size_t pMeshIndex /* = 0 */) { ai_assert(pMeshIndex < pNode->mNumMeshes); size_t meshIndex = pNode->mMeshes[pMeshIndex]; ai_assert(meshIndex < mScene->mNumMeshes); const aiMesh* mesh = mScene->mMeshes[meshIndex]; // resize array and initialise it with identity matrices mTransforms.resize(mesh->mNumBones, aiMatrix4x4()); // calculate the mesh's inverse global transform aiMatrix4x4 globalInverseMeshTransform = GetGlobalTransform(pNode); globalInverseMeshTransform.Inverse(); // Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform for (size_t a = 0; a < mesh->mNumBones; ++a) { const aiBone* bone = mesh->mBones[a]; const aiMatrix4x4& currentGlobalTransform = GetGlobalTransform(mBoneNodesByName[bone->mName.data]); mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix; } // and return the result return mTransforms; }
void CCharacter::ShowPlayerVectors() const { TMatrix m = GetGlobalTransform(); Vector vecUp = GetUpVector(); Vector vecRight = m.GetForwardVector().Cross(vecUp).Normalized(); Vector vecForward = vecUp.Cross(vecRight).Normalized(); m.SetColumn(0, vecForward); m.SetColumn(1, vecUp); m.SetColumn(2, vecRight); CCharacter* pLocalCharacter = Game()->GetLocalPlayer()->GetCharacter(); TVector vecEyeHeight = GetUpVector() * EyeHeight(); CRenderingContext c(GameServer()->GetRenderer()); c.Translate((GetGlobalOrigin() - pLocalCharacter->GetGlobalOrigin())); c.SetColor(Color(255, 255, 255)); c.BeginRenderDebugLines(); c.Vertex(Vector(0,0,0)); c.Vertex((float)EyeHeight() * vecUp); c.EndRender(); if (!GetGlobalVelocity().IsZero()) { c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + GetGlobalVelocity()); c.EndRender(); } c.SetColor(Color(255, 0, 0)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecForward); c.EndRender(); c.SetColor(Color(0, 255, 0)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecRight); c.EndRender(); c.SetColor(Color(0, 0, 255)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecUp); c.EndRender(); TVector vecPoint, vecNormal; if (Game()->TraceLine(GetGlobalOrigin(), GetGlobalOrigin() - GetUpVector()*100, vecPoint, vecNormal, NULL)) { c.Translate(vecPoint - GetGlobalOrigin()); c.Scale(0.1f, 0.1f, 0.1f); c.SetColor(Color(255, 255, 255)); c.RenderSphere(); } }
CScalableMatrix CSPCharacter::GetScalableRenderTransform() const { CSPCharacter* pCharacter = SPGame()->GetLocalPlayerCharacter(); CScalableVector vecCharacterOrigin = pCharacter->GetGlobalOrigin(); CScalableMatrix mTransform = GetGlobalTransform(); mTransform.SetTranslation(mTransform.GetTranslation() - vecCharacterOrigin); return mTransform; }
void CSPCharacter::LockViewToPlanet() { // Now lock the roll value to the planet. CPlanet* pNearestPlanet = GetNearestPlanet(); if (!pNearestPlanet) return; Matrix4x4 mGlobalRotation = GetGlobalTransform(); mGlobalRotation.SetTranslation(CScalableVector()); // Construct a "local space" for the planet Vector vecPlanetUp = GetUpVector(); Vector vecPlanetForward = mGlobalRotation.GetForwardVector(); Vector vecPlanetRight = vecPlanetForward.Cross(vecPlanetUp).Normalized(); vecPlanetForward = vecPlanetUp.Cross(vecPlanetRight).Normalized(); Matrix4x4 mPlanet(vecPlanetForward, vecPlanetUp, vecPlanetRight); Matrix4x4 mPlanetInverse = mPlanet; mPlanetInverse.InvertTR(); // Bring our current view angles into that local space Matrix4x4 mLocalRotation = mPlanetInverse * mGlobalRotation; EAngle angLocalRotation = mLocalRotation.GetAngles(); // Lock them so that the roll is 0 // I'm sure there's a way to do this without converting to euler but at this point I don't care. angLocalRotation.r = 0; Matrix4x4 mLockedLocalRotation; mLockedLocalRotation.SetAngles(angLocalRotation); // Bring it back out to global space Matrix4x4 mLockedRotation = mPlanet * mLockedLocalRotation; // Only use the changed r value to avoid floating point crap EAngle angNewLockedRotation = GetGlobalAngles(); EAngle angOverloadRotation = mLockedRotation.GetAngles(); // Lerp our way there float flTimeToLocked = 1; if (GameServer()->GetGameTime() - m_flLastEnteredAtmosphere > flTimeToLocked) angNewLockedRotation.r = angOverloadRotation.r; else angNewLockedRotation.r = RemapValClamped(SLerp(GameServer()->GetGameTime() - m_flLastEnteredAtmosphere, 0.3f), 0, flTimeToLocked, m_flRollFromSpace, angOverloadRotation.r); SetGlobalAngles(angNewLockedRotation); }
HRESULT CBoundingBox::PutData(enum BOUND_FORMAT nFormat, FWULONG nSize, /*[in, size_is(nSize)]*/ BYTE *pBuf) { #define BUFAABB ((struct BOUND_AABB*)pBuf) #define BUFOBB ((struct BOUND_OBB*)pBuf) #define BUFOBB_8 ((struct BOUND_OBB_8*)pBuf) #define BUFSPHERE ((struct BOUND_SPHERE*)pBuf) #define BUFCYLINDER ((struct BOUND_CYLINDER*)pBuf) switch (nFormat) { case BOUND_FORMAT_AABB: if (nSize != sizeof(BOUND_AABB)) return ERROR(FW_E_FORMAT); m_obb.vecSize.x = fabs(BUFAABB->vecMax.x - BUFAABB->vecMin.x) * 0.5f; m_obb.vecSize.y = fabs(BUFAABB->vecMax.y - BUFAABB->vecMin.y) * 0.5f; m_obb.vecSize.z = fabs(BUFAABB->vecMax.z - BUFAABB->vecMin.z) * 0.5f; memset(m_obb.M, 0, sizeof(m_obb.M)); m_obb.M[3][0] = (BUFAABB->vecMin.x + BUFAABB->vecMax.x) * 0.5f; m_obb.M[3][1] = (BUFAABB->vecMin.y + BUFAABB->vecMax.y) * 0.5f; m_obb.M[3][2] = (BUFAABB->vecMin.z + BUFAABB->vecMax.z) * 0.5f; m_obb.M[0][0] = m_obb.M[1][1] = m_obb.M[2][2] = m_obb.M[3][3] = 1.0f; break; case BOUND_FORMAT_OBB: if (nSize != sizeof(BOUND_OBB)) return ERROR(FW_E_FORMAT); memcpy(&m_obb, pBuf, sizeof(m_obb)); break; case BOUND_FORMAT_OBB_8: if (nSize != sizeof(BOUND_OBB)) return ERROR(FW_E_FORMAT); return ERROR(FW_E_FORMAT); case BOUND_FORMAT_SPHERE: if (nSize != sizeof(BOUND_SPHERE)) return ERROR(FW_E_FORMAT); m_obb.vecSize.x = m_obb.vecSize.y = m_obb.vecSize.z = BUFSPHERE->fRadius; memset(m_obb.M, 0, sizeof(m_obb.M)); m_obb.M[3][0] = BUFSPHERE->vecCenter.x; m_obb.M[3][1] = BUFSPHERE->vecCenter.y; m_obb.M[3][2] = BUFSPHERE->vecCenter.z; m_obb.M[0][0] = m_obb.M[1][1] = m_obb.M[2][2] = m_obb.M[3][3] = 1.0f; break; case BOUND_FORMAT_CYLINDER: if (nSize != sizeof(BOUND_CYLINDER)) return ERROR(FW_E_FORMAT); return ERROR(FW_E_FORMAT); default: return ERROR(FW_E_FORMAT); } ITransform *pT = NULL; CreateCompatibleTransform(&pT); HRESULT h = GetGlobalTransform(pT); if (FAILED(h)) return ERROR(h); pT->Inverse(); FWMATRIX M, M1; pT->AsMatrix(M1); pT->Release(); _Multiply(M, m_obb.M, M1); memcpy(m_obb.M, M, sizeof(M)); return S_OK; }
HRESULT CBoundingBox::GetData(enum BOUND_FORMAT nFormat, FWULONG nSize, /*[out, size_is(nSize)]*/ BYTE *pBuf) { #define BUFAABB ((struct BOUND_AABB*)pBuf) #define BUFOBB ((struct BOUND_OBB*)pBuf) #define BUFOBB_8 ((struct BOUND_OBB_8*)pBuf) #define BUFSPHERE ((struct BOUND_SPHERE*)pBuf) #define BUFCYLINDER ((struct BOUND_CYLINDER*)pBuf) FWMATRIX M, M1; ITransform *pT = NULL; CreateCompatibleTransform(&pT); HRESULT h = GetGlobalTransform(pT); if (FAILED(h)) return ERROR(h); pT->AsMatrix(M1); pT->Release(); _Multiply(M, m_obb.M, M1); switch (nFormat) { case BOUND_FORMAT_AABB: if (nSize != sizeof(BOUND_AABB)) return ERROR(FW_E_FORMAT); BUFAABB->vecMin.x = -m_obb.vecSize.x; BUFAABB->vecMin.y = -m_obb.vecSize.y; BUFAABB->vecMin.z = -m_obb.vecSize.z; BUFAABB->vecMax.x = m_obb.vecSize.x; BUFAABB->vecMax.y = m_obb.vecSize.y; BUFAABB->vecMax.z = m_obb.vecSize.z; _Transform(&BUFAABB->vecMin, M); _Transform(&BUFAABB->vecMax, M); break; case BOUND_FORMAT_OBB: if (nSize != sizeof(BOUND_OBB)) return ERROR(FW_E_FORMAT); memcpy(BUFOBB->M, M, sizeof(M)); memcpy(&BUFOBB->vecSize, &m_obb.vecSize, sizeof(m_obb.vecSize)); break; case BOUND_FORMAT_OBB_8: BUFOBB_8->OBB[0].x = -m_obb.vecSize.x; BUFOBB_8->OBB[0].y = -m_obb.vecSize.y; BUFOBB_8->OBB[0].z = -m_obb.vecSize.z; BUFOBB_8->OBB[1].x = m_obb.vecSize.x; BUFOBB_8->OBB[1].y = -m_obb.vecSize.y; BUFOBB_8->OBB[1].z = -m_obb.vecSize.z; BUFOBB_8->OBB[2].x = -m_obb.vecSize.x; BUFOBB_8->OBB[2].y = -m_obb.vecSize.y; BUFOBB_8->OBB[2].z = m_obb.vecSize.z; BUFOBB_8->OBB[3].x = m_obb.vecSize.x; BUFOBB_8->OBB[3].y = -m_obb.vecSize.y; BUFOBB_8->OBB[3].z = m_obb.vecSize.z; BUFOBB_8->OBB[4].x = -m_obb.vecSize.x; BUFOBB_8->OBB[4].y = m_obb.vecSize.y; BUFOBB_8->OBB[4].z = -m_obb.vecSize.z; BUFOBB_8->OBB[5].x = m_obb.vecSize.x; BUFOBB_8->OBB[5].y = m_obb.vecSize.y; BUFOBB_8->OBB[5].z = -m_obb.vecSize.z; BUFOBB_8->OBB[6].x = -m_obb.vecSize.x; BUFOBB_8->OBB[6].y = m_obb.vecSize.y; BUFOBB_8->OBB[6].z = m_obb.vecSize.z; BUFOBB_8->OBB[7].x = m_obb.vecSize.x; BUFOBB_8->OBB[7].y = m_obb.vecSize.y; BUFOBB_8->OBB[7].z = m_obb.vecSize.z; for (int i = 0; i < 8; i++) _Transform(BUFOBB_8->OBB + i, M); break; case BOUND_FORMAT_SPHERE: if (nSize != sizeof(BOUND_SPHERE)) return ERROR(FW_E_FORMAT); BUFSPHERE->vecCenter.x = (FWFLOAT)M[3][0]; BUFSPHERE->vecCenter.y = (FWFLOAT)M[3][1]; BUFSPHERE->vecCenter.z = (FWFLOAT)M[3][2]; // _Transform not needed here (no rotation) BUFSPHERE->fRadius = sqrt(m_obb.vecSize.x * m_obb.vecSize.x + m_obb.vecSize.y * m_obb.vecSize.y + m_obb.vecSize.z * m_obb.vecSize.z); break; case BOUND_FORMAT_CYLINDER: if (nSize != sizeof(BOUND_CYLINDER)) return ERROR(FW_E_FORMAT); BUFCYLINDER->vecPivot1.x = BUFCYLINDER->vecPivot1.z = BUFCYLINDER->vecPivot2.x = BUFCYLINDER->vecPivot2.z = 0.0f; BUFCYLINDER->vecPivot1.y = -m_obb.vecSize.y; BUFCYLINDER->vecPivot2.y = m_obb.vecSize.y; _Transform(&BUFCYLINDER->vecPivot1, M); _Transform(&BUFCYLINDER->vecPivot2, M); BUFCYLINDER->fRadius = sqrt(m_obb.vecSize.x * m_obb.vecSize.x + m_obb.vecSize.z * m_obb.vecSize.z); break; default: return ERROR(FW_E_FORMAT); } return S_OK; }
const Matrix4x4 CLevelEntity::GetPhysicsTransform() const { return GetGlobalTransform(); }