Matrix3 FormationBhvr::GetFollowerMatrix(TimeValue t,int which) { //we are using 4 Point3's to represent the matrix.. Point3 point; Matrix3 matrix; pblock->GetValue(follower_matrix1, 0,point,FOREVER,which); matrix.SetRow(0,point); pblock->GetValue(follower_matrix2, 0,point,FOREVER,which); matrix.SetRow(1,point); pblock->GetValue(follower_matrix3, 0,point,FOREVER,which); matrix.SetRow(2,point); pblock->GetValue(follower_matrix4, 0,point,FOREVER,which); matrix.SetRow(3,point); matrix.ValidateFlags(); return matrix; //Note that when this code was written that the Matrix3 paramblock //parameter wasn't working correctly in R4 at the time this was written. /* if(which<0||which>=GetFollowerCount(t)) return NULL; Matrix3 mat; pblock->GetValue(follower_matrix,t,mat,FOREVER,which); return mat; */ }
static void UnwrapMatrixFromNormal(Point3& normal, Matrix3& mat) { Point3 vx; vx.z = .0f; vx.x = -normal.y; vx.y = normal.x; if ( vx.x == .0f && vx.y == .0f ) { vx.x = 1.0f; } mat.SetRow(0,vx); mat.SetRow(1,normal^vx); mat.SetRow(2,normal); mat.SetTrans(Point3(0,0,0)); mat.NoScale(); }
Void SoftBody::_UpdatePose() { if ( !(m_hPose.bIsFrame) ) return; // Update COM m_hPose.vCenterOfMass = _ComputeCenterOfMass(); // Update Rotation & Scaling const Node * pNode; UInt iNodeIndex; Vector3 vTmpRow, vWeigthedDelta; Matrix3 matRotScale; matRotScale.MakeNull(); matRotScale.m00 = SCALAR_EPSILON; matRotScale.m11 = SCALAR_EPSILON * 2.0f; matRotScale.m22 = SCALAR_EPSILON * 3.0f; EnumNodes(); pNode = EnumNextNode(); while( pNode != NULL ) { iNodeIndex = pNode->GetIndex(); const Vector3 & vDelta = m_hPose.arrDeltas[iNodeIndex]; vWeigthedDelta = ( (pNode->Position - m_hPose.vCenterOfMass) * m_hPose.arrWeights[iNodeIndex] ); matRotScale.GetRow( vTmpRow, 0 ); matRotScale.SetRow( 0, vTmpRow + (vDelta * vWeigthedDelta.X) ); matRotScale.GetRow( vTmpRow, 1 ); matRotScale.SetRow( 1, vTmpRow + (vDelta * vWeigthedDelta.Y) ); matRotScale.GetRow( vTmpRow, 2 ); matRotScale.SetRow( 2, vTmpRow + (vDelta * vWeigthedDelta.Z) ); pNode = EnumNextNode(); } Matrix3 matRot, matScale; matRotScale.PolarDecomposition( matRot, matScale ); m_hPose.matRotation = matRot; m_hPose.matScaling = ( m_hPose.matBaseScaling * matScale ); if ( m_fMaxVolumeRatio > 1.0f ) { Scalar fInvDet = Clamp<Scalar>( MathFn->Invert( m_hPose.matScaling.Determinant() ), 1.0f, m_fMaxVolumeRatio ); m_hPose.matScaling *= fInvDet; } }
void TrackMouseCallBack::draw_marker(ViewExp& vpt, Point3 p, Point3 norm) { return; // sorry, this doesn't work yet - I'll post it later // set GW tm to orientation specified by norm and draw a circle Matrix3 tm; Point3 zdir, ydir, xdir; // compute the direction of the z axis to be. // the positive z axis points AWAY from the target. zdir = Normalize(norm); // compute direction of the X axis before roll. xdir = Normalize(CrossProd(zdir.x > 0 ? Point3(0, 0, 1) : Point3(0, 0, -1), zdir)); // compute direction of the Y axis before roll. ydir = Normalize(CrossProd(zdir, xdir)); tm.SetRow(0, xdir); tm.SetRow(1, ydir); tm.SetRow(2, zdir); vpt.getGW()->setTransform(tm); vpt.getGW()->setColor(LINE_COLOR, MARKER_COLOR); vpt.getGW()->marker(&p, CIRCLE_MRKR); }
void RemovePivotScale(INode* node) { const TimeValue t = ccMaxWorld::MaxTime(); Matrix3 nodeTM = node->GetNodeTM(t); Point3 pos = nodeTM.GetRow(3); Matrix3 objectTM = node->GetObjectTM(t); nodeTM = objectTM; nodeTM.SetRow(3, pos); Matrix3 pv = objectTM * Inverse(nodeTM); node->SetNodeTM(t, nodeTM); node->SetObjOffsetPos(pv.GetTrans()); node->SetObjOffsetRot(IdentQuat()); node->SetObjOffsetScale(ScaleValue(Point3(1,1,1))); }
//--------------------------------------------------------------------------- Matrix3 U2MaxSceneExport::UniformMatrix(Matrix3 orig_cur_mat) { AffineParts parts; Matrix3 mat; // Remove scaling from orig_cur_mat // 1) Decompose original and get decomposition info decomp_affine(orig_cur_mat, &parts); // 2) construct 3x3 rotation from quaternion parts.q parts.q.MakeMatrix(mat); // 3) construct position row from translation parts.t mat.SetRow(3, parts.t); return mat; }
void XsiExp::ExportNodeTM( INode * node, int indentLevel) { // dump the full matrix Matrix3 matrix = node->GetNodeTM(GetStaticFrame()); TSTR indent = GetIndent(indentLevel); fprintf(pStream,"%s\t%s {\n\n", indent.data(), "FrameTransformMatrix"); Object * obj = node->EvalWorldState(0).obj; BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE; if (node->GetParentNode() && node->GetParentNode()->IsRootNode()) { // bone chains get grafted into the hierarchy tree // if (!isBone) { // root mesh oTopMatrix = matrix; AffineParts ap; decomp_affine( matrix, &ap); topMatrix.Set( Point3( ap.k.x,0.0f,0.0f), Point3( 0.0f,ap.k.z,0.0f), Point3(0.0f,0.0f,ap.k.y), Point3(0,0,0)); // root transform is controlled by the engine matrix.IdentityMatrix(); } } else { matrix = matrix * Inverse(node->GetParentTM(GetStaticFrame())); if (!isBone) { matrix.SetRow( 3, topMatrix * matrix.GetRow(3)); } } // write the matrix values DumpMatrix3( &matrix, indentLevel+2); // transform close brace fprintf(pStream,"%s\t}\n", indent.data()); }
//tm the mirror tm void CopyBuffer::PasteToBuffer(MorphByBone *mod, MorphByBoneData *targ, Matrix3 mirrorTM, float threshold, BOOL flipTM) { if (copyData == NULL) return; if (copyData->morphTargets.Count() == 0) return; if (targ == NULL) return; //delete any existing morphs for (int i = 0; i < targ->morphTargets.Count(); i++) delete targ->morphTargets[i]; targ->morphTargets.ZeroCount(); int realCount= 0; for (int i = 0; i < copyData->morphTargets.Count(); i++) { if (!copyData->morphTargets[i]->IsDead()) realCount++; } targ->morphTargets.SetCount(realCount); for (int i = 0; i < mod->localDataList.Count(); i++) { MorphByBoneLocalData *ld = mod->localDataList[i]; if (ld) { ld->tempPoints = ld->preDeform; ld->tempMatchList.SetCount(ld->tempPoints.Count()); for (int j = 0; j < ld->preDeform.Count(); j++) { Matrix3 tm(1); //need to put our original points ld->tempPoints[j] = ld->tempPoints[j] * mirrorTM; ld->tempMatchList[j] = -1; } } } //now find closest pairs for (int i = 0; i < mod->localDataList.Count(); i++) { MorphByBoneLocalData *ld = mod->localDataList[i]; if (ld) { for (int j = 0; j < ld->tempPoints.Count(); j++) { Point3 sourcePoint = ld->preDeform[j]; float closest = 3.4e+38; int closestID = -1; for (int k = 0; k < ld->tempPoints.Count(); k++) { Point3 mirrorPoint = ld->tempPoints[k]; float dist = Length(sourcePoint-mirrorPoint); if ((dist < threshold) && (dist < closest)) { closest = dist; closestID = k; } } if (closestID != -1) ld->tempMatchList[closestID] = j; } } } //create a blank set of morphs int currentMorph = 0; for (int i = 0; i < copyData->morphTargets.Count(); i++) { if (!copyData->morphTargets[i]->IsDead()) { targ->morphTargets[currentMorph] = new MorphTargets(); int currentVert=0; for (int j = 0; j < mod->localDataList.Count(); j++) { targ->morphTargets[currentMorph]->d.SetCount(mod->localDataList[j]->preDeform.Count()); for (int k =0; k < mod->localDataList[j]->preDeform.Count(); k++) { targ->morphTargets[currentMorph]->d[currentVert].vertexID = k; targ->morphTargets[currentMorph]->d[currentVert].vec = Point3(0.0f,0.0f,0.0f); targ->morphTargets[currentMorph]->d[currentVert].vecParentSpace = Point3(0.0f,0.0f,0.0f); targ->morphTargets[currentMorph]->d[currentVert].originalPt = mod->localDataList[j]->preDeform[k];//*tm; targ->morphTargets[currentMorph]->d[currentVert].localOwner = j; currentVert++; } } currentMorph++; } } //this only works if it is not instanced //loop through morphs currentMorph = 0; for (int i = 0; i < copyData->morphTargets.Count(); i++) { if (!copyData->morphTargets[i]->IsDead()) { //loop through points for (int j = 0; j <targ->morphTargets[currentMorph]->d.Count(); j++) { //get the mirror index if there is one int ldIndex = targ->morphTargets[currentMorph]->d[j].localOwner; MorphByBoneLocalData *ld = mod->localDataList[ldIndex]; Matrix3 boneTM = copyData->currentBoneNodeTM; Matrix3 parentTM = copyData->parentBoneNodeCurrentTM; Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM; Matrix3 mirrorBoneTM = targ->currentBoneNodeTM; Matrix3 mirrorParentTM = targ->parentBoneNodeCurrentTM; Matrix3 lTM, pTM; lTM = boneTM * mirror * Inverse(mirrorBoneTM); pTM = parentTM * mirror * Inverse(mirrorParentTM); if (ld) { int mirrorID = targ->morphTargets[currentMorph]->d[j].vertexID; int sourceID = ld->tempMatchList[mirrorID]; //now look though our list and swap the 2 if (sourceID != -1) { ////transform the vec into local space, flip them, then back into bone space // targ->morphTargets[i]->d[j].vec = VectorTransform(copyData->morphTargts[i]->d[sourceID].vec,mirrorTM); if (1)//(flipTM) { Point3 vec = copyData->morphTargets[i]->d[sourceID].vec; // in local bone space targ->morphTargets[currentMorph]->d[j].vec = VectorTransform(lTM,vec); vec = copyData->morphTargets[i]->d[sourceID].vecParentSpace; // in local bone space targ->morphTargets[currentMorph]->d[j].vecParentSpace = VectorTransform(pTM,vec); //current bone tm //current parent tm //invserse of the self //mirror //self tm //inverse of mirror bone //inverse of mirror parent bone } else { targ->morphTargets[currentMorph]->d[j].vec = copyData->morphTargets[i]->d[sourceID].vec; targ->morphTargets[currentMorph]->d[j].vecParentSpace = copyData->morphTargets[i]->d[sourceID].vecParentSpace; } // Point3 pvec = copyData->morphTargets[i]->d[sourceID].vecParentSpace; // Matrix3 selfTM = ld->selfNodeTM; // Matrix3 parentTM = copyData->parentBoneNodeCurrentTM; // Matrix3 tm = parentTM * Inverse(selfTM) * mirrorTM * selfTM * Inverse(parentTM); // pvec = VectorTransform(tm,pvec); //do we need to flip the vecs? targ->morphTargets[currentMorph]->d[j].originalPt = copyData->morphTargets[i]->d[sourceID].originalPt * mirrorTM; } } } //resolve tms if (flipTM) { MorphByBoneLocalData *ld = mod->localDataList[0]; Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM; //mirror the initial copy node tm Matrix3 copyTM = copyData->currentBoneNodeTM; copyTM *= mirror; copyTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3)); // targ->morphTargets[currentMorph]->boneTMInParentSpace = copyTM * ; //put our current targ node tm into the copyTM space Matrix3 targTM = targ->currentBoneNodeTM; targTM *= Inverse(copyTM); //put the morph tm in worldspace Matrix3 morphTM = copyData->morphTargets[i]->boneTMInParentSpace * copyData->parentBoneNodeCurrentTM; //mirror it // morphTM *= mirror; // morphTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3)); //now animate it back to world using the morph target tm targTM *= morphTM; //jam it back into our parent space targTM *= Inverse(targ->currentBoneNodeTM); targ->morphTargets[currentMorph]->boneTMInParentSpace = targTM; } else targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace; //puts it in world space /* morphTM = copyData->morphTargets[i]->boneTMInParentSpace * copyData->parentBoneNodeCurrentTM; morphTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3)); morphTM = morphTM * mirror; morphTM = morphTM * Inverse(targ->parentBoneNodeCurrentTM); targ->morphTargets[currentMorph]->boneTMInParentSpace = morphTM; */ /* //mirror all the morph tms MorphByBoneLocalData *ld = mod->localDataList[0]; Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM; Matrix3 ptm = copyData->parentBoneNodeCurrentTM; Matrix3 mtm = copyData->morphTargets[i]->boneTMInParentSpace; Matrix3 morphWorldSpaceTM = mtm * ptm *mirror; morphWorldSpaceTM.SetRow(3,targ->currentBoneNodeTM.GetRow(3)); //link the target bone initial to the mirrored initial copy node tm //remcompute the mirror tms //but pack into our targ space if (flipTM) { MorphByBoneLocalData *ld = mod->localDataList[0]; Matrix3 mirror = Inverse(ld->selfNodeTM) * mirrorTM * ld->selfNodeTM; //transform the tm into local space //flip it thenback in parent space Matrix3 mtm = copyData->morphTargets[i]->boneTMInParentSpace; mtm = mtm * copyData->parentBoneNodeCurrentTM; //this puts in world space Point3 x,y,z; x = VectorTransform(mirror,mtm.GetRow(0)); y = VectorTransform(mirror,mtm.GetRow(1)); z = VectorTransform(mirror,mtm.GetRow(2)); mtm.SetRow(0,x); mtm.SetRow(1,y); mtm.SetRow(2,z); mtm = mtm * Inverse(copyData->parentBoneNodeCurrentTM); mtm.SetRow(3,copyData->morphTargets[i]->boneTMInParentSpace.GetRow(3)); //put in world space, then by the mirror then back into parent targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace; } else targ->morphTargets[currentMorph]->boneTMInParentSpace = copyData->morphTargets[i]->boneTMInParentSpace; */ targ->morphTargets[currentMorph]->influenceAngle = copyData->morphTargets[i]->influenceAngle; targ->morphTargets[currentMorph]->falloff = copyData->morphTargets[i]->falloff; targ->morphTargets[currentMorph]->name = copyData->morphTargets[i]->name; targ->morphTargets[currentMorph]->treeHWND = NULL; targ->morphTargets[currentMorph]->weight = copyData->morphTargets[i]->weight; targ->morphTargets[currentMorph]->flags = copyData->morphTargets[i]->flags; currentMorph++; } } //clean up temp data for (int i = 0; i < mod->localDataList.Count(); i++) { MorphByBoneLocalData *ld = mod->localDataList[i]; if (ld) { ld->tempPoints.Resize(0); ld->tempMatchList.Resize(0); } } }
Void SoftBody::_SetupPose( Bool bIsVolume, Bool bIsFrame ) { const Node * pNode; UInt iNodeIndex; // Update links EnumLinks(); Link * pLink = EnumNextLink(); while( pLink != NULL ) { pLink->UpdateConstants(); pLink = EnumNextLink(); } // Compute total mass Scalar fTotalMass = _ComputeMass(); Scalar fMassK = fTotalMass * 1000.0f * (Scalar)( GetNodeCount() ); EnumNodes(); pNode = EnumNextNode(); while( pNode != NULL ) { if ( pNode->InvMass == 0.0f ) fTotalMass += fMassK; pNode = EnumNextNode(); } Scalar fInvTotalMass = MathFn->Invert( fTotalMass ); // Flags m_hPose.bIsVolume = bIsVolume; m_hPose.bIsFrame = bIsFrame; // Weights m_hPose.arrWeights.Clear(); EnumNodes(); pNode = EnumNextNode(); while( pNode != NULL ) { if ( pNode->InvMass > 0.0f ) m_hPose.arrWeights.Push( pNode->Mass * fInvTotalMass ); else m_hPose.arrWeights.Push( fMassK * fInvTotalMass ); pNode = EnumNextNode(); } // COM m_hPose.vCenterOfMass = _ComputeCenterOfMass(); // Deltas m_hPose.arrDeltas.Clear(); EnumNodes(); pNode = EnumNextNode(); while( pNode != NULL ) { m_hPose.arrDeltas.Push( pNode->Position - m_hPose.vCenterOfMass ); pNode = EnumNextNode(); } // Volume m_hPose.fVolume = ( (bIsVolume) ? _ComputeVolume() : 0.0f ); // BaseScaling Matrix3 matBaseScaling; matBaseScaling.MakeNull(); Vector3 vTmpRow; EnumNodes(); pNode = EnumNextNode(); while( pNode != NULL ) { iNodeIndex = pNode->GetIndex(); const Vector3 & vDelta = m_hPose.arrDeltas[iNodeIndex]; const Vector3 & vWeightedDelta = ( vDelta * m_hPose.arrWeights[iNodeIndex] ); matBaseScaling.GetRow( vTmpRow, 0 ); matBaseScaling.SetRow( 0, vTmpRow + (vDelta * vWeightedDelta.X) ); matBaseScaling.GetRow( vTmpRow, 1 ); matBaseScaling.SetRow( 1, vTmpRow + (vDelta * vWeightedDelta.Y) ); matBaseScaling.GetRow( vTmpRow, 2 ); matBaseScaling.SetRow( 2, vTmpRow + (vDelta * vWeightedDelta.Z) ); pNode = EnumNextNode(); } matBaseScaling.Invert( m_hPose.matBaseScaling ); // Rotation & Scaling m_hPose.matRotation.MakeIdentity(); m_hPose.matScaling.MakeIdentity(); }
/* Use the shape of node to create Bullet shape for the actor. ActorNode is the main Max node. */ btCollisionShape* MxActor::createShape(NxActorDesc& actorDesc, ccMaxNode* node, ccMaxNode* actorNode) { actorDesc.localPose.IdentityMatrix(); btCollisionShape* shape = NULL; const TimeValue t = ccMaxWorld::MaxTime(); Matrix3 nodePose = node->PhysicsNodePoseTM; // MaxMsgBox(NULL, _T("createShape"), _T("Error"), MB_OK); int geomType = MxUserPropUtils::GetUserPropInt(m_node, "GeometryType",1); NxShapeType type = node->ShapeType; //first apply manual overrides switch (geomType) { case 2: { type = NX_SHAPE_SPHERE; break; } case 3: { type = NX_SHAPE_BOX; break; } case 4: { type = NX_SHAPE_CAPSULE; break; } case 5: { type = NX_SHAPE_CONVEX; break; } case 6: { type = NX_SHAPE_MESH; break; } default: { } }; actorDesc.localPose = node->PhysicsNodePoseTM * actorNode->PhysicsNodePoseTMInv; switch (type) { case NX_SHAPE_SPHERE: { btScalar radius = node->PrimaryShapePara.Radius; shape = new btSphereShape(radius); break; }; case NX_SHAPE_BOX: { //adjust for difference in pivot points between 3ds max and Bullet (Bullet uses the box center) Matrix3 offset; offset.IdentityMatrix(); offset.SetTrans(2,node->PrimaryShapePara.BoxDimension.z()); actorDesc.localPose = actorDesc.localPose * offset; shape = new btBoxShape(node->PrimaryShapePara.BoxDimension.absolute()); break; } case NX_SHAPE_CAPSULE: { char bla[1024]; sprintf(bla,"capsule not properly supported yet, radius=%f,height=%f",node->PrimaryShapePara.Radius,node->PrimaryShapePara.Height); MaxMsgBox(NULL, _T(bla), _T("Error"), MB_OK); shape = new btCapsuleShape(node->PrimaryShapePara.Radius,node->PrimaryShapePara.Height); break; } case NX_SHAPE_CONVEX: { if(m_proxyNode) { MaxMsgBox(NULL, _T("Error: convex shape proxy not supported (yet)"), _T("Error"), MB_OK); //d->meshData = MxUtils::nodeToNxConvexMesh(proxyMesh); //Matrix3 pose = nodePose * actorNode->PhysicsNodePoseTMInv; //d->localPose = MxMathUtils::MaxMatrixToNx(pose); } else { if(node->SimpleMesh.numFaces > 255) { MaxMsgBox(NULL, _T("Error: number of vertices in a convex shape should be less than 256"), _T("Error"), MB_OK); //warning/Error } else { BOOL needDel = FALSE; TriObject* tri = MxUtils::GetTriObjectFromNode(node->GetMaxNode(),0.f,needDel); if (tri) { int numVerts = tri->NumPoints(); btConvexHullShape* convexHull = new btConvexHullShape(); //for center of mass computation, simplify and assume mass is at the vertices btCompoundShape* compound = new btCompoundShape(); btSphereShape sphere(0.1); btTransform tr; tr.setIdentity(); btAlignedObjectArray<btScalar> masses; btScalar childMass = actorDesc.mass/(btScalar)numVerts; for (int i=0;i<numVerts;i++) { btVector3 pt(tri->GetPoint(i).x,tri->GetPoint(i).y,tri->GetPoint(i).z); convexHull->addPoint(pt); tr.setOrigin(pt); compound->addChildShape(tr,&sphere); masses.push_back(childMass); } btTransform principal; btVector3 inertia; compound->calculatePrincipalAxisTransform(&masses[0],principal,inertia); delete compound; btTransform principalInv = principal.inverse(); compound = new btCompoundShape(); compound->addChildShape(principalInv,convexHull); shape = compound; Matrix3 offset; bullet2Max(principal,offset); actorDesc.localPose = actorDesc.localPose * offset; if (needDel) delete tri; } } //d->meshData = MxUtils::nodeToNxConvexMesh(node->SimpleMesh); //Matrix3 pose = nodePose * actorNode->PhysicsNodePoseTMInv; //d->localPose = MxMathUtils::MaxMatrixToNx(pose); } break; } case NX_SHAPE_MESH: { BOOL needDel = FALSE; TriObject* tri = MxUtils::GetTriObjectFromNode(node->GetMaxNode(),0.f,needDel); if (tri) { int numVerts = tri->NumPoints(); btTriangleMesh* meshInterface = new btTriangleMesh(); Mesh& mesh = tri->GetMesh(); if (mesh.getNumFaces()>0) { for (int i=0;i<mesh.getNumFaces();i++) { Point3 p0=tri->GetPoint(mesh.faces[i].v[0]); Point3 p1=tri->GetPoint(mesh.faces[i].v[1]); Point3 p2=tri->GetPoint(mesh.faces[i].v[2]); meshInterface->addTriangle( btVector3(p0.x,p0.y,p0.z),btVector3(p1.x,p1.y,p1.z),btVector3(p2.x,p2.y,p2.z)); } if (actorDesc.mass>0) { // MaxMsgBox(NULL, _T("btGImpactMeshShape"), _T("Error"), MB_OK); btGImpactMeshShape* trimesh = new btGImpactMeshShape(meshInterface); shape = trimesh; } else { // MaxMsgBox(NULL, _T("btBvhTriangleMeshShape"), _T("Error"), MB_OK); btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(meshInterface,true); shape = trimesh; } } else { MaxMsgBox(NULL, _T("Error: no faces"), _T("Error"), MB_OK); } if (needDel) delete tri; } else { MaxMsgBox(NULL, _T("Error: couldn't GetTriObjectFromNode"), _T("Error"), MB_OK); } break; } default: { MaxMsgBox(NULL, _T("unknown shape type"), _T("Error"), MB_OK); } }; #if 0 NxShapeDesc* pd = NULL; NxShapeType type = node->ShapeType; PxSimpleMesh proxyMesh; Matrix3 nodePose = node->PhysicsNodePoseTM; if(m_proxyNode) { // for proxy, using mesh //type = NX_SHAPE_MESH; proxyMesh.clone(node->SimpleMesh); Point3 pos = nodePose.GetRow(3); pos = pos + ProxyDistance; nodePose.SetRow(3, pos); } if((type == NX_SHAPE_MESH) && (Interactivity != RB_STATIC)) { type = NX_SHAPE_CONVEX; } // /* bool NeedCCDSkeleton = (Interactivity != RB_STATIC) && (MxUserPropUtils::GetUserPropBool(node->GetMaxNode(), "EnableCCD", false)); if(NeedCCDSkeleton) { NxPhysicsSDK* psdk = gPluginData->getPhysicsSDK(); psdk->setParameter(NX_CONTINUOUS_CD, 1); psdk->setParameter(NX_CCD_EPSILON, 0.01f); } */ // create CCD skeleton for the shape //TODO("implement CCD skeleton creation"); PX_CCD_SKELETON ccdType = (PX_CCD_SKELETON) MxUserPropUtils::GetUserPropInt(node->GetMaxNode(), "px_shape_ccdtype", 1); switch(type) { default: if (gCurrentstream) gCurrentstream->printf("Unable to create a shape of node \"%s\", unknown shape type: %d.\n", node->GetMaxNode()->GetName(), type); return false; } // load property settings and material things. //LoadShapeProperties(*pd, node->GetMaxNode()); //CCD flag pd->name = node->GetMaxNode()->GetName(); pd->userData = node; // bool isvalid = pd->isValid(); actorDesc.shapes.push_back(pd); #endif return shape; }
void UnwrapMod::fnGizmoCenter() { //get our tm //set the tm scale TimeValue t = GetCOREInterface()->GetTime(); //get our selection Box3 bounds; bounds.Init(); //get the bounding box Point3 pnorm(0.0f,0.0f,0.0f); int ct = 0; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; bounds += ld->GetGeomVert(index) * tm; //gverts.d[index].p * tm; if (j < 4) temp_point[j] = ld->GetGeomVert(index) * tm; //gverts.d[index].p; } pnorm += Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]); ct++; } } } if (ct == 0) return; theHold.Begin(); SuspendAnimate(); AnimateOff(); pnorm = pnorm / (float) ct;//gfaces.Count(); //if just a primary axis set the tm; Point3 center = bounds.Center(); // build the scale //get our tm Matrix3 tm(1); tm = *fnGetGizmoTM(); Matrix3 initialTM = tm; Point3 vec2; vec2 = Normalize(tm.GetRow(0)); tm.SetRow(0,vec2); vec2 = Normalize(tm.GetRow(1)) ; tm.SetRow(1,vec2); vec2 = Normalize(tm.GetRow(2)); tm.SetRow(2,vec2); tm.SetRow(3,center); Matrix3 itm = Inverse(tm); //find our x and y scale Box3 localBounds; localBounds.Init(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index) * tm * itm;//gverts.d[index].p * tm * itm; localBounds += p; // if (fabs(p.x) > xmax) xmax = fabs(p.x); // if (fabs(p.y) > ymax) ymax = fabs(p.y); // if (fabs(p.z) > zmax) zmax = fabs(p.z); } } } } if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)) center = localBounds.Center() * tm; else if (fnGetMapMode() == CYLINDRICALMAP) { Point3 zvec = initialTM.GetRow(2); // center = center * tm; center = localBounds.Center() * tm - (zvec * 0.5f); } initialTM.SetRow(3,center); Matrix3 ptm(1), id(1); initialTM = initialTM ; SetXFormPacket tmpck(initialTM,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); ResumeAnimate(); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) ApplyGizmo(); theHold.Accept(GetString(IDS_MAPPING_FIT)); fnGetGizmoTM(); if (ip) ip->RedrawViews(ip->GetTime()); }
void UnwrapMod::fnAlignAndFit(int axis) { //get our selection Box3 bounds; bounds.Init(); //get the bounding box Point3 pnorm(0.0f,0.0f,0.0f); int ct = 0; TimeValue t = GetCOREInterface()->GetTime(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; bounds += ld->GetGeomVert(index) *tm;//gverts.d[index].p; if (j < 4) temp_point[j] = ld->GetGeomVert(index);//gverts.d[index].p; } pnorm += VectorTransform(Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]),tm); ct++; } } } if (ct == 0) return; theHold.Begin(); SuspendAnimate(); AnimateOff(); pnorm = pnorm / (float) ct; Matrix3 tm(1); //if just a primary axis set the tm; Point3 center = bounds.Center(); // build the scale Point3 scale(bounds.Width().x ,bounds.Width().y , bounds.Width().z); if (scale.x == 0.0f) scale.x = 1.0f; if (scale.y == 0.0f) scale.y = 1.0f; if (scale.z == 0.0f) scale.z = 1.0f; if (axis == 0) // x axi { tm.SetRow(0,Point3(0.0f,-scale.y,0.0f)); tm.SetRow(1,Point3(0.0f,0.0f,scale.z)); tm.SetRow(2,Point3(scale.x,0.0f,0.0f)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.x = bounds.pmin.x; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm ; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 1) // y axi { tm.SetRow(0,Point3(scale.x,0.0f,0.0f)); tm.SetRow(1,Point3(0.0f,0.0f,scale.z)); tm.SetRow(2,Point3(0.0f,scale.y,0.0f)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.y = bounds.pmin.y; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 2) //z axi { tm.SetRow(0,Point3(scale.x,0.0f,0.0f)); tm.SetRow(1,Point3(0.0f,scale.y,0.0f)); tm.SetRow(2,Point3(0.0f,0.0f,scale.z)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.z = bounds.pmin.z; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 3) // normal { int numberOfSelectionGroups = 0; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; if (ld->GetFaceSelection().NumberSet()) numberOfSelectionGroups++; } if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (numberOfSelectionGroups > 1)) { //get our tm Matrix3 tm; UnwrapMatrixFromNormal(pnorm,tm); Matrix3 itm = Inverse(tm); //find our x and y scale float xmax = 0.0f; float ymax = 0.0f; float zmax = 0.0f; Box3 localBounds; localBounds.Init(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index) * tm * itm;//gverts.d[index].p * itm; localBounds += p; } } } } // center = localBounds.Center(); xmax = localBounds.pmax.x - localBounds.pmin.x; ymax = localBounds.pmax.y - localBounds.pmin.y; zmax = localBounds.pmax.z - localBounds.pmin.z; if (xmax < 0.001f) xmax = 1.0f; if (ymax < 0.001f) ymax = 1.0f; if (zmax < 0.001f) zmax = 1.0f; Point3 vec; vec = Normalize(tm.GetRow(0)) * xmax; tm.SetRow(0,vec); vec = Normalize(tm.GetRow(1)) * ymax; tm.SetRow(1,vec); vec = Normalize(tm.GetRow(2)) * zmax; tm.SetRow(2,vec); tm.SetRow(3,center); Matrix3 ptm(1), id(1); tm = tm ; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if ((fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP)|| (fnGetMapMode() == BOXMAP)) { for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { //get our first 2 rings Tab<int> openEdges; Tab<int> startRing; Tab<int> endRing; MeshTopoData *ld = mMeshTopoData[ldID]; //skip any local data that has no selections if (ld->GetFaceSelection().NumberSet() == 0) continue; Matrix3 nodeTM = mMeshTopoData.GetNodeTM(t,ldID); for (int i = 0; i < ld->GetNumberGeomEdges(); i++)//TVMaps.gePtrList.Count(); i++) { int numberSelectedFaces = 0; int ct = ld->GetGeomEdgeNumberOfConnectedFaces(i);//TVMaps.gePtrList[i]->faceList.Count(); for (int j = 0; j < ct; j++) { int faceIndex = ld->GetGeomEdgeConnectedFace(i,j);//TVMaps.gePtrList[i]->faceList[j]; if (ld->GetFaceSelected(faceIndex))//fsel[faceIndex]) numberSelectedFaces++; } if (numberSelectedFaces == 1) { openEdges.Append(1,&i,1000); } } GetOpenEdges(ld,openEdges, startRing); GetOpenEdges(ld,openEdges, endRing); Point3 zVec = pnorm; Point3 centerS(0.0f,0.0f,0.0f), centerE; if ((startRing.Count() != 0) && (endRing.Count() != 0)) { //get the center start Box3 BoundsS, BoundsE; BoundsS.Init(); BoundsE.Init(); //get the center end for (int i = 0; i < startRing.Count(); i++) { int eIndex = startRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } for (int i = 0; i < endRing.Count(); i++) { int eIndex = endRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsE += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsE += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } centerS = BoundsS.Center(); centerE = BoundsE.Center(); //create the vec zVec = centerE - centerS; } else if ((startRing.Count() != 0) && (endRing.Count() == 0)) { //get the center start Box3 BoundsS; BoundsS.Init(); //get the center end for (int i = 0; i < startRing.Count(); i++) { int eIndex = startRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } centerS = BoundsS.Center(); int farthestPoint= -1; Point3 fp; float farthestDist= 0.0f; for (int k=0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index)* nodeTM;//gverts.d[index].p; float d = LengthSquared(p-centerS); if ((d > farthestDist) || (farthestPoint == -1)) { farthestDist = d; farthestPoint = index; fp = p; } } } } centerE = fp; //create the vec zVec = centerE - centerS; } else { zVec = Point3(0.0f,0.0f,1.0f); } //get our tm Matrix3 tm; UnwrapMatrixFromNormal(zVec,tm); tm.SetRow(3,centerS); Matrix3 itm = Inverse(tm); //find our x and y scale float xmax = 0.0f; float ymax = 0.0f; float zmax = 0.0f; Box3 localBounds; localBounds.Init(); for (int k = 0; k < ld->GetNumberFaces(); k++)//gfaces.Count(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index) * nodeTM * itm;//gverts.d[index].p * itm; localBounds += p; } } } center = localBounds.Center() * tm; if (fnGetMapMode() == CYLINDRICALMAP) { if ((startRing.Count() == 0) && (endRing.Count() == 0)) { centerS = center; centerS.z = localBounds.pmin.z; } else { centerS = centerS * itm; centerS.z = localBounds.pmin.z; centerS = centerS * tm; } } else if ((fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) { centerS = center; } Point3 bc = localBounds.Center(); bc.z = localBounds.pmin.z; bc = bc * tm; xmax = localBounds.pmax.x - localBounds.pmin.x; ymax = localBounds.pmax.y - localBounds.pmin.y; zmax = localBounds.pmax.z - localBounds.pmin.z; Point3 vec; vec = Normalize(tm.GetRow(0)) * xmax; tm.SetRow(0,vec); vec = Normalize(tm.GetRow(1)) * ymax; tm.SetRow(1,vec); vec = Normalize(tm.GetRow(2)) * zmax; tm.SetRow(2,vec); tm.SetRow(3,centerS); Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } } } ResumeAnimate(); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) ApplyGizmo(); theHold.Accept(GetString(IDS_MAPPING_ALIGN)); fnGetGizmoTM(); if (ip) ip->RedrawViews(ip->GetTime()); }
void UnwrapMod::fnGizmoAlignToView() { if (ip == NULL) return; ViewExp& vpt = ip->GetActiveViewExp(); if (!vpt.IsAlive()) return; //get our tm //set the tm scale theHold.Begin(); SuspendAnimate(); AnimateOff(); TimeValue t = GetCOREInterface()->GetTime(); // Viewport tm Matrix3 vtm; vpt.GetAffineTM(vtm); vtm = Inverse(vtm); // Node tm Matrix3 ntm(1);// = nodeList[0]->GetObjectTM(ip->GetTime()); Matrix3 destTM = vtm * Inverse(ntm); //get our tm Matrix3 initialTM = *fnGetGizmoTM(); Point3 center = Normalize(initialTM.GetRow(3)); initialTM.SetRow(3,center); for (int i = 0; i < 3; i++) { Point3 vec = destTM.GetRow(i); float l = Length(initialTM.GetRow(i)); vec = Normalize(vec) * l; initialTM.SetRow(i,vec); } initialTM.SetRow(3,center); Matrix3 ptm(1), id(1); initialTM = initialTM ; SetXFormPacket tmpck(initialTM,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); ResumeAnimate(); fnGizmoFit(); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) ApplyGizmo(); theHold.Accept(GetString(IDS_MAPPING_ALIGNTOVIEW)); fnGetGizmoTM(); if (ip) ip->RedrawViews(ip->GetTime()); }
void SGP_MaxInterface::GetTracks( int nNodeCount, INode** nodes, Track** tracks ) { StartProgressInfo(_M("Get node track...")); TimeValue nStartTick = GetStartTick(); TimeValue nEndTick = GetEndTick(); int nTickPerFrame = GetTickPerFrame(); int nFrameCount = 0; for( TimeValue t = nStartTick; t <= nEndTick; t += nTickPerFrame ) nFrameCount++; for( int i = 0; i < nNodeCount; i++ ) { tracks[i]->vectorVisible.resize( nFrameCount ); tracks[i]->vectorTrans.resize( nFrameCount ); tracks[i]->vectorRot.resize( nFrameCount ); tracks[i]->vectorScale.resize( nFrameCount ); Matrix3 matrix = nodes[i]->GetObjTMAfterWSM ( 0 ); bool bMirror = DotProd ( CrossProd ( matrix.GetRow ( 0 ), matrix.GetRow ( 1 ) ), matrix.GetRow ( 2 ) ) < 0.0 ? true : false; tracks[i]->bMirror = bMirror; } TimeValue t = nStartTick; for( int nFrameId = 0; nFrameId < nFrameCount; nFrameId++, t += nTickPerFrame ) { SetProgressInfo( 100.0f*nFrameId/nFrameCount ); for( int nNodeId = 0; nNodeId < nNodeCount; nNodeId++ ) { INode* pNode = nodes[nNodeId]; Track* pTrack = tracks[nNodeId]; Matrix3 tm = pNode->GetNodeTM(t); // The coordinate system of 3DMax9 is Right-X Up-Z Screenin-Y // But coordinate system of SGP Engine is like D3D Right-X Up-Y Screenin-Z // Node Transform Matrix should be swaped. /* If your matrix looks like this: { rx, ry, rz, 0 } { ux, uy, uz, 0 } { lx, ly, lz, 0 } { px, py, pz, 1 } To change it from left to right or right to left, flip it like this: { rx, rz, ry, 0 } { lx, lz, ly, 0 } { ux, uz, uy, 0 } { px, pz, py, 1 } */ Point3 Row0 = tm.GetRow(0); Point3 Row1 = tm.GetRow(1); Point3 Row2 = tm.GetRow(2); Point3 Row3 = tm.GetRow(3); sgp::swapVariables( Row0.y, Row0.z ); sgp::swapVariables( Row1.x, Row2.x ); sgp::swapVariables( Row1.y, Row2.z ); sgp::swapVariables( Row1.z, Row2.y ); sgp::swapVariables( Row3.y, Row3.z ); tm.SetRow(0, Row0); tm.SetRow(1, Row1); tm.SetRow(2, Row2); tm.SetRow(3, Row3); Point3 trans; Quat quat; Point3 scale; { // calculate the translation component Point3 p; p = tm.GetTrans(); trans.x = p.x; trans.y = p.y; trans.z = p.z; scale.x = tm.GetRow(0).Length(); scale.y = tm.GetRow(1).Length(); scale.z = tm.GetRow(2).Length(); tm.NoScale(); // calculate the rotation component Quat q(tm); if( tracks[nNodeId]->bMirror ) { float m[4][3]; memcpy( m, &tm, sizeof(float)*4*3 ); m[0][0] *= -1; m[1][0] *= -1; m[2][0] *= -1; Matrix3 mm(m); Quat q0(mm); q = q0; } quat.x = q.x; quat.y = q.y; quat.z = q.z; quat.w = q.w; } pTrack->vectorTrans.getReference(nFrameId) = trans; pTrack->vectorRot.getReference(nFrameId) = quat; pTrack->vectorScale.getReference(nFrameId) = scale; float fv = pNode->GetVisibility( t ); if( fv == 0 ) pTrack->vectorVisible.getReference(nFrameId) = false; else pTrack->vectorVisible.getReference(nFrameId) = true; } } StopProgressInfo(); }
void Import::ApplyModifiers (dScene& scene, const MaxNodeChache& maxNodeCache) { dScene::Iterator iter (scene); for (iter.Begin(); iter; iter ++) { dScene::dTreeNode* meshNode = iter.GetNode(); dNodeInfo* info = scene.GetInfoFromNode(meshNode); if (info->IsType(dGeometryNodeInfo::GetRttiType())) { dScene::dTreeNode* skinModifierNode = NULL; for (void* ptr = scene.GetFirstChild(meshNode); ptr; ptr = scene.GetNextChild(meshNode, ptr)) { dScene::dTreeNode* node = scene.GetNodeFromLink(ptr); dNodeInfo* info = scene.GetInfoFromNode(node); if (info->GetTypeId() == dGeometryNodeSkinModifierInfo::GetRttiType()) { skinModifierNode = node; break; } } if (skinModifierNode) { //create a skin modifier and add it Modifier* skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA); INode* maxNode = maxNodeCache.Find(meshNode)->GetInfo(); _ASSERTE (maxNode); IDerivedObject *derob = NULL; Object* obj = maxNode->GetObjectRef(); if(obj->SuperClassID() != GEN_DERIVOB_CLASS_ID) { derob = CreateDerivedObject(obj); maxNode->SetObjectRef(derob); } else { derob = (IDerivedObject*) obj; } derob->AddModifier(skinMod); dGeometryNodeSkinModifierInfo* skinModifier = (dGeometryNodeSkinModifierInfo*) scene.GetInfoFromNode(skinModifierNode); dMatrix matrix (skinModifier->m_shapeBindMatrix); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetSkinTm(maxNode, bindPoseMatrix, bindPoseMatrix); int maxNodeCount = 0; INode* maxNodes[1024]; for (void* ptr = scene.GetFirstChild(skinModifierNode); ptr; ptr = scene.GetNextChild(skinModifierNode, ptr)) { dScene::dTreeNode* boneNode = scene.GetNodeFromLink(ptr); INode* skelBone = maxNodeCache.Find(boneNode)->GetInfo(); maxNodes[maxNodeCount] = skelBone; maxNodeCount ++; skelBone->SetBoneNodeOnOff(TRUE, 0); skelBone->BoneAsLine(TRUE); skelBone->ShowBone(1); if (iskinImport->AddBoneEx(skelBone, TRUE)) { dSceneNodeInfo* sceneNode = (dSceneNodeInfo*) scene.GetInfoFromNode(boneNode); dMatrix matrix (sceneNode->GetTransform()); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetBoneTm(skelBone, bindPoseMatrix, bindPoseMatrix); } } // must evaluate the node after adding bones maxNode->EvalWorldState(0); for (int i = 0; i < skinModifier->m_vertexCount; i ++) { Tab<float> weightList; Tab<INode*> boneNodeList; for (int j = 0; j < 4; j ++) { if (skinModifier->m_vertexWeights[i][j] > 1.0e-5f) { int boneIndex = skinModifier->m_boneWeightIndex[i].m_index[j]; INode *skelBone = maxNodes[boneIndex]; _ASSERTE (skelBone); boneNodeList.Append (1, &skelBone); weightList.Append (1, &skinModifier->m_vertexWeights[i][j]); } } iskinImport->AddWeights(maxNode, i, boneNodeList, weightList); } } } } }