void OrientConstRotation::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
{
	if (firstTimeFlag) {
		Point3 trans, scaleP;
		Quat quat;
		Matrix3 tempMat(1);
		// CAL-9/26/2002: in absolute mode the value could be un-initialized (random value).
		if (method == CTRL_RELATIVE) tempMat = *(Matrix3*)val;
		DecomposeMatrix(tempMat, trans, quat, scaleP);
		baseRotQuatWorld = baseRotQuatLocal * quat;
		baseRotQuatWorld.Normalize();
		firstTimeFlag = 0;
	}
	if (!ivalid.InInterval(t)) {
		DbgAssert(val != NULL);
		Update(t);
	}
	valid &= ivalid;

			 
	if (method==CTRL_RELATIVE) {
		Interval iv;

		if (IsLocal()){			// From Update, I'm getting target_local_TM in curRot
			Matrix3 *mat = (Matrix3*)val; // this is source_Parent_TM
			Quat q = curRot;			// this is target_local_TM
			PreRotateMatrix(*mat, q);	// source_world_TM = source_Parent_TM * target_local_TM 
		}
		
		else { 		// i.e., WorldToWorld: from Update, I'm getting target_world_TM in curRot
			int ct = pblock->Count(orientation_target_list);;
			if (ct < 1){
				Matrix3 *mat = (Matrix3*)val;
				Quat q = curRot;
				PreRotateMatrix(*mat, q);
			}
			else{
				Matrix3 *mat = (Matrix3*)val; // this is source_Parent_TM
				// CAL-06/24/02: preserve all components and replace with the new orientation.
				AffineParts ap;
				decomp_affine( *mat, &ap );
				ap.q = curRot;				// target world rotation
				comp_affine( ap, *mat );
				// CAL-06/24/02: this only preserve the translation component
				// Point3 tr;
				// tr = mat->GetTrans();
				// mat->IdentityMatrix();
				// Quat q = curRot;			// this is target_world_TM
				// q.MakeMatrix(*mat);
				// mat->SetTrans(tr);
			}
		}
	} 
	else {
		*((Quat*)val) = curRot;
	}
//		RedrawListbox(GetCOREInterface()->GetTime());
}
Ejemplo n.º 2
0
Matrix3 plMaxNodeBase::GetWorldToParent(TimeValue t)
{
    // This may look back-ass-ward, but that's only because it
    // is. If we've got inheritance filtering on, then our localtoworld
    // is no longer parentl2w * l2p, because we'll be ignoring
    // some of our parent's transform. More precisely, we'll be
    // clobbering parts of the product of our parent's current transform
    // and our current local to parent. So we're going to calculate
    // a parent to world transform here that would get us to the
    // right point and orientation in space, even though it has
    // little or nothing to do with our parent's real transform.
    // Note that we only go through this charade if we've got
    // filtering of inheritance active for this node.
    plMaxNodeBase* parent = (plMaxNodeBase*)GetParentNode();
    if( !GetFilterInherit() )
        return parent->GetWorldToLocal(t);

    // l2w = l2p * parentL2W
    // l2w * parentW2L = l2p
    // parentW2L = w2l * l2p
    Point3 pos;
    float rot[4];
    ScaleValue scl;
    Interval posInv;
    Interval rotInv;
    Interval sclInv;

    Matrix3Indirect parentMatrix(parent->GetNodeTM(t));

    TMComponentsArg cmpts(&pos, &posInv, rot, &rotInv, &scl, &sclInv);
    GetTMController()->GetLocalTMComponents(t, cmpts, parentMatrix);

    Quat q;
    if( cmpts.rotRep == TMComponentsArg::RotationRep::kQuat )
        q = Quat(rot);
    else
        EulerToQuat(rot, q, cmpts.rotRep);

    Matrix3 l2p(true);
    l2p.PreTranslate(pos);
    PreRotateMatrix(l2p, q);
    l2p.PreScale(scl.s);
    PreRotateMatrix(l2p, scl.q);

    Matrix3 w2l = GetWorldToLocal(t);

    return w2l * l2p;
}
Ejemplo n.º 3
0
void SlaveRotationControl::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
   {
   if ( (sub == NULL) || (!masterPresent) || (blockID.Count()==0))
      {
      Quat f;
      f.Identity();
      if (method == CTRL_ABSOLUTE)
         {
         Quat *v = ((Quat*)val);
         *v = f;
         return;
         }
      else
         {
         Matrix3 *v = ((Matrix3*)val);
         PreRotateMatrix(*v,f);
         return;           
         }
      }

//copy keys into scratch control
   if (scratchControl == NULL)
      {
      UpdateSlave();
      }

   if (master)
      master->GetValue3(scratchControl,t,val,valid,blockID,subID,range,method);
   }
Ejemplo n.º 4
0
void EulerExposeControl::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
{
	Update(t);
	valid  &= ivalid; //only for the current time
	if (method==CTRL_RELATIVE)
	{	
		Matrix3 *mat = (Matrix3*)val;       
		PreRotateMatrix(*mat,curVal); 
	}
	else
		*((Quat*)val) = curVal;
}
Ejemplo n.º 5
0
void RotationMC::GetValueLive(TimeValue t,void *val, GetSetMethod method)
	{
	Point3 pt = base;
	for (int i=0; i<3; i++) if (bind[i]) pt[i] += DegToRad(bind[i]->Eval(t));
	Quat q;
	EulerToQuat(pt,q);
	if (method==CTRL_ABSOLUTE) {		
		*((Quat*)val) = q;
	} else {
		Matrix3 *tm = (Matrix3*)val;		
		PreRotateMatrix(*tm,q);		
		}
	}
Ejemplo n.º 6
0
void XsiExp::DumpMatrix3( Matrix3 * m, int indentLevel)
{
	Point3 row;
	TSTR indent = GetIndent(indentLevel);

  // swap y and z; max to soft correction
  decomp_affine( *m, &affine);
  // translate
  float temp = affine.t.z;
  affine.t.z = -affine.t.y;
  affine.t.y = temp;

  // rotate
  AngAxis aa( affine.q);
  temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  affine.q.Set(aa);

  // scale
  aa.Set( affine.u);
  temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  affine.u.Set( aa);
  temp = affine.k.z;
  affine.k.z = affine.k.y;
  affine.k.y = temp;

  Matrix3 matrix(1);
  matrix.PreTranslate(affine.t);
  PreRotateMatrix(matrix, affine.q);
  
	row = matrix.GetRow(0);
	fprintf(pStream,"%s %.6f,%.6f,%.6f,0.000000,\n", indent.data(), row.x, row.y, row.z);
	row = matrix.GetRow(1);
	fprintf(pStream,"%s %.6f,%.6f,%.6f,0.000000,\n", indent.data(), row.x, row.y, row.z);
	row = matrix.GetRow(2);
	fprintf(pStream,"%s %.6f,%.6f,%.6f,0.000000,\n", indent.data(), row.x, row.y, row.z);
	row = matrix.GetRow(3);
	fprintf(pStream,"%s %.6f,%.6f,%.6f,1.000000;;\n", indent.data(), row.x, row.y, row.z);
}
Ejemplo n.º 7
0
void PivotSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t)
{	
	// This snap computes the bounding box points of a node as 
	// well as the pivot point

	//local copy of the cursor position
	Point2 fp = Point2((float)p->x, (float)p->y);

	//In this snap mode we actually need to get a pointer to the node so that we 
	// can check for WSM's and compute the pivot point
	INode *inode = theman->GetNode();
	Matrix3 atm(1); //This will hold the nodes tm before WSMs

	//See if this guys has any spacewarps applied
	BOOL wsm = (BOOL) inode->GetProperty(PROPID_HAS_WSM);

	//If it does then we'll need to get a meaningful tm as follows
	if(wsm)
		atm = inode->GetObjTMBeforeWSM(t);

	//get the node's bounding box
	Box3 box;
	box.Init();
	pobj->GetDeformBBox(t, box, NULL );

	if(EssentiallyEmpty(box))
		pobj->GetLocalBoundBox(t, inode, theman->GetVpt() , box);

		//We need a hitmesh which shows the bounding box of the node
	//This automatic variable gets passed to the hitmesh copy constructor
	// in every case
	HitMesh thehitmesh, *phitmesh;
	thehitmesh.setNumVerts(8);
	for(int jj = 0;jj<8;++jj)
		thehitmesh.setVert(jj,box[jj]);


	BOOL got_one= FALSE;

	//Compute all the hit point candidates
	if(	GetActive(PIV_SUB))
	{
		got_one = FALSE;
		Point3 *pivpt;

		//JH 10/02/01
		//DID 296059
		Matrix3 tm(1);
		Point3 pos = inode->GetObjOffsetPos();
		tm.PreTranslate(pos);
		Quat quat = inode->GetObjOffsetRot();
		PreRotateMatrix(tm, quat);
		ScaleValue scale = inode->GetObjOffsetScale();
		ApplyScaling(tm, scale);
		Matrix3 InvTm = Inverse(tm);



		//JH 10/02/01
		//atm contains the identity normally, or the node TM before spacewarps, when space warps are applied
		//We're computing a point relative to the node TM, so in the former case the inverse of
		//the object offset pos is what we want. In the latter (when the node TM is identtity, we must add
		//in the node TM before WSM.
		pivpt = new Point3(atm.GetTrans() + InvTm.GetTrans());

		//Make a hitmesh
		phitmesh = new HitMesh(thehitmesh);

		//now register a hit with the osnap manager
		theman->RecordHit(new OsnapHit(*pivpt, this, PIV_SUB, phitmesh));
	}

	if(	GetActive(BBOX_SUB))
	{

		//set up our highlight mesh
		for(int ii = 0;ii<8;++ii)
		{
			phitmesh = new HitMesh(thehitmesh);

			theman->RecordHit(new OsnapHit(box[ii], this, BBOX_SUB, phitmesh));
		}
	}


};
Ejemplo n.º 8
0
void XsiExp::ExportMesh( INode * node, TimeValue t, int indentLevel)
{
	ObjectState os = node->EvalWorldState(t);
	if (!os.obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID)
  {
		return; // Safety net. This shouldn't happen.
	}
	BOOL needDel;
	TriObject * tri = GetTriObjectFromNode(node, t, needDel);
	if (!tri)
  {
    // no tri object
		return;
	}
  // prepare mesh
  Mesh * mesh = &tri->GetMesh();
  mesh->buildNormals();

  // object offset matrix; apply to verts
  // swap y and z; max to soft correction
  Matrix3 matrix(1);
  //  translate
  matrix.PreTranslate( Point3( node->GetObjOffsetPos().x, node->GetObjOffsetPos().z, -node->GetObjOffsetPos().y));

  // rotate
  AngAxis aa( node->GetObjOffsetRot());
  float temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  PreRotateMatrix(matrix, Quat( aa));

  // scale
  ScaleValue scale = node->GetObjOffsetScale();
  aa.Set( scale.q);
  temp = aa.axis.z;
  aa.axis.z = -aa.axis.y;
  aa.axis.y = temp;
  scale.q.Set( aa);
  temp = scale.s.z;
  scale.s.z = scale.s.y;
  scale.s.y = temp;
  ApplyScaling(matrix, scale);

  // apply root transform
  matrix = matrix * topMatrix;
  // only rotation for normals
  AffineParts ap;
  Matrix3 rotMatrix(1);
  decomp_affine( matrix, &ap);
  PreRotateMatrix( rotMatrix, ap.q);

  // set winding order
	int vx1 = 0, vx2 = 1, vx3 = 2;
	if (TMNegParity( node->GetNodeTM(GetStaticFrame())) != TMNegParity( matrix) )
  {
    // negative scaling; invert winding order and normal rotation
		vx1 = 2;	vx2 = 1;	vx3 = 0;
    rotMatrix = rotMatrix * Matrix3( Point3(-1,0,0), Point3(0,-1,0), Point3(0,0,-1), Point3(0,0,0));
	}

  // header
	TSTR indent = GetIndent(indentLevel+1);
	fprintf(pStream, "%s%s %s {\n",indent.data(), "Mesh", FixupName(node->GetName()));

  // write number of verts
  int numLoop = mesh->getNumVerts();
	fprintf(pStream, "%s\t%d;\n",indent.data(), numLoop);

  // write verts
	for (int i = 0; i < numLoop; i++)
  {
		Point3 v = mesh->verts[i];
		float temp = v.z;
    v.z = -v.y;
    v.y = temp;
		v = matrix * v;
		fprintf(pStream, "%s\t%.6f;%.6f;%.6f;%s\n", indent.data(), v.x, v.y, v.z, 
      i == numLoop - 1 ? ";\n" : ",");
	}
  // write number of faces
  numLoop = mesh->getNumFaces();
  fprintf(pStream, "%s\t%d;\n", indent.data(), numLoop);

  // write faces
	for (i = 0; i < numLoop; i++)
  {
		fprintf(pStream, "%s\t3;%d,%d,%d;%s\n",
			indent.data(),
			mesh->faces[i].v[vx1],
			mesh->faces[i].v[vx2],
			mesh->faces[i].v[vx3], 
      i == numLoop - 1 ? ";\n" : ",");
	}

  // face materials
	Mtl * nodeMtl = node->GetMtl();
  int numMtls = !nodeMtl || !nodeMtl->NumSubMtls() ? 1 : nodeMtl->NumSubMtls();

	// write face material list header	
	fprintf(pStream, "%s\tMeshMaterialList {\n", indent.data());
  // write number of materials
	fprintf(pStream, "%s\t\t%d;\n", indent.data(), numMtls);
  // write number of faces
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

  // write face material indices (1 for each face)
  for (i = 0; i < numLoop; i++)
  {
    int index = numMtls ? mesh->faces[i].getMatID() % numMtls : 0;
		fprintf(pStream,"%s\t\t%d%s\n",
			indent.data(),
      index,
      i == numLoop - 1 ? ";\n" : ",");
	}

  // write the materials
  ExportMaterial( node, indentLevel+2);

  // verts close brace
	fprintf(pStream, "%s\t}\n\n",indent.data());

  // write normals header
	fprintf(pStream, "%s\t%s {\n", indent.data(), "SI_MeshNormals");
	// write number of normals
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop * 3);

  // write normals (3 for each face)
	for (i = 0; i < numLoop; i++)
  {
		Face * f = &mesh->faces[i];
		int vert = f->getVert(vx1);

		Point3 vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    float temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z);

		vert = f->getVert(vx2);
		vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z);
    
		vert = f->getVert(vx3);
		vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert));
    temp = vn.z;
    vn.z = -vn.y;
    vn.y = temp;
		vn = rotMatrix * vn;
		fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;%s\n", indent.data(), vn.x, vn.y, vn.z,
      i == numLoop - 1 ? ";\n" : ",");
	}
  // write number of faces
  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

  // write faces
  for (i = 0; i < numLoop; i++)
  {
	  fprintf(pStream, "%s\t\t%d;3;%d,%d,%d;%s\n",
		  indent.data(),
      i,
      i * 3 + vx1, i * 3 + vx2, i * 3 + vx3,
      i == numLoop - 1 ? ";\n" : ",");
  }
  // normals close brace
	fprintf(pStream, "%s\t}\n\n",indent.data());

	// texcoords
	if (nodeMtl && mesh && (nodeMtl->Requirements(-1) & MTLREQ_FACEMAP))
  {
    // facemapping
    numLoop = mesh->getNumFaces() * 3;

    // write texture coords header
    fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data());
    // write number of texture coords
    fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

    // write texture coords
	  for (int i = 0; i < numLoop; i++)
    {
		  Point3 tv[3];
		  Face * f = &mesh->faces[i];
		  make_face_uv( f, tv);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;,\n",  indent.data(), tv[0].x, tv[0].y);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;,\n",  indent.data(), tv[1].x, tv[1].y);
		  fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv[2].x, tv[2].y,
        i == numLoop - 1 ? ";\n" : ",");
	  }
    // write number of faces
    numLoop = mesh->getNumFaces();
	  fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

    // write faces
	  for (i = 0; i < numLoop; i++)
    {
		  fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n",
			  indent.data(),
			  i,
			  mesh->tvFace[i].t[vx1],
			  mesh->tvFace[i].t[vx2],
			  mesh->tvFace[i].t[vx3],
        i == numLoop - 1 ? ";\n" : ",");
	  }
    // texture coords close brace
	  fprintf(pStream, "%s\t}\n\n", indent.data());
  }
  else
  {
		numLoop = mesh->getNumTVerts();

		if (numLoop)
    {
      // write texture coords header
  		fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data());
      // write number of texture coords
  		fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

      // write texture coords
			for (i = 0; i < numLoop; i++)
      {
				UVVert tv = mesh->tVerts[i];
				fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv.x, tv.y,
        i == numLoop - 1 ? ";\n" : ",");
			}
      // write number of faces
      numLoop = mesh->getNumFaces();
			fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop);

      // write faces
			for (i = 0; i < numLoop; i++)
      {
				fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n",
					indent.data(),
					i,
					mesh->tvFace[i].t[vx1],
					mesh->tvFace[i].t[vx2],
					mesh->tvFace[i].t[vx3],
          i == numLoop - 1 ? ";\n" : ",");
			}
      // texture coords close brace
			fprintf(pStream, "%s\t}\n\n", indent.data());
		}
  }

/*
	// Export color per vertex info
	if (GetIncludeVertexColors()) {
		int numCVx = mesh->numCVerts;

		fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVERTEX, numCVx);
		if (numCVx) {
			fprintf(pStream,"%s\t%s {\n",indent.data(), ID_MESH_CVERTLIST);
			for (i=0; i<numCVx; i++) {
				Point3 vc = mesh->vertCol[i];
				fprintf(pStream, "%s\t\t%s %d\t%s\n",indent.data(), ID_MESH_VERTCOL, i, Format(vc));
			}
			fprintf(pStream,"%s\t}\n",indent.data());
			
			fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVFACES, mesh->getNumFaces());

			fprintf(pStream, "%s\t%s {\n",indent.data(), ID_MESH_CFACELIST);
			for (i=0; i<mesh->getNumFaces(); i++) {
				fprintf(pStream,"%s\t\t%s %d\t%d\t%d\t%d\n",
					indent.data(),
					ID_MESH_CFACE, i,
					mesh->vcFace[i].t[vx1],
					mesh->vcFace[i].t[vx2],
					mesh->vcFace[i].t[vx3]);
			}
			fprintf(pStream, "%s\t}\n",indent.data());
		}
	}
*/

  // Mesh close brace
	fprintf(pStream, "%s}\n",indent.data());
  
  // dispose of tri object
  if (needDel)
  {
		delete tri;
	}
}
Ejemplo n.º 9
0
/*
  Transfer the max Node's mesh to PhysX unit and store it.
*/
void ccMaxNode::SyncFromMaxMesh()
{
	//MaxMsgBox(NULL, _T("SyncFromMaxMesh"), _T("Error"), MB_OK);

	ShapeType           = NX_SHAPE_MESH;
	const TimeValue  t  = ccMaxWorld::MaxTime();

	Matrix3 tm = MaxINode->GetNodeTM(t);
	NodePosInPhysics = tm.GetRow(3);
	NodePosInPhysics = ccMaxWorld::ChangeToPhysXUnit(NodePosInPhysics);

	ScaleValue sv = MaxINode->GetObjOffsetScale();
	bool objectIsScaled = PivotScaled(sv);
	//if(objectIsScaled)
	//	RemovePivotScale(MaxINode);

	//------------------------
	MaxNodeTM = MaxINode->GetNodeTM(t);
	// get pivot TM
	MaxPivotTM.IdentityMatrix();
	MaxPivotTM.SetTrans(MaxINode->GetObjOffsetPos()); 
	PreRotateMatrix(MaxPivotTM, MaxINode->GetObjOffsetRot()); 
	ApplyScaling(MaxPivotTM, MaxINode->GetObjOffsetScale());


	
	
//	char blaat[1024];
//	sprintf(blaat,"MaxPivotTM.MaxPivotTM.GetTrans()=(%f,%f,%f)",MaxPivotTM.GetTrans().x,MaxPivotTM.GetTrans().y,MaxPivotTM.GetTrans().z);
//	MaxMsgBox(NULL, _T(blaat), _T("Error"), MB_OK);

	// GetObjectTM() = MaxPivotTM * MaxNodeTM
	MaxNodeObjectTM = MaxINode->GetObjectTM(t);
	//-----------------------------------------------------------------------------------------------
	// object might be modified by world space modifiers. We need a solution in future for this case.
	bool isWorldSpace = MaxINode->GetObjTMAfterWSM(t).IsIdentity(); 
	//-----------------------------------------------------------------------------------------------
	Matrix3 PhysicsNodeTM = ccMaxWorld::ChangeToPhysXUnit(MaxNodeObjectTM);
	// get scale TM
	// PhysicsNodeTM == PhysicsNodeScaleTM * PhysicsNodePoseTM
	Point3 maxNodeScale = ccMaxWorld::ParseScale(PhysicsNodeTM, PhysicsNodeScaleTM, PhysicsNodePoseTM);      
	//Matrix3 right;
	//ParseMatrix(PhysicsNodePoseTM, right);
	//PhysicsNodePoseTM = right;
	//PhysicsNodeScaleTM = PhysicsNodeTM * Inverse(PhysicsNodePoseTM);
	//if(IsScaled(PhysicsNodeScaleTM))
	//	objectIsScaled = true;
	// check whether the Node's mesh is scaled equally at x/y/z
	ScaledIsUnified  = (fabs((maxNodeScale.x - maxNodeScale.z)/maxNodeScale.z) < gTolerenceEpsilon) && (fabs((maxNodeScale.y - maxNodeScale.z)/maxNodeScale.z) < gTolerenceEpsilon);
	ScaledIsUnified  = (! objectIsScaled) && ScaledIsUnified;
	//if(! ScaledIsUnified) {
	//	PhysicsNodePoseTM.IdentityMatrix();
	//	PhysicsNodePoseTM.SetRow(3, NodePosInPhysics);
	//	PhysicsNodeScaleTM = PhysicsNodeTM * Inverse(PhysicsNodePoseTM);
	//}
	PhysicsNodePoseTMInv = Inverse(PhysicsNodePoseTM);

	//gCurrentstream->printf("\nNxScaleTM = ");	MxUtils::PrintMatrix3(PhysicsNodeScaleTM); 
	//gCurrentstream->printf("\nNxPoseTM = ");	MxUtils::PrintMatrix3(PhysicsNodePoseTM); 
	//gCurrentstream->printf("\n");
	//Matrix3 t1 = PhysicsNodeScaleTM * PhysicsNodePoseTM;
	//bool e1 = (t1 == MaxNodeObjectTM);
	Object* obj   = MaxINode->EvalWorldState(t).obj;
	if (obj != NULL)
	{
		SimpleObject* so = (SimpleObject*)obj;
		Class_ID id = obj->ClassID();
		if (id == Class_ID(SPHERE_CLASS_ID, 0)) {
			ShapeType = NX_SHAPE_SPHERE;
			so->pblock->GetValue(SPHERE_RADIUS, 0, PrimaryShapePara.Radius, FOREVER);
			PrimaryShapePara.Radius *= maxNodeScale.x * ccMaxWorld::GetUnitChange();         // x/y/z is scaled with a same value
		}
		else if (id == Class_ID(BOXOBJ_CLASS_ID, 0)) {
			ShapeType = NX_SHAPE_BOX;
			so->pblock->GetValue(BOXOBJ_WIDTH , 0, PrimaryShapePara.BoxDimension[0], FOREVER);
			so->pblock->GetValue(BOXOBJ_LENGTH, 0, PrimaryShapePara.BoxDimension[1], FOREVER);
			so->pblock->GetValue(BOXOBJ_HEIGHT, 0, PrimaryShapePara.BoxDimension[2], FOREVER);
			PrimaryShapePara.BoxDimension *= (0.5f * maxNodeScale.x * ccMaxWorld::GetUnitChange());          // x/y/z is scaled with a same value     // Physics box is half the size
		}
		else if (id == CAPS_CLASS_ID) {
			ShapeType = NX_SHAPE_CAPSULE;
			int centersflag = 0;
			so->pblock->GetValue(CAPS_RADIUS , 0, PrimaryShapePara.Radius, FOREVER);
			so->pblock->GetValue(CAPS_HEIGHT , 0, PrimaryShapePara.Height, FOREVER);
			so->pblock->GetValue(CAPS_CENTERS, 0, centersflag, FOREVER);
			if(!centersflag) //there are some different ways in which you can specify a capsule in 3ds max, adjust length if "center" mode is not used
				PrimaryShapePara.Height -= PrimaryShapePara.Radius * 2.0f; 
			PrimaryShapePara.Radius *= maxNodeScale.x * ccMaxWorld::GetUnitChange();         // x/y/z is scaled with a same value
			PrimaryShapePara.Height *= maxNodeScale.x * ccMaxWorld::GetUnitChange();         // x/y/z is scaled with a same value
		}
	}
	if(! ScaledIsUnified)
		ShapeType     = NX_SHAPE_MESH;
	// Disable backface culling for cloth
	//MaxINode->BackCull(FALSE);
	// get mesh
	BOOL needDel = FALSE;
	TriObject* tri = MxUtils::GetTriObjectFromNode(MaxINode, t, needDel);
	if (tri == NULL) return;

	Mesh& mesh = tri->GetMesh();
	SimpleMesh.alloc(mesh.getNumVerts(), mesh.getNumFaces());
	//Matrix3 change = PhysicsNodeTM * Inverse(PhysicsNodePoseTM);
	for(NxU32 i = 0; i < SimpleMesh.numPoints; i++) 
	{
		Point3 tmp = mesh.verts[i] * ccMaxWorld::GetUnitChange() * PhysicsNodeScaleTM;
		((Point3*)SimpleMesh.points)[i] =  tmp;  // systemTM is unit change TM.
	}
	for(NxU32 i = 0; i < SimpleMesh.numFaces; i++) 
	{
		for(NxU32 j = 0; j < 3; j++) 
		{ 
			SimpleMesh.faces[i*3+j] = mesh.faces[i].v[j];
		}
	}
	if (needDel)
		tri->DeleteMe();
}
void HavokExport::makeHavokRigidBody(NiNodeRef parent, INode *ragdollParent, float scale) {

	this->scale = scale;

	Object *Obj = ragdollParent->GetObjectRef();

	Modifier* rbMod = nullptr;
	Modifier* shapeMod = nullptr;
	Modifier* constraintMod = nullptr;

	SimpleObject* havokTaperCapsule = nullptr;

	//get modifiers
	

	while (Obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
		IDerivedObject *DerObj = static_cast<IDerivedObject *> (Obj);
		const int nMods = DerObj->NumModifiers(); //it is really the last modifier on the stack, and not the total number of modifiers

		for (int i = 0; i < nMods; i++)
		{
			Modifier *Mod = DerObj->GetModifier(i);
			if (Mod->ClassID() == HK_RIGIDBODY_MODIFIER_CLASS_ID) {
				rbMod = Mod;
			}
			if (Mod->ClassID() == HK_SHAPE_MODIFIER_CLASS_ID) {
				shapeMod = Mod;
			}
			if (Mod->ClassID() == HK_CONSTRAINT_RAGDOLL_CLASS_ID || Mod->ClassID() == HK_CONSTRAINT_HINGE_CLASS_ID) {
				constraintMod = Mod;
			}
		}
		if (Obj->SuperClassID() == GEOMOBJECT_CLASS_ID) {
			havokTaperCapsule = (SimpleObject*)Obj;
		}
		Obj = DerObj->GetObjRef();
	}

	
	if (!rbMod) {
		throw exception(FormatText("No havok rigid body modifier found on %s", ragdollParent->GetName()));
	}
	if (!shapeMod) {
		throw exception(FormatText("No havok shape modifier found on %s", ragdollParent->GetName()));
	}

//	Object* taper = ragdollParent->GetObjectRef();
	IParamBlock2* taperParameters = Obj->GetParamBlockByID(PB_TAPEREDCAPSULE_OBJ_PBLOCK);
	float radius;
	enum
	{
		// GENERAL PROPERTIES ROLLOUT
		PA_TAPEREDCAPSULE_OBJ_RADIUS = 0,
		PA_TAPEREDCAPSULE_OBJ_TAPER,
		PA_TAPEREDCAPSULE_OBJ_HEIGHT,
		PA_TAPEREDCAPSULE_OBJ_VERSION_INTERNAL,
	};
	taperParameters->GetValue(PA_TAPEREDCAPSULE_OBJ_RADIUS, 0, radius, FOREVER);
	

	int shapeType;
	if (IParamBlock2* shapeParameters = shapeMod->GetParamBlockByID(PB_SHAPE_MOD_PBLOCK)) {
		shapeParameters->GetValue(PA_SHAPE_MOD_SHAPE_TYPE,0,shapeType,FOREVER);
	}

	//Havok Shape
	bhkShapeRef shape;

	if (shapeType == 2) {

		// Capsule
		bhkCapsuleShapeRef capsule = new bhkCapsuleShape();
		capsule->SetRadius(radius/scale);
		capsule->SetRadius1(radius/scale);
		capsule->SetRadius2(radius/scale);
		float length; 
		taperParameters->GetValue(PA_TAPEREDCAPSULE_OBJ_HEIGHT, 0, length, FOREVER);
		//get the normal
		Matrix3 axis(true);
		ragdollParent->GetObjOffsetRot().MakeMatrix(axis);
		Point3 normalAx = axis.GetRow(2);
		//capsule center
		Point3 center = ragdollParent->GetObjOffsetPos();
		//min and max points
		Point3 pt1 = center - normalAx*(length/2);
		Point3 pt2 = center + normalAx*(length/2);

		capsule->SetFirstPoint(TOVECTOR3(pt1)/scale);
		capsule->SetSecondPoint(TOVECTOR3(pt2)/scale);
		capsule->SetMaterial(HAV_MAT_SKIN);

		shape = StaticCast<bhkShape>(capsule);
		
	}
	else {
		// Sphere
		//CalcBoundingSphere(node, tm.GetTrans(), radius, 0);

		bhkSphereShapeRef sphere = new bhkSphereShape();
		sphere->SetRadius(radius/scale);
		sphere->SetMaterial(HAV_MAT_SKIN);
		shape = StaticCast<bhkShape>(sphere);
	}

	bhkRigidBodyRef body;

	if (shape)
	{
		bhkBlendCollisionObjectRef blendObj = new bhkBlendCollisionObject();
		body = new bhkRigidBody();

		Matrix3 tm = ragdollParent->GetObjTMAfterWSM(0);
		
		//Calculate Object Offset Matrix
		Matrix3 otm(1);
		Point3 pos = ragdollParent->GetObjOffsetPos();
		otm.PreTranslate(pos);
		Quat quat = ragdollParent->GetObjOffsetRot();
		PreRotateMatrix(otm, quat);
		Matrix3 otmInvert = otm;
		otmInvert.Invert();

		//correct object tm
		Matrix3 tmbhk = otmInvert * tm;

		//set geometric parameters
		body->SetRotation(TOQUATXYZW(Quat(tmbhk).Invert()));
		body->SetTranslation(TOVECTOR4(tmbhk.GetTrans() / scale));
		body->SetCenter(TOVECTOR4(ragdollParent->GetObjOffsetPos())/scale);

		//set physics
		if (IParamBlock2* rbParameters = rbMod->GetParamBlockByID(PB_RB_MOD_PBLOCK)) {
			//These are fundamental parameters

			int lyr = NP_DEFAULT_HVK_LAYER;
			int mtl = NP_DEFAULT_HVK_MATERIAL;
			int msys = NP_DEFAULT_HVK_MOTION_SYSTEM;
			int qtype = NP_DEFAULT_HVK_QUALITY_TYPE;
			float mass = NP_DEFAULT_HVK_MASS;
			float lindamp = NP_DEFAULT_HVK_LINEAR_DAMPING;
			float angdamp = NP_DEFAULT_HVK_ANGULAR_DAMPING;
			float frict = NP_DEFAULT_HVK_FRICTION;
			float maxlinvel = NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY;
			float maxangvel = NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY;
			float resti = NP_DEFAULT_HVK_RESTITUTION;
			float pendepth = NP_DEFAULT_HVK_PENETRATION_DEPTH;
			Point3 InertiaTensor;


			rbParameters->GetValue(PA_RB_MOD_MASS, 0, mass, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_RESTITUTION, 0, resti, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_FRICTION, 0, frict, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_INERTIA_TENSOR, 0, InertiaTensor, FOREVER);


			rbParameters->GetValue(PA_RB_MOD_LINEAR_DAMPING, 0, lindamp, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_CHANGE_ANGULAR_DAMPING, 0, angdamp, FOREVER);

			rbParameters->GetValue(PA_RB_MOD_MAX_LINEAR_VELOCITY, 0, maxlinvel, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_MAX_ANGULAR_VELOCITY, 0, maxangvel, FOREVER);

			rbParameters->GetValue(PA_RB_MOD_ALLOWED_PENETRATION_DEPTH, 0, pendepth, FOREVER);
			rbParameters->GetValue(PA_RB_MOD_QUALITY_TYPE, 0, qtype, FOREVER);

			body->SetMass(mass);
			body->SetRestitution(resti);
			body->SetFriction(frict);
			body->SetLinearDamping(lindamp);
			body->SetMaxLinearVelocity(maxlinvel);
			body->SetMaxAngularVelocity(maxangvel);
			body->SetPenetrationDepth(pendepth);
			InertiaMatrix im;
			im[0][0] = InertiaTensor[0];
			im[1][1] = InertiaTensor[1];
			im[2][2] = InertiaTensor[2];

			body->SetInertia(im);

			/*switch (qtype) {
			case QT_FIXED:
				body->SetQualityType(MO_QUAL_FIXED);
				break;
			case QT_KEYFRAMED:
				body->SetQualityType(MO_QUAL_KEYFRAMED);
				break;
			case QT_DEBRIS:
				body->SetQualityType(MO_QUAL_DEBRIS);
				break;
			case QT_MOVING:
				body->SetQualityType(MO_QUAL_MOVING);
				break;
			case QT_CRITICAL:
				body->SetQualityType(MO_QUAL_CRITICAL);
				break;
			case QT_BULLET:
				body->SetQualityType(MO_QUAL_BULLET);
				break;
			case QT_KEYFRAMED_REPORTING:
				body->SetQualityType(MO_QUAL_KEYFRAMED_REPORT);
				break;
			}*/

			body->SetSkyrimLayer(SkyrimLayer::SKYL_BIPED);
			body->SetSkyrimLayerCopy(SkyrimLayer::SKYL_BIPED);

			body->SetMotionSystem(MotionSystem::MO_SYS_BOX);
			body->SetDeactivatorType(DeactivatorType::DEACTIVATOR_NEVER);
			body->SetSolverDeactivation(SolverDeactivation::SOLVER_DEACTIVATION_LOW);
			body->SetQualityType(MO_QUAL_FIXED);

		}
		
		if (constraintMod && ragdollParent->GetParentNode() && parent->GetParent()) {
			if (constraintMod->ClassID() == HK_CONSTRAINT_RAGDOLL_CLASS_ID) {
				bhkRagdollConstraintRef ragdollConstraint = new bhkRagdollConstraint();
				
				//entities
				ragdollConstraint->AddEntity(body);
				NiNodeRef parentRef = parent->GetParent();
				bhkRigidBodyRef nifParentRigidBody;
				while (parentRef) {
					if (parentRef->GetCollisionObject()) {
						nifParentRigidBody = StaticCast<bhkRigidBody>(StaticCast<bhkBlendCollisionObject>(parentRef->GetCollisionObject())->GetBody());
						break;
					}
					parentRef = parentRef->GetParent();
				}
				if (!nifParentRigidBody)
					throw exception(FormatText("Unable to find NIF constraint parent for ragdoll node %s", ragdollParent->GetName()));
				ragdollConstraint->AddEntity(nifParentRigidBody);

				RagdollDescriptor desc;
				//parameters
				if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) {
					Point3 pivotA;
					Matrix3 parentRotation;
					Point3 pivotB;
					Matrix3 childRotation;
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_TRANSLATION, 0, pivotB, FOREVER);
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, FOREVER);
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_TRANSLATION, 0, pivotA, FOREVER);
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, FOREVER);
					
					desc.pivotA = TOVECTOR4(pivotA);
					desc.pivotB = TOVECTOR4(pivotB);
					desc.planeA = TOVECTOR4(parentRotation.GetRow(0));
					desc.motorA = TOVECTOR4(parentRotation.GetRow(1));
					desc.twistA = TOVECTOR4(parentRotation.GetRow(2));
					desc.planeB = TOVECTOR4(childRotation.GetRow(0));
					desc.motorB = TOVECTOR4(childRotation.GetRow(1));
					desc.twistB = TOVECTOR4(childRotation.GetRow(2));
					
				}
				if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_RAGDOLL_MOD_PBLOCK)) {
					float coneMaxAngle;
					float planeMinAngle;
					float planeMaxAngle;
					float coneMinAngle;
					float twistMinAngle;
					float maxFriction;

					constraintParameters->GetValue(PA_RAGDOLL_MOD_CONE_ANGLE, 0, coneMaxAngle, FOREVER);
					constraintParameters->GetValue(PA_RAGDOLL_MOD_PLANE_MIN, 0, planeMinAngle, FOREVER);
					constraintParameters->GetValue(PA_RAGDOLL_MOD_PLANE_MAX, 0, planeMaxAngle, FOREVER);
					constraintParameters->GetValue(PA_RAGDOLL_MOD_TWIST_MIN, 0, coneMinAngle, FOREVER);
					constraintParameters->GetValue(PA_RAGDOLL_MOD_TWIST_MAX, 0, twistMinAngle, FOREVER);
					constraintParameters->GetValue(PA_RAGDOLL_MOD_MAX_FRICTION_TORQUE, 0, maxFriction, FOREVER);

					desc.coneMaxAngle = TORAD(coneMaxAngle);
					desc.planeMinAngle = TORAD(planeMinAngle);
					desc.planeMaxAngle = TORAD(planeMaxAngle);
					desc.coneMaxAngle = TORAD(coneMinAngle);
					desc.twistMinAngle = TORAD(twistMinAngle);
					desc.maxFriction = maxFriction;


				}
				ragdollConstraint->SetRagdoll(desc);
				body->AddConstraint(ragdollConstraint);
			}
			else if (constraintMod->ClassID() == HK_CONSTRAINT_HINGE_CLASS_ID) {
				bhkLimitedHingeConstraintRef limitedHingeConstraint = new bhkLimitedHingeConstraint();

				//entities
				limitedHingeConstraint->AddEntity(body);
				NiNodeRef parentRef = parent->GetParent();
				bhkRigidBodyRef nifParentRigidBody;
				while (parentRef) {
					if (parentRef->GetCollisionObject()) {
						nifParentRigidBody = StaticCast<bhkRigidBody>(StaticCast<bhkBlendCollisionObject>(parentRef->GetCollisionObject())->GetBody());
						break;
					}
					parentRef = parentRef->GetParent();
				}
				if (!nifParentRigidBody)
					throw exception(FormatText("Unable to find NIF constraint parent for limited hinge node %s", ragdollParent->GetName()));
				limitedHingeConstraint->AddEntity(nifParentRigidBody);

				LimitedHingeDescriptor lh;

				if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) {
					Matrix3 parentRotation;
					Matrix3 childRotation;
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, FOREVER);
					constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, FOREVER);

					lh.perp2AxleInA1 = TOVECTOR4(parentRotation.GetRow(0));
					lh.perp2AxleInA2 = TOVECTOR4(parentRotation.GetRow(1));
					lh.axleA = TOVECTOR4(parentRotation.GetRow(2));
					lh.perp2AxleInB1 = TOVECTOR4(childRotation.GetRow(0));
					lh.perp2AxleInB2 = TOVECTOR4(childRotation.GetRow(1));
					lh.axleB = TOVECTOR4(childRotation.GetRow(2));
					
				}
				if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_HINGE_MOD_PBLOCK)) {
					float minAngle;
					float maxAngle;
					float maxFriction;

					constraintParameters->GetValue(PA_HINGE_MOD_LIMIT_MIN, 0, minAngle, FOREVER);
					constraintParameters->GetValue(PA_HINGE_MOD_LIMIT_MAX, 0, maxAngle, FOREVER);
					constraintParameters->GetValue(PA_HINGE_MOD_MAX_FRICTION_TORQUE, 0, maxFriction, FOREVER);
					//	constraintParameters->SetValue(PA_HINGE_MOD_MOTOR_TYPE, 0, lh.motor., 0);

					lh.minAngle = TORAD(minAngle);
					lh.maxAngle = TORAD(maxAngle);
					lh.maxAngle = maxFriction;

				}
				limitedHingeConstraint->SetLimitedHinge(lh);
				body->AddConstraint(limitedHingeConstraint);
			}
		}


		//InitializeRigidBody(body, node);
		body->SetShape(shape);
		blendObj->SetBody(StaticCast<NiObject>(body));
		parent->SetCollisionObject(StaticCast<NiCollisionObject>(blendObj));
	}

	////rigid body parameters
	//	// get data from node
	//int lyr = NP_DEFAULT_HVK_LAYER;
	//int mtl = NP_DEFAULT_HVK_MATERIAL;
	//int msys = NP_DEFAULT_HVK_MOTION_SYSTEM;
	//int qtype = NP_DEFAULT_HVK_QUALITY_TYPE;
	//float mass = NP_DEFAULT_HVK_MASS;
	//float lindamp = NP_DEFAULT_HVK_LINEAR_DAMPING;
	//float angdamp = NP_DEFAULT_HVK_ANGULAR_DAMPING;
	//float frict = NP_DEFAULT_HVK_FRICTION;
	//float maxlinvel = NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY;
	//float maxangvel = NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY;
	//float resti = NP_DEFAULT_HVK_RESTITUTION;
	//float pendepth = NP_DEFAULT_HVK_PENETRATION_DEPTH;
	//BOOL transenable = TRUE;

	//if (IParamBlock2* rbParameters = rbMod->GetParamBlockByID(PB_SHAPE_MOD_PBLOCK))
	//{
	//	//These are fundamental parameters
	//	rbParameters->GetValue(PA_RB_MOD_MASS, 0, mass, FOREVER);
	//	rbParameters->GetValue(PA_RB_MOD_RESTITUTION, 0, resti, FOREVER);
	//	rbParameters->GetValue(PA_RB_MOD_FRICTION, 0, frict, FOREVER);

	//	rbParameters->GetValue(PA_RB_MOD_LINEAR_DAMPING, 0, lindamp, FOREVER);
	//	rbParameters->GetValue(PA_RB_MOD_CHANGE_ANGULAR_DAMPING, 0, angdamp, FOREVER);

	//	rbParameters->GetValue(PA_RB_MOD_MAX_LINEAR_VELOCITY, 0, maxlinvel, FOREVER);
	//	rbParameters->GetValue(PA_RB_MOD_MAX_ANGULAR_VELOCITY, 0, maxangvel, FOREVER);

	//	rbParameters->GetValue(PA_RB_MOD_ALLOWED_PENETRATION_DEPTH, 0, pendepth, FOREVER);

	//	rbParameters->GetValue(PA_RB_MOD_QUALITY_TYPE, 0, qtype, FOREVER);


	//	switch (qtype) {
	//	case MO_QUAL_INVALID:
	//		break;
	//	case QT_FIXED:
	//		rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, MO_QUAL_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;
	//	}

	//	// setup body
	//	bhkRigidBodyRef body = transenable ? new bhkRigidBodyT() : new bhkRigidBody();

	//	OblivionLayer obv_layer; SkyrimLayer sky_layer;
	//	GetHavokLayersFromIndex(lyr, (int*)&obv_layer, (int*)&sky_layer);
	//	body->SetLayer(obv_layer);
	//	body->SetLayerCopy(obv_layer);
	//	body->SetSkyrimLayer(sky_layer);

	//	body->SetMotionSystem(MotionSystem(msys));
	//	body->SetQualityType(MotionQuality(qtype));
	//	body->SetMass(mass);
	//	body->SetLinearDamping(lindamp);
	//	body->SetAngularDamping(angdamp);
	//	body->SetFriction(frict);
	//	body->SetRestitution(resti);
	//	body->SetMaxLinearVelocity(maxlinvel);
	//	body->SetMaxAngularVelocity(maxangvel);
	//	body->SetPenetrationDepth(pendepth);
	//	body->SetCenter(center);
	//	QuaternionXYZW q; q.x = q.y = q.z = 0; q.w = 1.0f;
	//	body->SetRotation(q);
	//}
}
Ejemplo n.º 11
0
void ResetXForm::ResetNodes(const INodeTab& nodesToReset)
{
	Interface *ip = GetCOREInterface();
	for (int i = 0; i < nodesToReset.Count(); i++) {
		INode *node = nodesToReset[i];
		if (!node || node->IsGroupMember() || node->IsGroupHead()) 
			continue;
		if (SelectedAncestor(node)) 
			continue;

		Matrix3 ntm, ptm, rtm(1), piv(1), tm;
		
		// Get Parent and Node TMs
		ntm = node->GetNodeTM(ip->GetTime());
		ptm = node->GetParentTM(ip->GetTime());
		
		// Compute the relative TM
		ntm = ntm * Inverse(ptm);
		
		// The reset TM only inherits position
		rtm.SetTrans(ntm.GetTrans());
		
		// Set the node TM to the reset TM		
		tm = rtm*ptm;
		node->SetNodeTM(ip->GetTime(), tm);

		// Compute the pivot TM
		piv.SetTrans(node->GetObjOffsetPos());
		PreRotateMatrix(piv,node->GetObjOffsetRot());
		ApplyScaling(piv,node->GetObjOffsetScale());
		
		// Reset the offset to 0
		node->SetObjOffsetPos(Point3(0,0,0));
		node->SetObjOffsetRot(IdentQuat());
		node->SetObjOffsetScale(ScaleValue(Point3(1,1,1)));

		// Take the position out of the matrix since we don't reset position
		ntm.NoTrans();

		// Apply the offset to the TM
		ntm = piv * ntm;

		// Apply a derived object to the node's object
		Object *obj = node->GetObjectRef();
		IDerivedObject *dobj = CreateDerivedObject(obj);
		
		// Create an XForm mod
		SimpleMod *mod = (SimpleMod*)ip->CreateInstance(
			OSM_CLASS_ID,
			Class_ID(CLUSTOSM_CLASS_ID,0));

		// Apply the transformation to the mod.
		SetXFormPacket pckt(ntm);
		mod->tmControl->SetValue(ip->GetTime(),&pckt);

		// Add the modifier to the derived object.
		dobj->SetAFlag(A_LOCK_TARGET); // RB 3/11/99: When the macro recorder is on the derived object will get deleted unless it is locked.
		dobj->AddModifier(mod);
		dobj->ClearAFlag(A_LOCK_TARGET);

		// Replace the node's object
		node->SetObjectRef(dobj);
	}
	
//	Why on earth were we clearing the undo stack?
//	GetSystemSetting(SYSSET_CLEAR_UNDO);
	ip->RedrawViews(ip->GetTime());
	SetSaveRequiredFlag(TRUE);
}