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 CExportNel::addSkeletonBindPos (INode& skinedNode, mapBoneBindPos& boneBindPos) { // Return success uint ok=NoError; // Get the skin modifier Modifier* skin=getModifier (&skinedNode, SKIN_CLASS_ID); // Found it ? if (skin) { // Get a com_skin2 interface ISkin *comSkinInterface=(ISkin*)skin->GetInterface (SKIN_INTERFACE); // Should been controled with isSkin before. nlassert (comSkinInterface); // Found com_skin2 ? if (comSkinInterface) { // Get local data ISkinContextData *localData=comSkinInterface->GetContextInterface(&skinedNode); // Should been controled with isSkin before. nlassert (localData); // Found ? if (localData) { // Check same vertices count uint vertCount=localData->GetNumPoints(); // For each vertex for (uint vert=0; vert<vertCount; vert++) { // Get bones count for this vertex uint boneCount=localData->GetNumAssignedBones (vert); // For each bones for (uint bone=0; bone<boneCount; bone++) { // Get the bone id int boneId=localData->GetAssignedBone(vert, bone); // Get bone INode* INode *boneNode=comSkinInterface->GetBone(boneId); // Get the bind matrix of the bone Matrix3 bindPos; comSkinInterface->GetBoneInitTM(boneNode, bindPos); // Add an entry inthe map boneBindPos.insert (mapBoneBindPos::value_type (boneNode, bindPos)); } } } // Release the interface skin->ReleaseInterface (SKIN_INTERFACE, comSkinInterface); } } else { // Get the skin modifier Modifier* skin=getModifier (&skinedNode, PHYSIQUE_CLASS_ID); // Should been controled with isSkin before. nlassert (skin); // Found it ? if (skin) { // Get a com_skin2 interface IPhysiqueExport *physiqueInterface=(IPhysiqueExport *)skin->GetInterface (I_PHYINTERFACE); // Should been controled with isSkin before. nlassert (physiqueInterface); // Found com_skin2 ? if (physiqueInterface) { // Get local data IPhyContextExport *localData=physiqueInterface->GetContextInterface(&skinedNode); // Should been controled with isSkin before. nlassert (localData); // Found ? if (localData) { // Use rigid export localData->ConvertToRigid (TRUE); // Allow blending localData->AllowBlending (TRUE); // Check same vertices count uint vertCount=localData->GetNumberVertices(); // For each vertex for (uint vert=0; vert<vertCount; vert++) { if (vert==111) int toto=0; // Get a vertex interface IPhyVertexExport *vertexInterface=localData->GetVertexInterface (vert); // Check if it is a rigid vertex or a blended vertex int type=vertexInterface->GetVertexType (); if (type==RIGID_TYPE) { // this is a rigid vertex IPhyRigidVertex *rigidInterface=(IPhyRigidVertex*)vertexInterface; // Get bone INode* INode *bone=rigidInterface->GetNode(); // Get the bind matrix of the bone Matrix3 bindPos; int res=physiqueInterface->GetInitNodeTM (bone, bindPos); nlassert (res==MATRIX_RETURNED); // Add an entry inthe map if (boneBindPos.insert (mapBoneBindPos::value_type (bone, bindPos)).second) { #ifdef NL_DEBUG // *** Debug info // Bone name std::string boneName=getName (*bone); // Local matrix Matrix3 nodeTM; nodeTM=bone->GetNodeTM (0); // Offset matrix Matrix3 offsetScaleTM (TRUE); Matrix3 offsetRotTM (TRUE); Matrix3 offsetPosTM (TRUE); ApplyScaling (offsetScaleTM, bone->GetObjOffsetScale ()); offsetRotTM.SetRotate (bone->GetObjOffsetRot ()); offsetPosTM.SetTrans (bone->GetObjOffsetPos ()); Matrix3 offsetTM = offsetScaleTM * offsetRotTM * offsetPosTM; // Local + offset matrix Matrix3 nodeOffsetTM = offsetTM * nodeTM; // Init TM Matrix3 initTM; int res=physiqueInterface->GetInitNodeTM (bone, initTM); nlassert (res==MATRIX_RETURNED); // invert initTM.Invert(); Matrix3 compNode=nodeTM*initTM; Matrix3 compOffsetNode=nodeOffsetTM*initTM; Matrix3 compOffsetNode2=nodeOffsetTM*initTM; #endif // NL_DEBUG } } else { // It must be a blendable vertex nlassert (type==RIGID_BLENDED_TYPE); IPhyBlendedRigidVertex *blendedInterface=(IPhyBlendedRigidVertex*)vertexInterface; // For each bones uint boneIndex; uint count=(uint)blendedInterface->GetNumberNodes (); for (boneIndex=0; boneIndex<count; boneIndex++) { // Get the bone pointer INode *bone = blendedInterface->GetNode(boneIndex); if (bone == NULL) { nlwarning("bone == NULL; boneIndex = %i / %i", boneIndex, count); } else { // Get the bind matrix of the bone Matrix3 bindPos; int res = physiqueInterface->GetInitNodeTM (bone, bindPos); if (res != MATRIX_RETURNED) { nlwarning("res != MATRIX_RETURNED; res = %i; boneIndex = %i / %i", res, boneIndex, count); nlwarning("bone = %i", (uint32)(void *)bone); std::string boneName = getName (*bone); nlwarning("boneName = %s", boneName.c_str()); nlassert(false); } // Add an entry inthe map if (boneBindPos.insert (mapBoneBindPos::value_type (bone, bindPos)).second) { #ifdef NL_DEBUG // *** Debug info // Bone name std::string boneName=getName (*bone); // Local matrix Matrix3 nodeTM; nodeTM=bone->GetNodeTM (0); // Offset matrix Matrix3 offsetScaleTM (TRUE); Matrix3 offsetRotTM (TRUE); Matrix3 offsetPosTM (TRUE); ApplyScaling (offsetScaleTM, bone->GetObjOffsetScale ()); offsetRotTM.SetRotate (bone->GetObjOffsetRot ()); offsetPosTM.SetTrans (bone->GetObjOffsetPos ()); Matrix3 offsetTM = offsetScaleTM * offsetRotTM * offsetPosTM; // Local + offset matrix Matrix3 nodeOffsetTM = offsetTM * nodeTM; // Init TM Matrix3 initTM; int res=physiqueInterface->GetInitNodeTM (bone, initTM); nlassert (res==MATRIX_RETURNED); // invert initTM.Invert(); Matrix3 compNode=nodeTM*initTM; Matrix3 compOffsetNode=nodeOffsetTM*initTM; Matrix3 compOffsetNode2=nodeOffsetTM*initTM; #endif // NL_DEBUG } } } } // Release vertex interfaces localData->ReleaseVertexInterface (vertexInterface); } // Release locaData interface physiqueInterface->ReleaseContextInterface (localData); } // Release the interface skin->ReleaseInterface (SKIN_INTERFACE, physiqueInterface); } } } }
// *************************************************************************** void CExportNel::getNELBoneLocalScale(INode &node, TimeValue time, NLMISC::CVector &nelScale) { // To get the correct local Scale, we use an other bone as reference (if present) INode *referenceNode= getNELScaleReferenceNode(node); // get the Max local pos. Matrix3 localTM (TRUE); getLocalMatrix (localTM, node, time); NLMISC::CVector maxScale; NLMISC::CQuat maxRot; NLMISC::CVector maxPos; decompMatrix (maxScale, maxRot, maxPos, localTM); // Biped node case, take the scale from ratio with the reference node. if(isBipedNode(node)) { // Replace scale with ratio from reference value, if possible if (referenceNode) { ScaleValue scaleValue; // get my Offset scale. CVector myScale; scaleValue = node.GetObjOffsetScale(); myScale.x= scaleValue.s.x; myScale.y= scaleValue.s.y; myScale.z= scaleValue.s.z; // get its Offset scale. CVector refScale; scaleValue = referenceNode->GetObjOffsetScale(); refScale.x= scaleValue.s.x; refScale.y= scaleValue.s.y; refScale.z= scaleValue.s.z; // Get The ratio as the result nelScale.x= myScale.x / refScale.x; nelScale.y= myScale.y / refScale.y; nelScale.z= myScale.z / refScale.z; } else { // Not present, suppose no scale. nelScale.set(1,1,1); } } // get the scale from std way. else { // We are a normal node here, not biped. /* If this node do not inherit scale (ie must unherit), then we must not take the localScale computed with getLocalMatrix. In this case, the local Scale is simply the NodeTM scale. */ if( getNELUnHeritFatherScale(node) ) { Matrix3 nodeTM; nodeTM = node.GetNodeTM (time); decompMatrix (maxScale, maxRot, maxPos, nodeTM); // Get the scale from worldMatrix. nelScale= maxScale; } else { // Get the scale from localMatrix. nelScale= maxScale; } } }
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); }