Esempio n. 1
0
/*---------------------------------------------------------------------------*/
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;
}
Esempio n. 3
0
/*---------------------------------------------------------------------------*/
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);

}