/*---------------------------------------------------------------------------*/ bool NifCollisionUtility::injectCollisionData(vector<hkGeometry>& geometryMap, bhkMoppBvTreeShapeRef pMoppShape, bhkCompressedMeshShapeDataRef pData, bhkRigidBodyRef pRigidBody) { if (pMoppShape == NULL) return false; if (pData == NULL) return false; if (geometryMap.empty()) return false; //---- Havok ---- START hkpCompressedMeshShape* pCompMesh (NULL); hkpMoppCode* pMoppCode (NULL); hkpMoppBvTreeShape* pMoppBvTree(NULL); hkpCompressedMeshShapeBuilder shapeBuilder; hkpMoppCompilerInput mci; vector<int> geometryIdxVec; vector<bhkCMSDMaterial> tMtrlVec; SkyrimHavokMaterial material (SKY_HAV_MAT_STONE); int subPartId (0); int tChunkSize (0); // initialize shape Builder shapeBuilder.m_stripperPasses = 5000; // create compressedMeshShape pCompMesh = shapeBuilder.createMeshShape(0.001f, hkpCompressedMeshShape::MATERIAL_SINGLE_VALUE_PER_CHUNK); // add geometries to compressedMeshShape for (vector<hkGeometry>::iterator geoIter = geometryMap.begin(); geoIter != geometryMap.end(); geoIter++) { size_t matIdx(0); // determine material index material = (SkyrimHavokMaterial) geoIter->m_triangles[0].m_material; // material already known? for (matIdx=0; matIdx < tMtrlVec.size(); ++matIdx) { if (tMtrlVec[matIdx].skyrimMaterial == material) break; } // add new material? if (matIdx >= tMtrlVec.size()) { bhkCMSDMaterial tChunkMat; // create single material tChunkMat.skyrimMaterial = material; tChunkMat.skyrimLayer = pRigidBody->GetSkyrimLayer(); // add material to list tMtrlVec.push_back(tChunkMat); } // set material index to each triangle of geometry for (int idx(0); idx < geoIter->m_triangles.getSize(); ++idx) { geoIter->m_triangles[idx].m_material = matIdx; } // add geometry to shape subPartId = shapeBuilder.beginSubpart(pCompMesh); shapeBuilder.addGeometry(*geoIter, hkMatrix4::getIdentity(), pCompMesh); shapeBuilder.endSubpart(pCompMesh); shapeBuilder.addInstance(subPartId, hkMatrix4::getIdentity(), pCompMesh); } // for (vector<hkGeometry>::iterator geoIter = geometryMap.begin(); geoIter != geometryMap.end(); geoIter++) // create welding info mci.m_enableChunkSubdivision = false; // PC version pMoppCode = hkpMoppUtility::buildCode(pCompMesh, mci); pMoppBvTree = new hkpMoppBvTreeShape(pCompMesh, pMoppCode); hkpMeshWeldingUtility::computeWeldingInfo(pCompMesh, pMoppBvTree, hkpWeldingUtility::WELDING_TYPE_TWO_SIDED); //---- Havok ---- END //---- Merge ---- START hkArray<hkpCompressedMeshShape::Chunk> chunkListHvk; vector<bhkCMSDChunk> chunkListNif = pData->GetChunks(); vector<Vector4> tVec4Vec; vector<bhkCMSDBigTris> tBTriVec; vector<bhkCMSDTransform> tTranVec; map<unsigned int, bhkCMSDMaterial> tMtrlMap; short chunkIdxNif(0); // --- modify MoppBvTree --- // set origin pMoppShape->SetMoppOrigin(Vector3(pMoppBvTree->getMoppCode()->m_info.m_offset(0), pMoppBvTree->getMoppCode()->m_info.m_offset(1), pMoppBvTree->getMoppCode()->m_info.m_offset(2))); // set scale pMoppShape->SetMoppScale(pMoppBvTree->getMoppCode()->m_info.getScale()); // set build Type pMoppShape->SetBuildType(MoppDataBuildType((Niflib::byte) pMoppCode->m_buildType)); // copy mopp data pMoppShape->SetMoppCode(vector<Niflib::byte>(pMoppBvTree->m_moppData, pMoppBvTree->m_moppData+pMoppBvTree->m_moppDataSize)); // set boundings pData->SetBoundsMin(Vector4(pCompMesh->m_bounds.m_min(0), pCompMesh->m_bounds.m_min(1), pCompMesh->m_bounds.m_min(2), pCompMesh->m_bounds.m_min(3))); pData->SetBoundsMax(Vector4(pCompMesh->m_bounds.m_max(0), pCompMesh->m_bounds.m_max(1), pCompMesh->m_bounds.m_max(2), pCompMesh->m_bounds.m_max(3))); // resize and copy bigVerts pData->SetNumBigVerts(pCompMesh->m_bigVertices.getSize()); tVec4Vec = pData->GetBigVerts(); tVec4Vec.resize(pData->GetNumBigVerts()); for (unsigned int idx(0); idx < pData->GetNumBigVerts(); ++idx) { tVec4Vec[idx].x = pCompMesh->m_bigVertices[idx](0); tVec4Vec[idx].y = pCompMesh->m_bigVertices[idx](1); tVec4Vec[idx].z = pCompMesh->m_bigVertices[idx](2); tVec4Vec[idx].w = pCompMesh->m_bigVertices[idx](3); } pData->SetBigVerts(tVec4Vec); // resize and copy bigTris pData->SetNumBigTris(pCompMesh->m_bigTriangles.getSize()); tBTriVec = pData->GetBigTris(); tBTriVec.resize(pData->GetNumBigTris()); for (unsigned int idx(0); idx < pData->GetNumBigTris(); ++idx) { tBTriVec[idx].triangle1 = pCompMesh->m_bigTriangles[idx].m_a; tBTriVec[idx].triangle2 = pCompMesh->m_bigTriangles[idx].m_b; tBTriVec[idx].triangle3 = pCompMesh->m_bigTriangles[idx].m_c; tBTriVec[idx].unknownInt1 = pCompMesh->m_bigTriangles[idx].m_material; tBTriVec[idx].unknownShort1 = pCompMesh->m_bigTriangles[idx].m_weldingInfo; } pData->SetBigTris(tBTriVec); // resize and copy transform data pData->SetNumTransforms(pCompMesh->m_transforms.getSize()); tTranVec = pData->GetChunkTransforms(); tTranVec.resize(pData->GetNumTransforms()); for (unsigned int idx(0); idx < pData->GetNumTransforms(); ++idx) { tTranVec[idx].translation.x = pCompMesh->m_transforms[idx].m_translation(0); tTranVec[idx].translation.y = pCompMesh->m_transforms[idx].m_translation(1); tTranVec[idx].translation.z = pCompMesh->m_transforms[idx].m_translation(2); tTranVec[idx].translation.w = pCompMesh->m_transforms[idx].m_translation(3); tTranVec[idx].rotation.x = pCompMesh->m_transforms[idx].m_rotation(0); tTranVec[idx].rotation.y = pCompMesh->m_transforms[idx].m_rotation(1); tTranVec[idx].rotation.z = pCompMesh->m_transforms[idx].m_rotation(2); tTranVec[idx].rotation.w = pCompMesh->m_transforms[idx].m_rotation(3); } pData->SetChunkTransforms(tTranVec); // set material list pData->SetChunkMaterials(tMtrlVec); // get chunk list from mesh chunkListHvk = pCompMesh->m_chunks; // resize nif chunk list chunkListNif.resize(chunkListHvk.getSize()); // for each chunk for (hkArray<hkpCompressedMeshShape::Chunk>::iterator pCIterHvk = pCompMesh->m_chunks.begin(); pCIterHvk != pCompMesh->m_chunks.end(); pCIterHvk++) { // get nif chunk bhkCMSDChunk& chunkNif = chunkListNif[chunkIdxNif]; // set offset => translation chunkNif.translation.x = pCIterHvk->m_offset(0); chunkNif.translation.y = pCIterHvk->m_offset(1); chunkNif.translation.z = pCIterHvk->m_offset(2); chunkNif.translation.w = pCIterHvk->m_offset(3); // force flags to fixed values chunkNif.materialIndex = pCIterHvk->m_materialInfo; chunkNif.unknownShort1 = 65535; chunkNif.transformIndex = pCIterHvk->m_transformIndex; // vertices chunkNif.numVertices = pCIterHvk->m_vertices.getSize(); chunkNif.vertices.resize(chunkNif.numVertices); for (unsigned int i(0); i < chunkNif.numVertices; ++i) { chunkNif.vertices[i] = pCIterHvk->m_vertices[i]; } // indices chunkNif.numIndices = pCIterHvk->m_indices.getSize(); chunkNif.indices.resize(chunkNif.numIndices); for (unsigned int i(0); i < chunkNif.numIndices; ++i) { chunkNif.indices[i] = pCIterHvk->m_indices[i]; } // strips chunkNif.numStrips = pCIterHvk->m_stripLengths.getSize(); chunkNif.strips.resize(chunkNif.numStrips); for (unsigned int i(0); i < chunkNif.numStrips; ++i) { chunkNif.strips[i] = pCIterHvk->m_stripLengths[i]; } // welding chunkNif.numIndices2 = pCIterHvk->m_weldingInfo.getSize(); chunkNif.indices2.resize(chunkNif.numIndices2); for (unsigned int i(0); i < chunkNif.numIndices2; ++i) { chunkNif.indices2[i] = pCIterHvk->m_weldingInfo[i]; } // next chunk ++chunkIdxNif; } // for (hkArray<hkpCompressedMeshShape::Chunk>::iterator pCIterHvk = // set modified chunk list to compressed mesh shape data pData->SetChunks(chunkListNif); //---- Merge ---- END return true; }
bool CollisionImport::ImportRigidBody(bhkRigidBodyRef body, INode* node) { if (body == NULL) return false; int lyr = body->GetLayer(); //body->GetLayerCopy(lyr); int msys = body->GetMotionSystem(); int qtype = body->GetQualityType(); float mass = body->GetMass(); float lindamp = body->GetLinearDamping(); float angdamp = body->GetAngularDamping(); float frict = body->GetFriction(); float resti = body->GetRestitution(); float maxlinvel = body->GetMaxLinearVelocity(); float maxangvel = body->GetMaxAngularVelocity(); float pendepth = body->GetPenetrationDepth(); Vector3 center = TOVECTOR3(body->GetCenter()); // Update node npSetProp(node, NP_HVK_LAYER, lyr); //npSetProp(node, NP_HVK_MATERIAL, mtl); npSetProp(node, NP_HVK_MOTION_SYSTEM, msys); npSetProp(node, NP_HVK_QUALITY_TYPE, qtype); npSetProp(node, NP_HVK_MASS, mass); npSetProp(node, NP_HVK_LINEAR_DAMPING, lindamp); npSetProp(node, NP_HVK_ANGULAR_DAMPING, angdamp); npSetProp(node, NP_HVK_FRICTION, frict); npSetProp(node, NP_HVK_RESTITUTION, resti); npSetProp(node, NP_HVK_MAX_LINEAR_VELOCITY, maxlinvel); npSetProp(node, NP_HVK_MAX_ANGULAR_VELOCITY, maxangvel); npSetProp(node, NP_HVK_PENETRATION_DEPTH, pendepth); npSetProp(node, NP_HVK_CENTER, center); npSetCollision(node, true); return true; }
/*---------------------------------------------------------------------------*/ bhkShapeRef NifCollisionUtility::convertCollPackedNiTriStrips(bhkPackedNiTriStripsShapeRef pShape, bhkMoppBvTreeShapeRef pMoppShape, bhkRigidBodyRef pRigidBody, string fileNameCollTmpl) { bhkShapeRef pShapeOut(pShape); vector<hkGeometry> geometryMap; vector<Matrix44> transformAry; // get geometries from PackedNiTriStrips getGeometryFromPackedNiTriStrips(pShape, geometryMap, transformAry); // geometry found? => create collision data if (!geometryMap.empty()) { NiNodeRef pRootTemplate(DynamicCast<BSFadeNode>(ReadNifTree((const char*) fileNameCollTmpl.c_str()))); // get template if (pRootTemplate != NULL) { bhkCollisionObjectRef pCollNodeTmpl(DynamicCast<bhkCollisionObject>(pRootTemplate->GetCollisionObject())); // bhkCollisionObject found if (pCollNodeTmpl != NULL) { // parse collision node subtrees and correct targets bhkRigidBodyRef pRigidBody(DynamicCast<bhkRigidBody>(pCollNodeTmpl->GetBody())); // bhkRigidBody found if (pRigidBody != NULL) { bhkMoppBvTreeShapeRef pTmplMopp(DynamicCast<bhkMoppBvTreeShape>(pRigidBody->GetShape())); // bhkMoppBvTreeShape found if (pTmplMopp != NULL) { bhkCompressedMeshShapeRef pTmplCShape(DynamicCast<bhkCompressedMeshShape>(pTmplMopp->GetShape())); // bhkCompressedMeshShape found if (pTmplCShape != NULL) { bhkCompressedMeshShapeDataRef pData(pTmplCShape->GetData()); // bhkCompressedMeshShapeData found if (pData != NULL) { // set bhkCompressedMeshShape to existing bhkMoppBvTreeShape pTmplMopp->SetShape (NULL); pMoppShape->SetShape(pTmplCShape); // fill in Havok data into Nif structures injectCollisionData(geometryMap, pMoppShape, pData, pRigidBody); // set result shape pShapeOut = pTmplCShape; } // if (pData != NULL) } // if (pTmplCShape != NULL) } // if (pTmplMopp != NULL) } // if (pRigidBody != NULL) } // if (pCollNodeTmpl == NULL) } // if (pRootTemplate != NULL) } // if (!geometryMap.empty()) return pShapeOut; }
void HavokImport::createRagdollRigidBody(INode* n, INode* parent, INode* ragdollParent, bhkRigidBodyRef rbody) { const int MaxChar = 512; char buffer[MaxChar]; //TSTR name(A2THelper(buffer, parent->GetName().c_str(), _countof(buffer))); n->SetName(FormatText(TEXT("Ragdoll_%s"), parent->GetName())); Object *pObj = n->GetObjectRef(); IDerivedObject *dobj = nullptr; if (n->SuperClassID() == GEN_DERIVOB_CLASS_ID) dobj = static_cast<IDerivedObject*>(pObj); else { dobj = CreateDerivedObject(pObj); } MotionSystem msys = rbody->GetMotionSystem(); //? MotionQuality qtype = rbody->GetQualityType(); float mass = rbody->GetMass(); float lindamp = rbody->GetLinearDamping(); float angdamp = rbody->GetAngularDamping(); float frict = rbody->GetFriction(); float resti = rbody->GetRestitution(); float maxlinvel = rbody->GetMaxLinearVelocity(); float maxangvel = rbody->GetMaxAngularVelocity(); float pendepth = rbody->GetPenetrationDepth(); InertiaMatrix im = rbody->GetInertia(); Modifier* rbMod = (Modifier*)CreateInstance(OSM_CLASS_ID, HK_RIGIDBODY_MODIFIER_CLASS_ID); if (IParamBlock2* rbParameters = rbMod->GetParamBlockByID(PB_RB_MOD_PBLOCK)) { //These are fundamental parameters rbParameters->SetValue(PA_RB_MOD_MASS, 0, mass, 0); rbParameters->SetValue(PA_RB_MOD_RESTITUTION, 0, resti, 0); rbParameters->SetValue(PA_RB_MOD_FRICTION, 0, frict, 0); rbParameters->SetValue(PA_RB_MOD_INERTIA_TENSOR, 0, Point3(im[0][0],im[1][1],im[2][2]), 0); rbParameters->SetValue(PA_RB_MOD_LINEAR_DAMPING, 0, lindamp, 0); rbParameters->SetValue(PA_RB_MOD_CHANGE_ANGULAR_DAMPING, 0, angdamp, 0); rbParameters->SetValue(PA_RB_MOD_MAX_LINEAR_VELOCITY, 0, maxlinvel, 0); rbParameters->SetValue(PA_RB_MOD_MAX_ANGULAR_VELOCITY, 0, maxangvel, 0); rbParameters->SetValue(PA_RB_MOD_ALLOWED_PENETRATION_DEPTH, 0, pendepth, 0); rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_FIXED, 0); rbParameters->SetValue(PA_RB_MOD_SOLVER_DEACTIVATION, 0, SD_LOW, 0); rbParameters->SetValue(PA_RB_MOD_DEACTIVATOR_TYPE, 0, DT_LOW, 0); /*body->SetMotionSystem(MotionSystem::MO_SYS_BOX); body->SetDeactivatorType(DeactivatorType::DEACTIVATOR_NEVER); body->SetSolverDeactivation(SolverDeactivation::SOLVER_DEACTIVATION_LOW); body->SetQualityType(MO_QUAL_FIXED);*/ /*switch (qtype) { case MO_QUAL_INVALID: break; case MO_QUAL_FIXED: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_FIXED, 0); break; case MO_QUAL_KEYFRAMED: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_KEYFRAMED, 0); break; case MO_QUAL_DEBRIS: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_DEBRIS, 0); break; case MO_QUAL_MOVING: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_MOVING, 0); break; case MO_QUAL_CRITICAL: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_CRITICAL, 0); break; case MO_QUAL_BULLET: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_BULLET, 0); break; case MO_QUAL_USER: break; case MO_QUAL_CHARACTER: break; case MO_QUAL_KEYFRAMED_REPORT: rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_KEYFRAMED_REPORTING, 0); break; }*/ } //Link Rigid Body to parent Rigid Body ICustAttribContainer* cc = rbMod->GetCustAttribContainer(); if (!cc) { rbMod->AllocCustAttribContainer(); cc = rbMod->GetCustAttribContainer(); } CustAttrib* c = (CustAttrib*)CreateInstance(CUST_ATTRIB_CLASS_ID, Class_ID(0x6e663460, 0x32682c72)); IParamBlock2* custModParameters = c->GetParamBlock(0); custModParameters->SetValue(0, 0, parent, 0); cc->InsertCustAttrib(0, c); Modifier* constraintMod = nullptr; vector< bhkSerializableRef > constraints = rbody->GetConstraints(); //Rigid Body constraints if (ragdollParent) { for (vector< bhkSerializableRef >::iterator it = constraints.begin(); it != constraints.end(); ) { bhkConstraintRef constraint = bhkConstraintRef(*it); if (constraint->IsDerivedType(bhkLimitedHingeConstraint::TYPE)) { bhkLimitedHingeConstraintRef limitedHingeConstraint = bhkLimitedHingeConstraintRef(*it); LimitedHingeDescriptor lh = limitedHingeConstraint->GetLimitedHinge(); constraintMod = (Modifier*)CreateInstance(OSM_CLASS_ID, HK_CONSTRAINT_HINGE_CLASS_ID); if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_NODE, 0, ragdollParent, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_ROTATION_LOCK, 0, 0, 0); Point3 origin(0, 0, 0); Matrix3 parentRotation(TOPOINT3(lh.perp2AxleInA1), TOPOINT3(lh.perp2AxleInA2), TOPOINT3(lh.axleA), origin); Matrix3 childRotation(TOPOINT3(lh.perp2AxleInB1), TOPOINT3(lh.perp2AxleInB2), TOPOINT3(lh.axleB), origin); //Matrix3 parentRotation(true); //MatrixFromNormal(TOPOINT3(lh.axleA), parentRotation); //Matrix3 childRotation(true); //MatrixFromNormal(TOPOINT3(lh.axleB), childRotation); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, 0); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_HINGE_MOD_PBLOCK)) { constraintParameters->SetValue(PA_HINGE_MOD_IS_LIMITED, 0, 1, 0); constraintParameters->SetValue(PA_HINGE_MOD_LIMIT_MIN, 0, TODEG(lh.minAngle), 0); constraintParameters->SetValue(PA_HINGE_MOD_LIMIT_MAX, 0, TODEG(lh.maxAngle), 0); constraintParameters->SetValue(PA_HINGE_MOD_MAX_FRICTION_TORQUE, 0, lh.maxFriction, 0); // constraintParameters->SetValue(PA_HINGE_MOD_MOTOR_TYPE, 0, lh.motor., 0); } } else if (constraint->IsDerivedType(bhkRagdollConstraint::TYPE)) { bhkRagdollConstraintRef ragdollConstraint = bhkRagdollConstraintRef(*it); RagdollDescriptor rag = ragdollConstraint->GetRagdoll(); constraintMod = (Modifier*)CreateInstance(OSM_CLASS_ID, HK_CONSTRAINT_RAGDOLL_CLASS_ID); if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_NODE, 0, ragdollParent, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_ROTATION_LOCK, 0, 0, 0); //TOVECTOR3(rag.twistA); //MatrixFromNormal(TOPOINT3(rag.twistA), parentRotation); Point3 origin(0,0,0); Matrix3 parentRotation(TOPOINT3(rag.planeA),TOPOINT3(rag.motorA),TOPOINT3(rag.twistA),origin); //TOVECTOR3(rag.twistB); //MatrixFromNormal(TOPOINT3(rag.twistB), childRotation); Matrix3 childRotation(TOPOINT3(rag.planeB), TOPOINT3(rag.motorB), TOPOINT3(rag.twistB), origin); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_TRANSLATION, 0, TOPOINT3(rag.pivotB), 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_TRANSLATION, 0, TOPOINT3(rag.pivotA), 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, 0); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_RAGDOLL_MOD_PBLOCK)) { constraintParameters->SetValue(PA_RAGDOLL_MOD_CONE_ANGLE, 0, TODEG(rag.coneMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_PLANE_MIN, 0, TODEG(rag.planeMinAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_PLANE_MAX, 0, TODEG(rag.planeMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_TWIST_MIN, 0, TODEG(rag.twistMinAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_TWIST_MAX, 0, TODEG(rag.twistMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_MAX_FRICTION_TORQUE, 0, rag.maxFriction, 0); } } else if (constraint->IsDerivedType(bhkMalleableConstraint::TYPE)) { bhkMalleableConstraintRef malleableConstraint = bhkMalleableConstraintRef(*it); if (malleableConstraint->GetConstraintType() == (unsigned int)2) { LimitedHingeDescriptor lh = malleableConstraint->GetLimitedHinge(); constraintMod = (Modifier*)CreateInstance(OSM_CLASS_ID, HK_CONSTRAINT_HINGE_CLASS_ID); if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_NODE, 0, ragdollParent, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_ROTATION_LOCK, 0, 0, 0); Point3 origin(0, 0, 0); Matrix3 parentRotation(TOPOINT3(lh.perp2AxleInA1), TOPOINT3(lh.perp2AxleInA2), TOPOINT3(lh.axleA), origin); Matrix3 childRotation(TOPOINT3(lh.perp2AxleInB1), TOPOINT3(lh.perp2AxleInB2), TOPOINT3(lh.axleB), origin); //Matrix3 parentRotation(true); //MatrixFromNormal(TOPOINT3(lh.axleA), parentRotation); //Matrix3 childRotation(true); //MatrixFromNormal(TOPOINT3(lh.axleB), childRotation); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, 0); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_HINGE_MOD_PBLOCK)) { constraintParameters->SetValue(PA_HINGE_MOD_IS_LIMITED, 0, 1, 0); constraintParameters->SetValue(PA_HINGE_MOD_LIMIT_MIN, 0, TODEG(lh.minAngle), 0); constraintParameters->SetValue(PA_HINGE_MOD_LIMIT_MAX, 0, TODEG(lh.maxAngle), 0); constraintParameters->SetValue(PA_HINGE_MOD_MAX_FRICTION_TORQUE, 0, lh.maxFriction, 0); // constraintParameters->SetValue(PA_HINGE_MOD_MOTOR_TYPE, 0, lh.motor., 0); } } else if (malleableConstraint->GetConstraintType() == (unsigned int)7) { RagdollDescriptor rag = malleableConstraint->GetRagdoll(); constraintMod = (Modifier*)CreateInstance(OSM_CLASS_ID, HK_CONSTRAINT_RAGDOLL_CLASS_ID); if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_NODE, 0, ragdollParent, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_ROTATION_LOCK, 0, 0, 0); //TOVECTOR3(rag.twistA); //MatrixFromNormal(TOPOINT3(rag.twistA), parentRotation); Point3 origin(0, 0, 0); Matrix3 parentRotation(TOPOINT3(rag.planeA), TOPOINT3(rag.motorA), TOPOINT3(rag.twistA), origin); //TOVECTOR3(rag.twistB); //MatrixFromNormal(TOPOINT3(rag.twistB), childRotation); Matrix3 childRotation(TOPOINT3(rag.planeB), TOPOINT3(rag.motorB), TOPOINT3(rag.twistB), origin); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_TRANSLATION, 0, TOPOINT3(rag.pivotB), 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_TRANSLATION, 0, TOPOINT3(rag.pivotA), 0); constraintParameters->SetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, 0); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_RAGDOLL_MOD_PBLOCK)) { constraintParameters->SetValue(PA_RAGDOLL_MOD_CONE_ANGLE, 0, TODEG(rag.coneMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_PLANE_MIN, 0, TODEG(rag.planeMinAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_PLANE_MAX, 0, TODEG(rag.planeMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_TWIST_MIN, 0, TODEG(rag.twistMinAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_TWIST_MAX, 0, TODEG(rag.twistMaxAngle), 0); constraintParameters->SetValue(PA_RAGDOLL_MOD_MAX_FRICTION_TORQUE, 0, rag.maxFriction, 0); } } } ++it; } } dobj->SetAFlag(A_LOCK_TARGET); dobj->AddModifier(rbMod); if (constraintMod) dobj->AddModifier(constraintMod); dobj->ClearAFlag(A_LOCK_TARGET); n->SetObjectRef(dobj); }