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()); }
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; }
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); }
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; }
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); } }
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); }
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)); } } };
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; } }
/* 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); //} }
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); }