//This will set the formation void FormationBhvr::SetFormation(TimeValue t) { INode *node; Matrix3 tempMatrix; //Make sure that the leader is not part of the follower array.. RemoveLeaderFromFormation(t); INode *leader = GetLeader(t); if(leader==NULL) return; Matrix3 leaderPosition = GetCurrentMatrix(leader,t); leaderPosition.NoScale(); //kill any scale if we have it leaderPosition.Invert(); //it's inverted... int numDelegates = GetFollowerCount(t); //zero out the formation matrix that's used for saving it out. pblock->ZeroCount(follower_matrix1); pblock->ZeroCount(follower_matrix2); pblock->ZeroCount(follower_matrix3); pblock->ZeroCount(follower_matrix4); for(int i =0;i<numDelegates;i++) { node = GetFollower(t,i); if(node) { tempMatrix = GetCurrentMatrix(node,t); tempMatrix.NoScale(); Matrix3 leaderMat =tempMatrix*leaderPosition; AppendFollowerMatrix(t,leaderMat); //killed because matrix3 wasn't working ...pblock->Append(follower_matrix,1,&leaderMat); } else { //we still set up follower_matrix so that the counts //of the follower_matrix tab and the follower tab are equal. tempMatrix.IdentityMatrix(); AppendFollowerMatrix(t,tempMatrix); //pblock->Append(follower_matrix,1,&tempMat); } } }
void SplineData::RotateSelectedCrossSections(Quat q) { Tab<int> selSplines; Tab<int> selCrossSections; GetSelectedCrossSections(selSplines,selCrossSections); //move the cross sections for (int i = 0; i < selSplines.Count(); i++) { int splineIndex = selSplines[i]; int crossSectionIndex = selCrossSections[i]; SplineCrossSection *section = GetCrossSection(splineIndex,crossSectionIndex); Matrix3 sTM = section->mTM; sTM.NoScale(); sTM.NoTrans(); Quat tq = TransformQuat(sTM,q); //no back into our initial space tq = TransformQuat(section->mIBaseTM,tq); section->mQuat += tq; } RecomputeCrossSections(); }
void makBoneTrans2(INode* pNode , sBoneTrans_t& boneTrans , Matrix3& mat) { Point3 Trans = mat.GetTrans(); Matrix3 RotMat = mat; Matrix3 ScaleMat = mat; RotMat.NoScale(); ScaleMat = mat * Inverse(RotMat); //算出Scale Matrix; RotMat.NoTrans(); Quat RotQuat(RotMat); //ScaleMat.NoRot(); //ScaleMat.NoTrans(); boneTrans.m_Rotate = conv_type<sQuat_t , Quat>(RotQuat); boneTrans.m_Trans = conv_type<sVector_t ,Point3 >(Trans); boneTrans.m_Scale.x = ScaleMat.GetRow(0).x; boneTrans.m_Scale.y = ScaleMat.GetRow(1).y; boneTrans.m_Scale.z = ScaleMat.GetRow(2).z; if( abs(boneTrans.m_Scale.x - boneTrans.m_Scale.y) > 0.000001 || abs(boneTrans.m_Scale.y - boneTrans.m_Scale.z) > 0.000001 || abs(boneTrans.m_Scale.z - boneTrans.m_Scale.x) > 0.000001 ) { std::wstring _NodeName = INodeName(pNode); XEVOL_LOG(eXL_DEBUG_HIGH , L" {警告} : 骨头[ %s ] 的上有NonUniformScale\r\n", _NodeName.c_str() ); } }
//The display function that is used to display the formation. int FormationBhvr::Display(TimeValue t, ViewExp *vpt) { // setup int i,j; if(DisplayFormation(t)==FALSE) return FALSE; if(GetFollowerCount(t)<=0) return FALSE; if(GetFollowerMatrixCount(t)<=0) return FALSE; INode *leaderNode; leaderNode = GetLeader(t); if(leaderNode==NULL) return FALSE; //check tgo see if we have created a default sphere for drawing yet... //if we haven't then create it.. if (numpts == 0) GetSpherePoints(Point3(0.0f,0.0f,0.0f), 1.0, SpherePts); GraphicsWindow *gw = vpt->getGW(); //set the identity matrix... Matrix3 idMat; idMat.IdentityMatrix(); gw->setTransform(idMat); gw->setColor(LINE_COLOR,.815f,.976f,1.0f); float scaleRadius = GetDisplayScale(t); //set the drawing radius values based upon what the radius size is. for (i=0; i<NUMAROUND * 3; i++) ScaledPts[i] = ((SpherePts[i] * scaleRadius)); //for each follower we need to increase the bounding box by it's //world position location... for(i =0;i<GetFollowerCount(t);i++) { INode *followerNode = GetFollower(t,i); if(followerNode) //if we have a a node... { Matrix3 leaderMat = GetCurrentMatrix(leaderNode,t); leaderMat.NoScale(); Matrix3 followerMat = GetFollowerMatrix(t,i); Matrix3 worldSpace = followerMat *leaderMat; for (j=0; j<NUMAROUND * 3; j++) CurPts[j] = worldSpace*ScaledPts[j]; //adding the center to the point positions gw->polyline(NUMAROUND,&CurPts[0],NULL,NULL,TRUE,NULL); gw->polyline(NUMAROUND,&CurPts[NUMAROUND],NULL,NULL,TRUE,NULL); gw->polyline(NUMAROUND,&CurPts[NUMAROUND * 2],NULL,NULL,TRUE,NULL); } } return TRUE; }
Matrix3 MshExp::TransformNode(INode* pNode,TimeValue CurTime, int TransformType){ Matrix3 mat; switch((TransformType&0xff)) { case TN_AFTER_WORLD://After World mat = pNode->GetObjTMAfterWSM(CurTime); break; case TN_BEFORE_WORLD://Before World mat = pNode->GetObjTMBeforeWSM(CurTime); break; case TN_TRANSFORM: mat = pNode->GetNodeTM(CurTime); break; default: mat = Matrix3(1); break; } if(TransformType&TN_NO_TRANSLATION) mat.NoTrans(); if(TransformType&TN_NO_ROTATION) mat.NoRot(); if(TransformType&TN_NO_SCALE) mat.NoScale(); return mat; }
void ProtHelpObject::GetMat(TimeValue t, INode* inode, ViewExp& vpt, Matrix3& tm) { if ( ! vpt.IsAlive() ) { tm.Zero(); return; } tm = inode->GetObjectTM(t); tm.NoScale(); float scaleFactor = vpt.NonScalingObjectSize() * vpt.GetVPWorldWidth(tm.GetTrans()) / 360.0f; tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor)); }
void SplineData::AlignCrossSection(int splineIndex, int crossSectionIndex,Point3 vec) { if ((splineIndex >= 0) && (splineIndex < mSplineElementData.Count())) { int numCrossSections = NumberOfCrossSections(splineIndex); if ((crossSectionIndex >= 0) && (crossSectionIndex < numCrossSections)) { //put the vec in spline space SplineCrossSection *crossSection = GetCrossSection(splineIndex,crossSectionIndex); Matrix3 crossSectionTM = crossSection->mTM; crossSectionTM.NoScale(); crossSectionTM.NoTrans(); Matrix3 icrossSectionTM = Inverse(crossSectionTM); Point3 crossSectionZVec = crossSection->mTangentNormalized; Point3 yvec = Normalize(vec); Point3 xvec = Normalize(CrossProd(yvec,crossSectionZVec)); Point3 zvec = Normalize(CrossProd(xvec,yvec)); Matrix3 rtm(1); rtm.SetRow(0,xvec); rtm.SetRow(1,yvec); rtm.SetRow(2,zvec); rtm.SetRow(3,Point3(0.0f,0.0f,0.0f)); Matrix3 relativeTM = crossSection->mIBaseTM * rtm; Quat q(relativeTM); q = TransformQuat(crossSection->mIBaseTM,q); crossSection->mQuat = q; return; } } DbgAssert(0); }
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(); }
Matrix3 SGP_MaxInterface::GetNodeTM(INode *pNode, float time) { // initialize matrix with the identity Matrix3 tm; tm.IdentityMatrix(); // only do this for valid nodes if(pNode != NULL) { // get the node transformation tm = pNode->GetNodeTM(SecToTicks(time)); // make the transformation uniform tm.NoScale(); } return tm; }
void SplineData::MoveSelectedCrossSections(Point3 vec) { Tab<int> selSplines; Tab<int> selCrossSections; GetSelectedCrossSections(selSplines,selCrossSections); if (selSplines.Count() == 0) return; //get the spline length float l = mSplineElementData[selSplines[0]]->GetSplineLength(); //get the sel cross u SplineCrossSection *section = GetCrossSection(selSplines[0],selCrossSections[0]); //transform into spline space Matrix3 sTM = section->mTM; sTM.NoScale(); Point3 tv = VectorTransform(sTM,vec); //no back into our initial space Point3 v = VectorTransform(section->mIBaseTM,tv); //compute how much u to move float incU = v.z/l; //move the cross sections for (int i = 0; i < mSplineElementData.Count(); i++) { if (mSplineElementData[i]->IsSelected()) { for (int j = 0; j < (NumberOfCrossSections(i)); j++) { if (CrossSectionIsSelected(i,j)) { SplineCrossSection *section = GetCrossSection(i,j); Matrix3 sTM = section->mTM; sTM.NoScale(); tv = VectorTransform(sTM,vec); v = VectorTransform(section->mIBaseTM,tv); float tempU = section->mOffset.z + incU; if (tempU > 1.0f) tempU = 1.0f; if (tempU < 0.0f) tempU = 0.0f; float prevU = 0.0f; if (j != 0) prevU = GetCrossSection(i,j-1)->mOffset.z; float nextU = 1.0; if ((j+1) < NumberOfCrossSections(i)) nextU = GetCrossSection(i,j+1)->mOffset.z; if ((tempU < nextU) && (tempU > prevU)) { //we cant slide the end/start cross sections if ((j != 0) && (j != NumberOfCrossSections(i)-1)) section->mOffset.z = tempU; } section->mOffset.x += v.x; section->mOffset.y += v.y; } } } } RecomputeCrossSections(); }
int FormationBhvr::Perform(INode *node, TimeValue t, int numsubsamples, BOOL DisplayHelpers, float BhvrWeight, PerformOut &out) { Object *o = node->GetObjectRef(); if (o->ClassID() != DELEG_CLASSID) return FALSE; // this should never happen IDelegate *IDeleg = (IDelegate *) o->GetInterface(I_DELEGINTERFACE); Point3 vel= IDeleg->GetCurrentVelocity(); Point3 pos = IDeleg->GetCurrentPosition(); INode *leader = GetLeader(t); if(leader==NULL) return 0; Matrix3 formationMat; //Get the local formation matrix and check if(FindFollowerMatrix(t,node,formationMat)==FALSE) return 0; //that node doesn't exist in the formation so exit. //returned values. Point3 frc,goal; float speedwt, speedAtGoalwt; //Find the Formation Position Target in World Space. Matrix3 currentLeaderMat = GetCurrentMatrix(leader,t); currentLeaderMat.NoScale(); Matrix3 worldSpace = formationMat*currentLeaderMat; Point3 target = worldSpace.GetTrans(); //set the goal as the target goal = target; //set the force as the direction to move towards the target frc = goal - pos; float length = frc.FLength(); if(length!=0.0f) //we are not at the goal { frc /=length; //set up the leader Vector Point3 leaderVec = leaderVel*leaderSpeed; //If the target is behind you but moving towards you don't turn around to //go toward it. Instead move in the direction of the leader. if(frc%vel<0.0f && //if you are behind it length/IDeleg->GetAverageSpeed(t)<10 && //AND less than 20 frames vel%leaderVel>0.0f) //AND it is going toward you. { //set frc as leader's Velocity. frc = leaderVel; //move at half the leaderSpeed. Leader will still catch //up to you and you'll have some speed when it does. //set the speewt speedwt = (leaderSpeed*0.5f)/IDeleg->GetAverageSpeed(t); } else //we should just move towards the target. { //We need to find the speed to be it. We do this by //finding the time we will intersect our target based //upon the leader's velocity and our own velocity. vel -= leaderVec; //find time to intersect.. float newSpeed = vel.FLength(); float timeToIntersect = length/newSpeed; //from that time.. figure out what it speed should be.. newSpeed = timeToIntersect * IDeleg->GetMaxAccel(t); if(newSpeed>IDeleg->GetAverageSpeed(t)) newSpeed = IDeleg->GetAverageSpeed(t); //check to see if we will move past the goal.. if so //move the goal along the leader vec. This reduces overshooting //the goal and decreases wobbling. if((newSpeed+leaderSpeed)>length) { goal += leaderVel*(leaderSpeed); frc = goal -pos; float newLength = frc.FLength(); if(newLength!=0.0f) //check for if zero to avoid divide by zero.. { frc /= newLength; speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t); } else { speedwt = 0.0f; } } else //far enough away.. leave the ole frc value.. speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t); } } else //we are at the goal { frc.x = frc.y = frc.z = 0.0f; //set the speedwt to be the leaderSpeed speedwt = leaderSpeed/IDeleg->GetAverageSpeed(t); } frc *= BhvrWeight *IDeleg->GetAverageSpeed(t); //scale by weight and average speed.. //set the speedWtAtGoal.. We want it to be the speed of the leader speedAtGoalwt = leaderSpeed/IDeleg->GetAverageSpeed(t); //Display Any Helpers. if (DisplayHelpers && IDeleg->OkToDisplayMyForces()) { if (DisplayTarget(t)) IDeleg->SphereDisplay(goal,pblock->GetFloat(target_scale),GetTargetColor(t)); if (DisplayForce(t)) IDeleg->LineDisplay(IDeleg->GetCurrentPosition(),IDeleg->GetCurrentPosition()+frc,GetForceColor(t),TRUE); } //set up the out structure.. out.frc = frc; out.goal = goal; out.speedwt = speedwt; out.speedAtGoalwt = speedAtGoalwt; return BHVR_SETS_FORCE | BHVR_SETS_GOAL | BHVR_SETS_SPEED; }
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(); }