/** * @brief * Returns position, rotation and scale from a matrix */ void PLTools::GetPosRotScale(const GMatrix &mTransform, Point3 &vPos, Quat &qRot, Point3 &vScale, bool bFlip) { // Get the position vPos = mTransform.Translation(); // Get the rotation of the node as quaternion qRot = mTransform.Rotation(); // Flip 180 degree around the y-axis? (true for camera and spot lights) if (bFlip) { Quat qRotationOffset; // We have to add a rotation about the x-axis of -90 degree... is this a IGame transform bug or something other odd?? float fAngles[] = {static_cast<float>(HALFPI), 0.0f, 0.0f}; EulerToQuat(fAngles, qRotationOffset); qRot = qRotationOffset*qRot; // We have to 'invert the z-axis', this is no PixelLight bug or so, we decided to do so to make things more universal fAngles[0] = 0.0f; fAngles[2] = static_cast<float>(PI); EulerToQuat(fAngles, qRotationOffset); qRot = qRotationOffset*qRot; } // Look out! We REALLY need to take the parity of the transform matrix into account! vScale = mTransform.Scaling()*static_cast<float>(mTransform.Parity()); }
void MeshExporter::_dumpJoint(IGameNode * node) { IGameObject * obj = node->GetIGameObject(); IGameObject::MaxType T = obj->GetMaxType(); IGameObject::ObjectTypes type = obj->GetIGameType(); const char * name = node->GetName(); switch(type) { case IGameObject::IGAME_BONE: case IGameObject::IGAME_HELPER: { joint * bone = mMeshSource->NewJoint(node->GetName()); int parent = -1; if (node->GetNodeParent()) { parent = _getJointId(node->GetNodeParent()->GetName()); mMeshSource->SetJointLink(parent, mMeshSource->GetJointCount() - 1); } else { INode* pNode = node->GetMaxNode()->GetParentNode(); if (pNode) parent = _getJointId(pNode->GetName()); } IGameControl * pGameControl = node->GetIGameControl(); // base matrix { GMatrix matWorld = node->GetLocalTM(); bone->position = Utility::ToFloat3(matWorld.Translation()); bone->rotation = Utility::ToQuat(matWorld.Rotation()); bone->scale = Utility::ToFloat3(matWorld.Scaling()); /* if (node->GetNodeParent()) { int parentId = _getBoneId(node->GetNodeParent()->GetName()); if (parentId != -1) { xBone * parentBn = GetBone(parentId); bone->position = bone->position - parentBn->position; bone->orientation = parentBn->orientation.Inverse() * bone->orientation; bone->scale = bone->scale / parentBn->scale; } } */ } _dumpAnimation(pGameControl, mMeshSource->GetJointCount() - 1); } break; } }
bool Optimizer:: dumpPhysXCookMesh(IGameNode* gameNode, const std::string& nodeName, int flag) { // 受缩放影响 GMatrix worldTM = gameNode->GetWorldTM(); Point3 scale = worldTM.Scaling(); // 世界矩阵的逆矩阵 GMatrix nodeInvWorldTM = gameNode->GetWorldTM().Inverse(); IGameObject* gameObject = gameNode->GetIGameObject(); IGameMesh* gameMesh = static_cast<IGameMesh*>(gameObject); gameMesh->InitializeData(); int numFaces = gameMesh->GetNumberOfFaces(); int numVertex = numFaces * 3; std::vector<physx::PxVec3> pxVertices; pxVertices.reserve(numVertex); oiram::IndexBuffer indexBuffer; indexBuffer.use32BitIndices = numVertex > 65535; indexBuffer.use32BitIndices ? indexBuffer.uiIndexBuffer.reserve(numVertex) : indexBuffer.usIndexBuffer.reserve(numVertex); for (int i = 0; i < numFaces; ++i) { FaceEx* face = gameMesh->GetFace(i); for (int v = 0; v < 3; ++v) { Point3 position = gameMesh->GetVertex(face->vert[v], false); position = position * nodeInvWorldTM; pxVertices.push_back(physx::PxVec3(position.x * scale.x, position.y * scale.y, position.z * scale.z)); if (indexBuffer.use32BitIndices) indexBuffer.uiIndexBuffer.push_back(static_cast<unsigned int>(indexBuffer.uiIndexBuffer.size())); else indexBuffer.usIndexBuffer.push_back(static_cast<unsigned short>(indexBuffer.usIndexBuffer.size())); } } gameNode->ReleaseIGameObject(); // 初始化physx对象 physx::PxDefaultAllocator s_defAlloc; PxOiramErrorCallback s_defErrCb; physx::PxFoundation* pFound = PxCreateFoundation(PX_PHYSICS_VERSION, s_defAlloc, s_defErrCb); physx::PxCooking* pCooking = PxCreateCooking(PX_PHYSICS_VERSION, *pFound, physx::PxCookingParams()); // 优化物理模型顶点 optimizePhysXMesh(flag, mD3DDevice, mEpsilon, pxVertices, indexBuffer); bool success = false; PxCookMesh cookMesh; switch (flag) { // cookConvexMesh case 1: default: { physx::PxConvexMeshDesc meshDesc; meshDesc.points.data = pxVertices.data(); meshDesc.points.count = static_cast<physx::PxU32>(pxVertices.size()); meshDesc.points.stride = sizeof(physx::PxVec3); meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; // 先尝试导出 success = meshDesc.isValid() && pCooking->cookConvexMesh(meshDesc, cookMesh); if (!success) { // polygon数量大于255的时候需要加上eINFLATE_CONVEX meshDesc.flags |= physx::PxConvexFlag::eINFLATE_CONVEX; success = meshDesc.isValid() && pCooking->cookConvexMesh(meshDesc, cookMesh); } } break; // cookTriangleMesh case 2: { physx::PxTriangleMeshDesc meshDesc; meshDesc.points.data = pxVertices.data(); meshDesc.points.count = static_cast<physx::PxU32>(pxVertices.size()); meshDesc.points.stride = sizeof(physx::PxVec3); if (indexBuffer.use32BitIndices) { meshDesc.triangles.data = indexBuffer.uiIndexBuffer.data(); meshDesc.triangles.count = static_cast<physx::PxU32>(indexBuffer.uiIndexBuffer.size()) / 3; meshDesc.triangles.stride = sizeof(physx::PxU32) * 3; } else { meshDesc.triangles.data = indexBuffer.usIndexBuffer.data(); meshDesc.triangles.count = static_cast<physx::PxU16>(indexBuffer.usIndexBuffer.size()) / 3; meshDesc.triangles.stride = sizeof(physx::PxU16) * 3; meshDesc.flags = physx::PxMeshFlag::e16_BIT_INDICES; } success = meshDesc.isValid(); success = success && pCooking->cookTriangleMesh(meshDesc, cookMesh); } break; } if (success) { std::string pxName = nodeName + ".px"; LogManager::getSingleton().logMessage(false, "Exporting: %s", pxName.c_str()); pxName = config.exportPath + pxName; FILE* fp = fopen(pxName.c_str(), "wb"); if (fp) { fwrite(cookMesh.getData(), cookMesh.getSize(), 1, fp); fclose(fp); } } pCooking->release(); pFound->release(); return success; }