void VRayCamera::getTM(TimeValue t, INode *node, ViewExp *vpt, Matrix3 &tm) { tm=node->GetObjectTM(t); AffineParts ap; decomp_affine(tm, &ap); tm.IdentityMatrix(); tm.SetRotate(ap.q); tm.SetTrans(ap.t); float scaleFactor=vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/360.0f; tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor)); }
// Luna task 748T void ConvertPathToFrenets (Spline3D *pSpline, Matrix3 & relativeTransform, Tab<Matrix3> & tFrenets, int numSegs, bool align, float rotateAroundZ) { // Given a path, a sequence of points in 3-space, create transforms // for putting a cross-section around each of those points, loft-style. // bezShape is provided by user, tFrenets contains output, numSegs is one less than the number of transforms requested. // Strategy: The Z-axis is mapped along the path, and the X and Y axes // are chosen in a well-defined manner to get an orthonormal basis. int i; if (numSegs < 1) return; tFrenets.SetCount (numSegs+1); int numIntervals = pSpline->Closed() ? numSegs+1 : numSegs; float denominator = float(numIntervals); Point3 xDir, yDir, zDir, location, tangent, axis; float position, sine, cosine, theta; Matrix3 rotation; // Find initial x,y directions: location = relativeTransform * pSpline->InterpCurve3D (0.0f); tangent = relativeTransform.VectorTransform (pSpline->TangentCurve3D (0.0f)); Point3 lastTangent = tangent; Matrix3 inverseBasisOfSpline(1); if (align) { theBasisFinder.BasisFromZDir (tangent, xDir, yDir); if (rotateAroundZ) { Matrix3 rotator(1); rotator.SetRotate (AngAxis (tangent, rotateAroundZ)); xDir = xDir * rotator; yDir = yDir * rotator; } Matrix3 basisOfSpline(1); basisOfSpline.SetRow (0, xDir); basisOfSpline.SetRow (1, yDir); basisOfSpline.SetRow (2, tangent); basisOfSpline.SetTrans (location); inverseBasisOfSpline = Inverse (basisOfSpline); lastTangent = Point3(0,0,1); } else { inverseBasisOfSpline.SetRow (3, -location); } // Make relative transform take the spline from its own object space to our object space, // and from there into the space defined by its origin and initial direction: relativeTransform = relativeTransform * inverseBasisOfSpline; // (Note left-to-right evaluation order: Given matrices A,B, point x, x(AB) = (xA)B // The first transform is necessarily the identity: tFrenets[0].IdentityMatrix (); // Set up xDir, yDir, zDir to match our first-point basis: xDir = Point3 (1,0,0); yDir = Point3 (0,1,0); zDir = Point3 (0,0,1); for (i=1; i<=numIntervals; i++) { position = float(i) / denominator; location = relativeTransform * pSpline->InterpCurve3D (position); tangent = relativeTransform.VectorTransform (pSpline->TangentCurve3D (position)); // This is the procedure we follow at each step in the path: find the // orthonormal basis with the right orientation, then compose with // the translation putting the origin at the path-point. // As we proceed along the path, we apply minimal rotations to // our original basis to keep the Z-axis tangent to the curve. // The X and Y axes follow in a natural manner. // xDir, yDir, zDir still have their values from last time... // Create a rotation matrix which maps the last tangent onto the current tangent: axis = lastTangent ^ tangent; // gives axis, scaled by sine of angle. sine = FLength(axis); // positive - keeps angle value in (0,PI) range. cosine = DotProd (lastTangent, tangent); // Gives cosine of angle. theta = atan2f (sine, cosine); rotation.SetRotate (AngAxis (Normalize(axis), theta)); xDir = Normalize (rotation * xDir); yDir = Normalize (rotation * yDir); zDir = Normalize (rotation * zDir); lastTangent = tangent; if (i<=numSegs) { tFrenets[i].IdentityMatrix (); tFrenets[i].SetRow (0, xDir); tFrenets[i].SetRow (1, yDir); tFrenets[i].SetRow (2, zDir); tFrenets[i].SetTrans (location); } } /* following code not needed for now - treating all splines as open. if (!pSpline->Closed ()) return; // If we have a closed loop, our procedure may result in X,Y vectors // that are twisted severely between the first and last point. // Here we correct for that by pre-transforming each frenet transform // by a small rotation around the Z-axis. (The last pass through the above // loop should give the final twist: the initial and final Z-axis directions // are the same, and the difference between the initial and final X-axis // directions is the total twist along the spline.) // Now we measure the difference between our original and final x-vectors: axis = originalXDir ^ xDir; sine = FLength (axis); cosine = DotProd (originalXDir, xDir); theta = atan2f (sine, cosine); for (i=1; i<=numSegs; i++) { rotation.SetRotate (AngAxis (Normalize(axis), -theta/denominator)); tFrenets[i] = rotation * tFrenets[i]; } */ }
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); } } } }