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());
}
示例#2
0
 void convertToTransform(Matrix<4,4,F32> & mat, Quaternion & rot, Point3D & trans, Quaternion & srot, Point3D & scale)
 {
     AffineParts parts;
     decomp_affine(mat,&parts);
     trans = parts.trans;
     rot = parts.rot;
     srot = parts.scaleRot;
     scale = parts.scale;
 }
示例#3
0
//=================================================================
// Methods for DumpFrameRotationsTEP
//
int DumpFrameRotationsTEP::callback(INode *pnode)
{
	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

	if (::FNodeMarkedToSkip(pnode))
		return TREE_CONTINUE;

	int iNode = ::GetIndexOfINode(pnode);

	TSTR strNodeName(pnode->GetName());

	// The model's root is a child of the real "scene root"
	INode *pnodeParent = pnode->GetParentNode();
	BOOL fNodeIsRoot = pnodeParent->IsRootNode( );

	// Get Node's "Local" Transformation Matrix
	Matrix3 mat3NodeTM		= pnode->GetNodeTM(m_tvToDump);
	Matrix3 mat3ParentTM	= pnodeParent->GetNodeTM(m_tvToDump);
	mat3NodeTM.NoScale();		// Clear these out because they apparently
	mat3ParentTM.NoScale();		// screw up the following calculation.
	Matrix3 mat3NodeLocalTM	= mat3NodeTM * Inverse(mat3ParentTM);
	Point3 rowTrans = mat3NodeLocalTM.GetTrans();

	// check to see if the parent bone was mirrored.  If so, mirror invert this bones position
	if (m_phec->m_rgmaxnode[iNode].imaxnodeParent >= 0 && m_phec->m_rgmaxnode[m_phec->m_rgmaxnode[iNode].imaxnodeParent].isMirrored)
	{
		rowTrans = rowTrans * -1.0f;
	}

	// Get the rotation (via decomposition into "affine parts", then quaternion-to-Euler)
	// Apparently the order of rotations returned by QuatToEuler() is X, then Y, then Z.
	AffineParts affparts;
	float rgflXYZRotations[3];

	decomp_affine(mat3NodeLocalTM, &affparts);
	QuatToEuler(affparts.q, rgflXYZRotations);

	float xRot = rgflXYZRotations[0];		// in radians
	float yRot = rgflXYZRotations[1];		// in radians
	float zRot = rgflXYZRotations[2];		// in radians

	// Get rotations in the -2pi...2pi range
	xRot = ::FlReduceRotation(xRot);
	yRot = ::FlReduceRotation(yRot);
	zRot = ::FlReduceRotation(zRot);
	
	// Print rotations
	fprintf(m_pfile, "%3d %f %f %f %f %f %f\n", 
		// Node:%-15s Rotation (x,y,z)\n",
		iNode, rowTrans.x, rowTrans.y, rowTrans.z, xRot, yRot, zRot);

	return TREE_CONTINUE;
}
示例#4
0
bool bgAnimMax::GetDecompAffine(TimeValue time, INode* pNode, AffineParts* pAP, Point3* pRotAxis, float* pRotAngle)
{
	Matrix3 tm = pNode->GetNodeTM(time) * Inverse(pNode->GetParentTM(time));
	decomp_affine(tm, pAP);

	Point3 vRotAxis;
	float  fRotAngle;
	if (pRotAngle != NULL && pRotAngle != NULL)
	{
		AngAxisFromQ(pAP->q, pRotAngle, *pRotAxis);
	}
	return true;
}
示例#5
0
bool TbsAnimObj::GetDecompAffine( TimeValue t, INode* pNode, AffineParts* ap, Point3* rotAxis, float* rotAngle )
{
	Matrix3 tm = pNode->GetNodeTM(t) * Inverse(pNode->GetParentTM(t));
	decomp_affine(tm, ap);

	Point3 vRotAxis;
	float  fRotAngle;
	if( rotAngle != NULL && rotAngle != NULL )
	{
		AngAxisFromQ(ap->q, rotAngle, *rotAxis);
	}
	return true;
}
示例#6
0
   void zapScale(Matrix<4,4,F32> & mat)
   {
      AffineParts parts;
      decomp_affine(mat,&parts);

      // now put the matrix back together again without the scale:
      // mat = mat.rot * mat.pos
      Vector<F32,4> trans;
      trans[0] = parts.trans.x();
      trans[1] = parts.trans.y();
      trans[2] = parts.trans.z();
      trans[3] = 1;
      mat = parts.rot.toMatrix();
      mat.setCol(3,trans);

#ifdef TEST_DTS_MATH
      {
         // A test...will get rid of once we know it works...
         Matrix<4,4,F32> mat2;
         decomp_affine(mat,&parts);
         trans[0] = parts.trans.x();
         trans[1] = parts.trans.y();
         trans[2] = parts.trans.z();
         trans[3] = 1;
         mat2 = parts.rot.toMatrix();
         mat2.setCol(3,trans);
         for (S32 i=0; i<4; i++)
         {
            for (S32 j=0; j<4; j++)
            {
               assert(isZero(mat[i][j]-mat2[i][j],0.01f));
            }
         }
      }
#endif
   }
//---------------------------------------------------------------------------
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;
}
示例#8
0
// REAPPLYANIMATION
// Now that we've reparented a node within the hierarchy, re-apply all its animation.
void ReapplyAnimation(INode *node, plSampleVec *samples)
{
    Control *controller = node->GetTMController();

    Control *rotControl = NewDefaultRotationController();   // we set the default rotation controller type above in RemoveBiped()
    Control *posControl = NewDefaultPositionController();   // '' ''
    Control *scaleControl = NewDefaultScaleController();    // '' ''
    
    controller->SetRotationController(rotControl);
    controller->SetPositionController(posControl);
    controller->SetScaleController(scaleControl);

    for(int i = 0; i < samples->size(); i++)
    {
        nodeTMInfo *info = (*samples)[i];
        Matrix3 m = info->fMat3;
        TimeValue t = info->fTime;

#if 1
        node->SetNodeTM(t, m);
#else
        AffineParts parts;

        INode *parent = node->GetParentNode();
        Matrix3 parentTM = parent->GetNodeTM(t);
        Matrix3 invParentTM = Inverse(parentTM);
        m *= invParentTM;

        decomp_affine(m, &parts);

        Quat q(parts.q.x, parts.q.y, parts.q.z, parts.q.w);
        Point3 p(parts.t.x, parts.t.y, parts.t.z);

        rotControl->SetValue(t, q);
        posControl->SetValue(t, p);
#endif
    }

    IKeyControl *posKeyCont = GetKeyControlInterface(posControl);
    IKeyControl *scaleKeyCont = GetKeyControlInterface(scaleControl);

    ReduceKeys<ILinPoint3Key>(node, posKeyCont);
    EliminateScaleKeys(node, scaleKeyCont);
    // grrrr ReduceKeys<ILinScaleKey>(node, scaleKeyCont);
}
示例#9
0
static void AddStaticPropPoints(std::vector<PropPoint> &propPoints, const FMMatrix44& upAxisTransform, FCDSceneNode* node)
{
	if (node->GetName().find("prop-") == 0 || node->GetName().find("prop_") == 0)
	{
		// Strip off the "prop-" from the name
		std::string propPointName (node->GetName().substr(5));

		Log(LOG_INFO, "Adding prop point %s", propPointName.c_str());

		// CalculateWorldTransform applies transformations recursively for all parents of this node
		// upAxisTransform transforms this node to right-handed Z_UP coordinates

		FMMatrix44 transform = upAxisTransform * node->CalculateWorldTransform();

		HMatrix matrix;
		memcpy(matrix, transform.Transposed().m, sizeof(matrix));

		AffineParts parts;
		decomp_affine(matrix, &parts);

		// Add prop point in game coordinates

		PropPoint p = {
			propPointName,
			
			// Flip translation across the x-axis by swapping y and z
			{ parts.t.x, parts.t.z, parts.t.y },

			// To convert the quaternions: imagine you're using the axis/angle
			// representation, then swap the y,z basis vectors and change the
			// direction of rotation by negating the angle ( => negating sin(angle)
			// => negating x,y,z => changing (x,y,z,w) to (-x,-z,-y,w)
			// but then (-x,-z,-y,w) == (x,z,y,-w) so do that instead)
			{ parts.q.x, parts.q.z, parts.q.y, -parts.q.w },

			0xff
		};
		propPoints.push_back(p);
	}

	// Search children for prop points
	for (size_t i = 0; i < node->GetChildrenCount(); ++i)
		AddStaticPropPoints(propPoints, upAxisTransform, node->GetChild(i));
}
示例#10
0
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());
}
示例#11
0
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);
}
示例#12
0
void AsciiExp::DumpRotSample(INode* node, int indentLevel) 
{	
	TSTR indent = GetIndent(indentLevel);
	
	_ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_ROT_TRACK);

	TimeValue start = ip->GetAnimRange().Start();
	TimeValue end = ip->GetAnimRange().End();
	TimeValue t;
	int delta = GetTicksPerFrame() * GetKeyFrameStep();
	Matrix3 tm;
	AffineParts ap;
	Quat prevQ;

	prevQ.Identity();

	for (t=start; t<=end; t+=delta) {
		tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));

		decomp_affine(tm, &ap);

		// Rotation keys should be relative, so we need to convert these
		// absolute samples to relative values.

		Quat q = ap.q / prevQ;
		prevQ = ap.q;

		if (q.IsIdentity()) {
			// No point in exporting null keys...
			continue;
		}

		// Output the sample
		_ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"),
			indent.data(),
			ID_ROT_SAMPLE,
			t,
			Format(q));
	}

	_ftprintf(pStream, _T("%s\t\t}\n"), indent.data());
}
示例#13
0
/** 
 * This method will check if there is any animation connected to the node.
 * It will run from start to end of animation range and if the position,
 * rotation or scale has been changed during this, it will return true.
 */
BOOL OSGExp::hasAnimation(INode* node){
	TimeValue start = _ip->GetAnimRange().Start();
	TimeValue end = _ip->GetAnimRange().End();
	TimeValue t;
	int delta = GetTicksPerFrame();
	Matrix3 tm;
	AffineParts ap;
	Point3 firstPos;
	float rotAngle, firstRotAngle;
	Point3 rotAxis, firstRotAxis;
	Point3 firstScaleFactor;
	//return TRUE;

	for (t=start; t<=end; t+=delta) {

		tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));

		decomp_affine(tm, &ap);

		AngAxisFromQ(ap.q, &rotAngle, rotAxis);

		// If any point, rotation or scale in the t'th frame has
		// changes from the start frame then we have an animation.
		if (t != start){
			if(!Util::isPoint3Equal(ap.t, firstPos) ||
				!Util::isPoint3Equal(rotAxis, firstRotAxis) ||
				fabs(rotAngle - firstRotAngle) > ALMOST_ZERO ||
				!Util::isPoint3Equal(ap.k, firstScaleFactor)){
				return TRUE;
			}
		}
		else {
			firstPos = ap.t;
			firstRotAngle = rotAngle;
			firstRotAxis = rotAxis;
			firstScaleFactor = ap.k;
		}
	}
	return FALSE;
}
示例#14
0
/**
 * This method will sample the node at each frame to get any possible change
 * of position, rotation and scaling. The posible changes is inserted into an
 * OSG AnimationPath and returned.
 */
osg::AnimationPath* OSGExp::sampleNode(INode* node){

    // Create the animation path.
    osg::AnimationPath* animationPath = new osg::AnimationPath();
    animationPath->setLoopMode(osg::AnimationPath::LOOP);

	TimeValue start = _ip->GetAnimRange().Start();
	TimeValue end = _ip->GetAnimRange().End();
	int val;
	if (node->GetUserPropInt("startFrame",val))
		start= val;
	if (node->GetUserPropInt("endFrame",val))
		end= val;
	TimeValue t;
	int delta = GetTicksPerFrame();
	Matrix3 tm;
	AffineParts ap;

	for (t=start; t<=end; t+=delta) {
		tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
		decomp_affine(tm, &ap);
		Point3 pos = ap.t;
		Point3 sca = ap.k;

		// Note: OSG wants absolute rotations
		Quat rot = ap.q;

		// Convert from Max's left-handed rotation to right-handed
		float ang;
		Point3 axis;
		AngAxisFromQ(rot, &ang, axis);
		ang = -ang;
		rot = QFromAngAxis(ang, axis);
 
		// Insert the sample point into animation path
		addControlPoint(animationPath, (t/(float)TIME_TICKSPERSEC), pos, rot, sca);
	}
	return animationPath;
}
示例#15
0
void AsciiExp::DumpPosSample(INode* node, int indentLevel) 
{	
	TSTR indent = GetIndent(indentLevel);
	
	_ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_POS_TRACK);

	TimeValue start = ip->GetAnimRange().Start();
	TimeValue end = ip->GetAnimRange().End();
	TimeValue t;
	int delta = GetTicksPerFrame() * GetKeyFrameStep();
	Matrix3 tm;
	AffineParts ap;
	Point3	prevPos;

	for (t=start; t<=end; t+=delta) {
		tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
		decomp_affine(tm, &ap);

		Point3 pos = ap.t;

		if (t!= start && EqualPoint3(pos, prevPos)) {
			// Skip identical keys 
			continue;
		}

		prevPos = pos;

		// Output the sample
		_ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"),
			indent.data(),
			ID_POS_SAMPLE,
			t,
			Format(pos));
	}

	_ftprintf(pStream, _T("%s\t\t}\n"), indent.data());
}
示例#16
0
文件: cppout.cpp 项目: 2asoft/xray
void 
CppOut::OutputObject(INode *node,TCHAR *fname)
{
    ObjectState os = node->EvalWorldState(theCppOut.ip->GetTime());
    assert(os.obj->SuperClassID()==GEOMOBJECT_CLASS_ID);
    BOOL needDel;
    NullView nullView;
    Mesh *mesh = ((GeomObject*)os.obj)->GetRenderMesh(ip->GetTime(),
                                                      node,nullView,needDel);
    if (!mesh) return;

    FILE *file = fopen(fname,_T("wt"));

    float maxLen = 0.0f, len;
    int i;
    Matrix3 tm = node->GetObjTMAfterWSM(theCppOut.ip->GetTime());
    AffineParts parts;
    decomp_affine(tm, &parts);

    if (file) {
        Box3 bb = mesh->getBoundingBox() * tm;
        Point3 center = bb.Center();
        for (i=0; i<mesh->getNumVerts(); i++) {
            Point3 v = tm * mesh->verts[i] - center;
            len = Length(v);
            if (len > maxLen)
                maxLen = len;
        }
        fprintf(file, "    mesh.setNumVerts(%d);\n", mesh->getNumVerts());
        fprintf(file, "    mesh.setNumFaces(%d);\n", mesh->getNumFaces());
        for (i=0; i<mesh->getNumVerts(); i++) {
            Point3 v = (tm  * mesh->verts[i] - center) / maxLen;
            fprintf(file,"    mesh.setVert(%d, size * Point3(%f,%f,%f));\n",
                    i, v.x, v.y, v.z);
        }

        for (i=0; i<mesh->getNumFaces(); i++) {
            if (parts.f < 0.0f)
                fprintf(file,"    mesh.faces[%d].setVerts(%d,%d,%d);\n",
                        i, mesh->faces[i].v[1], mesh->faces[i].v[0],
                        mesh->faces[i].v[2]);
            else
                fprintf(file,"    mesh.faces[%d].setVerts(%d,%d,%d);\n",
                        i, mesh->faces[i].v[0], mesh->faces[i].v[1],
                        mesh->faces[i].v[2]);
            if (parts.f < 0.0f) 
                fprintf(file,"    mesh.faces[%d].setEdgeVisFlags(%d,%d,%d);\n",
                        i,
                        mesh->faces[i].getEdgeVis(0) ? 1 : 0,
                        mesh->faces[i].getEdgeVis(2) ? 1 : 0,
                        mesh->faces[i].getEdgeVis(1) ? 1 : 0);
            else
                fprintf(file,"    mesh.faces[%d].setEdgeVisFlags(%d,%d,%d);\n",
                        i,
                        mesh->faces[i].getEdgeVis(0) ? 1 : 0,
                        mesh->faces[i].getEdgeVis(1) ? 1 : 0,
                        mesh->faces[i].getEdgeVis(2) ? 1 : 0);
            fprintf(file,"    mesh.faces[%d].setSmGroup(%x);\n",
                    i, mesh->faces[i].smGroup);
        }
		
        fclose(file);
    }	
    if (needDel) delete mesh;
}
示例#17
0
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;
	}
}
示例#18
0
void XsiExp::DumpScaleKeys( INode * node, int indentLevel) 
{
  Control * cont = node->GetTMController()->GetScaleController();
	IKeyControl * ikc = GetKeyControlInterface(cont);
	INode * parent = node->GetParentNode();
	if (!cont || !parent || (parent && parent->IsRootNode()) || !ikc)
  {
    // no controller or root node
		return;
  }
	int numKeys = ikc->GetNumKeys();
	if (numKeys <= 1)
  {  
    return;
  }
	Object * obj = node->EvalWorldState(0).obj;
  BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE;

  // anim keys header
  TSTR indent = GetIndent(indentLevel);
	fprintf(pStream,"%s\tSI_AnimationKey {\n", indent.data()); 
	fprintf(pStream,"%s\t\t1;\n", indent.data());     // 1 means scale keys
	fprintf(pStream,"%s\t\t%d;\n", indent.data(), numKeys);

	int t, delta = GetTicksPerFrame();
 	Matrix3 matrix;
  AffineParts ap;
	for (int i = 0; i < numKeys; i++)
  {  
    // get the key's time
	  if (cont->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0))
    {
  	  ITCBRotKey key;
			ikc->GetKey(i, &key);
      t = key.time;
    }
    else if (cont->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0))
	  {
		  IBezQuatKey key;
		  ikc->GetKey(i, &key);
      t = key.time;
    }
	  else if (cont->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0))
    {
  	  ILinRotKey key;
		  ikc->GetKey(i, &key);
      t = key.time;
    }
    // sample the node's matrix
    matrix = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
    if (!isBone)
    {
      matrix = matrix * topMatrix;
    }
    decomp_affine(matrix, &ap);

		fprintf(pStream, "%s\t\t%d; 3; %.6f, %.6f, %.6f;;%s\n", 
			indent.data(),
			t / delta,
			ap.k.x, ap.k.z, ap.k.y,
      i == numKeys - 1 ? ";\n" : ",");
	}
  // anim keys close
	fprintf(pStream,"%s\t}\n\n", indent.data());
}
void OrientConstRotation::Update(TimeValue t){
	Interval iv = FOREVER;
	ivalid = FOREVER;
	
	int ct = pblock->Count(orientation_target_list);
	int ctf = pblock->Count(orientation_target_weight);

	float total_orient_target_weight_prev = 0.0f, total_orient_target_weight_current = 0.0f;
	float orient_targ_Wt_current = 0.0f;
	Quat quat_prev, quat_current, lCurRot;
	INode *orient_target_prev= NULL, *orient_target_current= NULL;
	Matrix3 targetTM(1);
	Point3 trans, scaleP;

	quat_prev.Identity();
	quat_current.Identity();
	lCurRot.Identity();

		if (ct == 1){
			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}
		}
		else if (ct > 1){

			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
//			if (orient_target_prev != NULL)
//			{
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}

			for (int i = 0; i < ct -1; i++) {
//				ct = pblock->Count(orientation_target_list);
				pblock->GetValue(orientation_target_list, t, orient_target_current, iv, i+1);
				pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, i+1);
//				if (orient_target_current != NULL){
					ivalid &= iv;

					if (orient_target_current == NULL){
						targetTM.IdentityMatrix();
					}
					else {
						targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					}

//					Matrix3 targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					if (IsLocal() && orient_target_current != NULL) {
						targetTM = targetTM * Inverse(orient_target_current->GetParentTM(t));
					}
					AffineParts comps;		// Requires header decomp.h
					decomp_affine(targetTM, &comps);
					quat_current = comps.q;
					quat_current.Normalize();
					quat_current.MakeClosest(quat_prev);

					float slerp_wt = 0.0f;
					if ((total_orient_target_weight_prev + orient_targ_Wt_current) != 0.0){
						slerp_wt = orient_targ_Wt_current / (total_orient_target_weight_prev + orient_targ_Wt_current);
					}

					lCurRot = Slerp(quat_prev, quat_current, slerp_wt);
					lCurRot.Normalize();

					quat_prev = lCurRot;
					total_orient_target_weight_prev += orient_targ_Wt_current;
//				}
			}			//for (int i = 0; i < ct -1; i++)
		}				//else if (ct > 1)

		if (oldTargetNumber != ct) {
			InitialOrientQuat = lCurRot;
		}

		curRot = lCurRot;
		if (total_orient_target_weight_prev > 0.0){
			if (Relative()){
				if(IsLocal()){
					curRot =   baseRotQuatLocal * (lCurRot /InitialOrientQuat);
				}
				else{
					curRot =   baseRotQuatWorld * (lCurRot /InitialOrientQuat);
				}
			}
		}
		else {
			curRot = baseRotQuatLocal;
		}
		curRot.MakeClosest(IdentQuat());
		curRot.Normalize();
		oldTargetNumber = ct;
//	if (ivalid.Empty()) ivalid.SetInstant(t);
}
示例#20
0
//----------------------------------------------------------------------------------
bool DumpModel(IGameMesh *gM, m_model *pModel, IGameNode *pGameNode)
{
    IGameSkin *skin = NULL;

    if (gM->InitializeData()) // prepare game data
    {
        GMatrix ObjectTM = pGameNode->GetObjectTM(ExporterMAX::GetExporter()->GetStaticFrame());

        Matrix3 world_to_obj = Inverse(ObjectTM.ExtractMatrix3());

        AffineParts	PRS;
        decomp_affine(ObjectTM.ExtractMatrix3(), &PRS);

        //Matrix xform;
        //
        //xform.set_rot(Quaternion(-PRS.q.x, -PRS.q.z, PRS.q.y, PRS.q.w));
        //xform.set_translation(Vector(-PRS.t.x, PRS.t.z, PRS.t.y));

        const int numMod = gM->GetNumModifiers();

        if (numMod > 0)
        {
            for (int i = 0; i < numMod; i++)     // check for skin modifier
            {
                IGameModifier * pM = gM->GetIGameModifier(i);
                if (pM->IsSkin()) {
                    skin = (IGameSkin*)pM; // skin modifier
                }
            }
        }

        mesh_opt       *m_opt;
        TriMapType      tri_map;
        MatFaceMapType  matface_map; // int <-> material

        unsigned int max_face_idx = 0;
        unsigned int FaceNum = Helper_GetNumberOfFaces(gM, FaceNum, max_face_idx);

        for (size_t i = 0; i < FaceNum; ++i)
        {
            Helper_ProcessFace(gM, i, PRS, world_to_obj, matface_map, tri_map, max_face_idx);
        }

        Helper_ComputeNormals(gM, matface_map);

        for (size_t IndexAdd = 0; IndexAdd < tri_map.size(); ++IndexAdd)
        {
            pModel->meshes.push_back(new m_mesh());
        }

        int count = 0;

        TriMapIt it = tri_map.begin();

        while (it != tri_map.end())
        {
            m_mesh &msh = *pModel->meshes[count];

            msh.num_faces = (*it).second->size() / 3;

            msh.material_id = (*it).first;

            msh.faces_idx = new unsigned int[msh.num_faces * 3];

            for (size_t i = 0; i < msh.num_faces * 3; i+=3)
            {
                int Idx0 = (*it).second->front();
                (*it).second->pop_front();

                int Idx1 = (*it).second->front();
                (*it).second->pop_front();

                int Idx2 = (*it).second->front();
                (*it).second->pop_front();

                msh.faces_idx[i+0] = Idx2;
                msh.faces_idx[i+1] = Idx1;
                msh.faces_idx[i+2] = Idx0;
            }

            MatFaceMapIt it_mapfacemap = matface_map.find((*it).first);
            assert(it_mapfacemap != matface_map.end());
            m_opt = (*it_mapfacemap).second;

            msh.skin = skin ? true : false;
            msh.num_vertices = m_opt->face_map.size();
            msh.vertices = new Vector[msh.num_vertices];
            msh.normals = new Vector[msh.num_vertices];
            msh.colors = new Vector4f[msh.num_vertices];

            msh.weights = skin ? new Vector4f[msh.num_vertices] : NULL;
            msh.bone_idxs = skin ? new unsigned int[msh.num_vertices * 4] : NULL;

            unsigned int texdim = 0;
            bool * faceidx_cache = new bool[msh.num_vertices];
            memset(faceidx_cache, 0, msh.num_vertices * sizeof(bool));
            bool alloc_texture = false;

            for (size_t i = 0; i < msh.num_faces * 3; ++i)
            {
                unsigned int face_idx = msh.faces_idx[i];
                FaceMapIt it_face_map = m_opt->face_map.find(face_idx);
                assert(it_face_map != m_opt->face_map.end());

                vert_opt face = (*it_face_map).second;

                msh.faces_idx[i] = face.face_idx;

                if (faceidx_cache[face.face_idx] == false)
                {
                    faceidx_cache[face.face_idx] = true;

                    msh.vertices[face.face_idx] = Vector(face.v.x, face.v.y, face.v.z);

                    msh.colors[face.face_idx].x = face.c.x;
                    msh.colors[face.face_idx].y = face.c.y;
                    msh.colors[face.face_idx].z = face.c.z;

                    Vector V(face.n.x, face.n.y, face.n.z);
                    V.normalize();
                    msh.normals[face.face_idx] = V;

                    if (msh.skin)
                    {
                        msh.weights[face.face_idx].x = face.weights.x;
                        msh.weights[face.face_idx].y = face.weights.y;
                        msh.weights[face.face_idx].z = face.weights.z;

                        msh.bone_idxs[face.face_idx * 4 + 0] = face.bones[0]; // already remapped idxs
                        msh.bone_idxs[face.face_idx * 4 + 1] = face.bones[1];
                        msh.bone_idxs[face.face_idx * 4 + 2] = face.bones[2];
                        msh.bone_idxs[face.face_idx * 4 + 3] = face.bones[3];
                    }

                    if (face.num_tmaps && alloc_texture == false)
                    {
                        alloc_texture = true;
                        texdim = 2;
                        msh.num_texcoord_sets = face.num_tmaps;
                        msh.texcoord_sets = new m_texcoord_set[msh.num_texcoord_sets];
                        for (size_t j = 0; j < face.num_tmaps; ++j)
                        {
                            msh.texcoord_sets[j].dim = texdim;
                            msh.texcoord_sets[j].texcoords = new float[msh.num_vertices * texdim];
                        }
                    }

                    for (size_t j = 0; j < face.num_tmaps; ++j)
                    {
                        msh.texcoord_sets[j].texcoords[face.face_idx * texdim] = face.tmaps[j].x;
                        msh.texcoord_sets[j].texcoords[face.face_idx * texdim + 1] = face.tmaps[j].y;
                    }

                    Vector tmp = face.v; //transform_coord(face.v, xform);
                    //mult_pos(tmp, xform, face.v);

                    // aabb min...
                    if (tmp.x < pModel->aabb_min.x)
                        pModel->aabb_min.x = tmp.x;
                    if (tmp.y < pModel->aabb_min.y)
                        pModel->aabb_min.y = tmp.y;
                    if (tmp.z < pModel->aabb_min.z)
                        pModel->aabb_min.z = tmp.z;
                    // aabb max...
                    if (tmp.x > pModel->aabb_max.x)
                        pModel->aabb_max.x = tmp.x;
                    if (tmp.y > pModel->aabb_max.y)
                        pModel->aabb_max.y = tmp.y;
                    if (tmp.z > pModel->aabb_max.z)
                        pModel->aabb_max.z = tmp.z;

                    // mesh bounding box
                    // aabb min...
                    if (tmp.x < msh.aabb_min.x)
                        msh.aabb_min.x = tmp.x;
                    if (tmp.y < msh.aabb_min.y)
                        msh.aabb_min.y = tmp.y;
                    if (tmp.z < msh.aabb_min.z)
                        msh.aabb_min.z = tmp.z;
                    // aabb max...
                    if (tmp.x > msh.aabb_max.x)
                        msh.aabb_max.x = tmp.x;
                    if (tmp.y > msh.aabb_max.y)
                        msh.aabb_max.y = tmp.y;
                    if (tmp.z > msh.aabb_max.z)
                        msh.aabb_max.z = tmp.z;
                }
            }
            delete [] faceidx_cache;
            ++count;
            ++it;

            Helper_ComputeUV(msh);
            Helper_ComputeTBN(msh);
        }
        return true;
    }
    return false; // "BadObject";
}
示例#21
0
   Matrix<4,4,F32> & getLocalNodeMatrix(AppNode * node, AppNode  * parent, const AppTime & time, Matrix<4,4,F32> & matrix, AffineParts & a10, AffineParts & a20)
   {
      // Here's the story:  the default transforms have no scale.  In order to account for scale, the
      // scale at the default time is folded into the object offset (which is multiplied into the points
      // before exporting).  Because of this, the local transform at a given time must take into account
      // the scale of the parent and child node at time 0 in addition to the current time.  In particular,
      // the world transform at a given time is WT(time) = T(time) * inverse(Tscale(0))

      // in order to avoid recomputing matrix at default time over and over, we assume that the first request
      // for the matrix will be at the default time, and thereafter, we will pass that matrix in and reuse it...
      Matrix<4,4,F32> m1 = node->getNodeTransform(time);
      Matrix<4,4,F32> m2;
      if (parent)
         m2 = parent->getNodeTransform(time);
      else
         m2 = Matrix<4,4,F32>::identity();
      if (time == AppTime::DefaultTime())
      {
         decomp_affine(m1,&a10);
         decomp_affine(m2,&a20);
      }

      // build the inverse scale matrices
      Matrix<4,4,F32> stretchRot10,stretchRot20;
      Matrix<4,4,F32> scaleMat10,scaleMat20;
      Matrix<4,4,F32> invScale10, invScale20;
      Point3D sfactor10, sfactor20;
      stretchRot10 = a10.scaleRot.toMatrix();
      stretchRot20 = a20.scaleRot.toMatrix();
      sfactor10 = Point3D(a10.sign/a10.scale.x(),a10.sign/a10.scale.y(),a10.sign/a10.scale.z());
      sfactor20 = Point3D(a20.sign/a20.scale.x(),a20.sign/a20.scale.y(),a20.sign/a20.scale.z());
      scaleMat10 = Matrix<4,4,F32>::identity();
      scaleMat10[0][0] = sfactor10.x();
      scaleMat10[1][1] = sfactor10.y();
      scaleMat10[2][2] = sfactor10.z();
      scaleMat20 = Matrix<4,4,F32>::identity();
      scaleMat20[0][0] = sfactor20.x();
      scaleMat20[1][1] = sfactor20.y();
      scaleMat20[2][2] = sfactor20.z();


      invScale10 = stretchRot10 * scaleMat10 * stretchRot10.inverse();
      invScale20 = stretchRot20 * scaleMat20 * stretchRot20.inverse();

      // build world transforms
      m1 = m1 * invScale10;
      m2 = m2 * invScale20;

      // build local transform
      matrix = m2.inverse() * m1;

#ifdef TEST_DTS_MATH
      {
         Matrix<4,4,F32> testMat;
         Matrix<4,4,F32> m2inv = m2.inverse();
         testMat = m2inv * m2;
         {
            for (S32 i=0; i<4; i++)
               for (S32 j=0; j<4; j++)
               {
                  F32 val = i==j ? 1.0f : 0.0f;
                  assert(isEqual(testMat[i][j],val,0.01f) && "assertion failed");
               }
         }
         testMat = m2 * m2inv;
         {
            for (S32 i=0; i<4; i++)
               for (S32 j=0; j<4; j++)
               {
                  F32 val = i==j ? 1.0f : 0.0f;
                  assert(isEqual(testMat[i][j],val,0.01f) && "assertion failed");
               }
         }
      }
#endif

      return matrix;
   }
示例#22
0
BOOL AsciiExp::CheckForAnimation(INode* node, BOOL& bPos, BOOL& bRot, BOOL& bScale)
{
	TimeValue start = ip->GetAnimRange().Start();
	TimeValue end = ip->GetAnimRange().End();
	TimeValue t;
	int delta = GetTicksPerFrame();
	Matrix3 tm;
	AffineParts ap;
	Point3 firstPos;
	float rotAngle, firstRotAngle = 0.0f;
	Point3 rotAxis, firstRotAxis;
	Point3 firstScaleFactor;

	bPos = bRot = bScale = FALSE;

	for (t=start; t<=end; t+=delta) {
		tm = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));

		decomp_affine(tm, &ap);

		AngAxisFromQ(ap.q, &rotAngle, rotAxis);

		if (t != start) {
			if (!bPos) {
				if (!EqualPoint3(ap.t, firstPos)) {
					bPos = TRUE;
					}
				}
			// MAX 2.x:
			// We examine the rotation angle to see if the rotation component
			// has changed.
			// Although not entierly true, it should work.
			// It is rare that the rotation axis is animated without
			// the rotation angle being somewhat affected.
			// MAX 3.x:
			// The above did not work, I have a repro scene that doesn't export a rotation track
			// because of this. I fixed it to also compare the axis.
			if (!bRot) {
				if (fabs(rotAngle - firstRotAngle) > ALMOST_ZERO) {
					bRot = TRUE;
					}
				else if (!EqualPoint3(rotAxis, firstRotAxis)) {
					bRot = TRUE;
					}
				}

			if (!bScale) {
				if (!EqualPoint3(ap.k, firstScaleFactor)) {
					bScale = TRUE;
					}
				}
			}
		else {
			firstPos = ap.t;
			firstRotAngle = rotAngle;
			firstRotAxis = rotAxis;
			firstScaleFactor = ap.k;
			}

		// No need to continue looping if all components are animated
		if (bPos && bRot && bScale)
			break;
		}

	return bPos || bRot || bScale;
	}
示例#23
0
int EditPatchMod::DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPatch, bool & canUndo)
{
    ModContextList mcList;
    INodeTab nodes;

    if (!ip)
        return 0;

    ip->GetModContexts(mcList, nodes);

    if (mcList.Count() != 1)
    {
        nodes.DisposeTemporary();
        return 0;
    }

    EditPatchData *patchData =(EditPatchData*)mcList[0]->localData;
    if (!patchData)
    {
        nodes.DisposeTemporary();
        return 0;
    }
    patchData->BeginEdit(ip->GetTime());

    // If the mesh isn't yet cached, this will cause it to get cached.
    RPatchMesh *rpatch;
    PatchMesh *patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch);
    if (!patch)
    {
        nodes.DisposeTemporary();
        return 0;
    }
    patchData->RecordTopologyTags(patch);
    RecordTopologyTags();

    // Transform the shape for attachment:
    // If reorienting, just translate to align pivots
    // Otherwise, transform to match our transform
    Matrix3 attMat(1);
    if (attachReorient)
    {
        Matrix3 thisTM = nodes[0]->GetNodeTM(ip->GetTime());
        Matrix3 thisOTMBWSM = nodes[0]->GetObjTMBeforeWSM(ip->GetTime());
        Matrix3 thisPivTM = thisTM * Inverse(thisOTMBWSM);
        Matrix3 otherTM = node->GetNodeTM(ip->GetTime());
        Matrix3 otherOTMBWSM = node->GetObjTMBeforeWSM(ip->GetTime());
        Matrix3 otherPivTM = otherTM * Inverse(otherOTMBWSM);
        Point3 otherObjOffset = node->GetObjOffsetPos();
        attMat = Inverse(otherPivTM) * thisPivTM;
    }
    else
    {
        attMat = node->GetObjectTM(ip->GetTime()) *
                 Inverse(nodes[0]->GetObjectTM(ip->GetTime()));
    }

    // RB 3-17-96 : Check for mirroring
    AffineParts parts;
    decomp_affine(attMat, &parts);
    if (parts.f < 0.0f)
    {
        int v[8], ct, ct2, j;
        Point3 p[9];

        for (int i = 0; i < attPatch->numPatches; i++)
        {

            // Re-order rpatch
            if (attPatch->patches[i].type == PATCH_QUAD)
            {
                UI_PATCH rpatch=rattPatch->getUIPatch (i);
                int ctU=rpatch.NbTilesU<<1;
                int ctV=rpatch.NbTilesV<<1;
                int nU;
                for (nU=0; nU<ctU; nU++)
                {
                    for (int nV=0; nV<ctV; nV++)
                    {
                        rattPatch->getUIPatch (i).getTileDesc (nU+nV*ctU)=rpatch.getTileDesc (ctU-1-nU+(ctV-1-nV)*ctU);
                    }
                }
                for (nU=0; nU<ctU+1; nU++)
                {
                    for (int nV=0; nV<ctV+1; nV++)
                    {
                        rattPatch->getUIPatch (i).setColor (nU+nV*(ctU+1), rpatch.getColor (ctU-nU+(ctV-nV)*ctU));
                    }
                }
            }

            // Re-order vertices
            ct = attPatch->patches[i].type == PATCH_QUAD ? 4 : 3;
            for (j = 0; j < ct; j++)
            {
                v[j] = attPatch->patches[i].v[j];
            }
            for (j = 0; j < ct; j++)
            {
                attPatch->patches[i].v[j] = v[ct - j - 1];
            }

            // Re-order vecs
            ct  = attPatch->patches[i].type == PATCH_QUAD ? 8 : 6;
            ct2 = attPatch->patches[i].type == PATCH_QUAD ? 5 : 3;
            for (j = 0; j < ct; j++)
            {
                v[j] = attPatch->patches[i].vec[j];
            }
            for (j = 0; j < ct; j++, ct2--)
            {
                if (ct2 < 0)
                    ct2 = ct - 1;
                attPatch->patches[i].vec[j] = v[ct2];
            }

            // Re-order enteriors
            if (attPatch->patches[i].type == PATCH_QUAD)
            {
                ct = 4;
                for (j = 0; j < ct; j++)
                {
                    v[j] = attPatch->patches[i].interior[j];
                }
                for (j = 0; j < ct; j++)
                {
                    attPatch->patches[i].interior[j] = v[ct - j - 1];
                }
            }

            // Re-order aux
            if (attPatch->patches[i].type == PATCH_TRI)
            {
                ct = 9;
                for (j = 0; j < ct; j++)
                {
                    p[j] = attPatch->patches[i].aux[j];
                }
                for (j = 0; j < ct; j++)
                {
                    attPatch->patches[i].aux[j] = p[ct - j - 1];
                }
            }

            // Re-order TV faces if present
            for (int chan = 0; chan < patch->getNumMaps(); ++chan)
            {
                if (attPatch->tvPatches[chan])
                {
                    ct = 4;
                    for (j = 0; j < ct; j++)
                    {
                        v[j] = attPatch->tvPatches[chan][i].tv[j];
                    }
                    for (j = 0; j < ct; j++)
                    {
                        attPatch->tvPatches[chan][i].tv[j] = v[ct - j - 1];
                    }
                }
            }
        }
    }

    int i;
    for (i = 0; i < attPatch->numVerts; ++i)
        attPatch->verts[i].p = attPatch->verts[i].p * attMat;
    for (i = 0; i < attPatch->numVecs; ++i)
        attPatch->vecs[i].p = attPatch->vecs[i].p * attMat;
    attPatch->computeInteriors();

    theHold.Begin();

    // Combine the materials of the two nodes.
    int mat2Offset = 0;
    Mtl *m1 = nodes[0]->GetMtl();
    Mtl *m2 = node->GetMtl();
    bool condenseMe = FALSE;
    if (m1 && m2 &&(m1 != m2))
    {
        if (attachMat == ATTACHMAT_IDTOMAT)
        {
            int ct = 1;
            if (m1->IsMultiMtl())
                ct = m1->NumSubMtls();
            for (int i = 0; i < patch->numPatches; ++i)
            {
                int mtid = patch->getPatchMtlIndex(i);
                if (mtid >= ct)
                    patch->setPatchMtlIndex(i, mtid % ct);
            }
            FitPatchIDsToMaterial(*attPatch, m2);
            if (condenseMat)
                condenseMe = TRUE;
        }
        // the theHold calls here were a vain attempt to make this all undoable.
        // This should be revisited in the future so we don't have to use the SYSSET_CLEAR_UNDO.
        theHold.Suspend();
        if (attachMat == ATTACHMAT_MATTOID)
        {
            m1 = FitMaterialToPatchIDs(*patch, m1);
            m2 = FitMaterialToPatchIDs(*attPatch, m2);
        }

        Mtl *multi = CombineMaterials(m1, m2, mat2Offset);
        if (attachMat == ATTACHMAT_NEITHER)
            mat2Offset = 0;
        theHold.Resume();
        // We can't be in face subobject mode, else we screw up the materials:
        DWORD oldSL = patch->selLevel;
        DWORD roldSL = patch->selLevel;
        patch->selLevel = PATCH_OBJECT;
        rpatch->SetSelLevel (EP_OBJECT);
        nodes[0]->SetMtl(multi);
        patch->selLevel = oldSL;
        rpatch->SetSelLevel (roldSL);
        m1 = multi;
        canUndo = FALSE;	// Absolutely cannot undo material combinations.
    }
    if (!m1 && m2)
    {
        // We can't be in face subobject mode, else we screw up the materials:
        DWORD oldSL = patch->selLevel;
        DWORD roldSL = rpatch->GetSelLevel();
        patch->selLevel = PATCH_OBJECT;
        rpatch->SetSelLevel (EP_OBJECT);
        nodes[0]->SetMtl(m2);
        patch->selLevel = oldSL;
        rpatch->SetSelLevel (roldSL);
        m1 = m2;
    }

    // Start a restore object...
    if (theHold.Holding())
        theHold.Put(new PatchRestore(patchData, this, patch, rpatch, "DoAttach"));

    // Do the attach
    patch->Attach(attPatch, mat2Offset);
    rpatch->Attach(rattPatch, *patch);
    patchData->UpdateChanges(patch, rpatch);
    patchData->TempData(this)->Invalidate(PART_TOPO | PART_GEOM);

    // Get rid of the original node
    ip->DeleteNode(node);

    ResolveTopoChanges();
    theHold.Accept(GetString(IDS_TH_ATTACH));

    if (m1 && condenseMe)
    {
        // Following clears undo stack.
        patch = patchData->TempData(this)->GetPatch(ip->GetTime(), rpatch);
        m1 = CondenseMatAssignments(*patch, m1);
    }

    nodes.DisposeTemporary();
    ClearPatchDataFlag(mcList, EPD_BEENDONE);
    NotifyDependents(FOREVER, PART_TOPO | PART_GEOM, REFMSG_CHANGE);
    ip->RedrawViews(ip->GetTime(), REDRAW_NORMAL);
    return 1;
}
示例#24
0
	/**
	 * Converts a COLLADA XML document into the PMD mesh format.
	 *
	 * @param input XML document to parse
	 * @param output callback for writing the PMD data; called lots of times
	 *               with small strings
	 * @param xmlErrors output - errors reported by the XML parser
	 * @throws ColladaException on failure
	 */
	static void ColladaToPMD(const char* input, OutputCB& output, std::string& xmlErrors)
	{
		CommonConvert converter(input, xmlErrors);

		if (converter.GetInstance().GetEntity()->GetType() == FCDEntity::GEOMETRY)
		{
			Log(LOG_INFO, "Found static geometry");

			FCDGeometryPolygons* polys = GetPolysFromGeometry((FCDGeometry*)converter.GetInstance().GetEntity());

			// Convert the geometry into a suitable form for the game
			ReindexGeometry(polys);

			std::vector<VertexBlend> boneWeights;	// unused
			std::vector<BoneTransform> boneTransforms;	// unused
			std::vector<PropPoint> propPoints;

			// Get the raw vertex data

			FCDGeometryPolygonsInput* inputPosition = polys->FindInput(FUDaeGeometryInput::POSITION);
			FCDGeometryPolygonsInput* inputNormal   = polys->FindInput(FUDaeGeometryInput::NORMAL);
			FCDGeometryPolygonsInput* inputTexcoord = polys->FindInput(FUDaeGeometryInput::TEXCOORD);

			const uint32* indicesCombined = inputPosition->GetIndices();
			size_t indicesCombinedCount = inputPosition->GetIndexCount();
			// (ReindexGeometry guarantees position/normal/texcoord have the same indexes)

			FCDGeometrySource* sourcePosition = inputPosition->GetSource();
			FCDGeometrySource* sourceNormal   = inputNormal  ->GetSource();
			FCDGeometrySource* sourceTexcoord = inputTexcoord->GetSource();

			float* dataPosition = sourcePosition->GetData();
			float* dataNormal   = sourceNormal  ->GetData();
			float* dataTexcoord = sourceTexcoord->GetData();
			size_t vertexCount = sourcePosition->GetDataCount() / 3;
			assert(sourcePosition->GetDataCount() == vertexCount*3);
			assert(sourceNormal  ->GetDataCount() == vertexCount*3);
			assert(sourceTexcoord->GetDataCount() == vertexCount*2);

			// Transform mesh coordinate system to game coordinates
			// (doesn't modify prop points)

			TransformStaticModel(dataPosition, dataNormal, vertexCount, converter.GetEntityTransform(), converter.IsYUp());

			// Add static prop points
			//	which are empty child nodes of the main parent

			// Default prop points are already given in game coordinates
			AddDefaultPropPoints(propPoints);
			
			// Calculate transform to convert from COLLADA-defined up_axis to Z-up because
			//	it's relatively straightforward to convert that to game coordinates
			FMMatrix44 upAxisTransform = FMMatrix44_Identity;
			if (converter.IsYUp())
			{
				// Prop points are rotated -90 degrees about the X-axis, reverse that rotation
				// (do this once now because it's easier than messing with quaternions later)
				upAxisTransform = FMMatrix44::XAxisRotationMatrix(1.57f);
			}

			AddStaticPropPoints(propPoints, upAxisTransform, converter.GetInstance().GetParent());

			WritePMD(output, indicesCombined, indicesCombinedCount, dataPosition, dataNormal, dataTexcoord, vertexCount, boneWeights, boneTransforms, propPoints);
		}
		else if (converter.GetInstance().GetType() == FCDEntityInstance::CONTROLLER)
		{
			Log(LOG_INFO, "Found skinned geometry");

			FCDControllerInstance& controllerInstance = static_cast<FCDControllerInstance&>(converter.GetInstance());

			// (NB: GetType is deprecated and should be replaced with HasType,
			// except that has irritating linker errors when using a DLL, so don't
			// bother)
			
			assert(converter.GetInstance().GetEntity()->GetType() == FCDEntity::CONTROLLER); // assume this is always true?
			FCDController* controller = static_cast<FCDController*>(converter.GetInstance().GetEntity());

			FCDSkinController* skin = controller->GetSkinController();
			REQUIRE(skin != NULL, "is skin controller");

			FixSkeletonRoots(controllerInstance);

			// Data for joints is stored in two places - avoid overflows by limiting
			// to the minimum of the two sizes, and warn if they're different (which
			// happens in practice for slightly-broken meshes)
			size_t jointCount = std::min(skin->GetJointCount(), controllerInstance.GetJointCount());
			if (skin->GetJointCount() != controllerInstance.GetJointCount())
			{
				Log(LOG_WARNING, "Mismatched bone counts (skin has %d, skeleton has %d)", 
					skin->GetJointCount(), controllerInstance.GetJointCount());
				for (size_t i = 0; i < skin->GetJointCount(); ++i)
					Log(LOG_INFO, "Skin joint %d: %s", i, skin->GetJoint(i)->GetId().c_str());
				for (size_t i = 0; i < controllerInstance.GetJointCount(); ++i)
					Log(LOG_INFO, "Skeleton joint %d: %s", i, controllerInstance.GetJoint(i)->GetName().c_str());
			}

			// Get the skinned mesh for this entity
			FCDGeometry* baseGeometry = controller->GetBaseGeometry();
			REQUIRE(baseGeometry != NULL, "controller has base geometry");
			FCDGeometryPolygons* polys = GetPolysFromGeometry(baseGeometry);

			// Make sure it doesn't use more bones per vertex than the game can handle
			SkinReduceInfluences(skin, maxInfluences, 0.001f);

			// Convert the geometry into a suitable form for the game
			ReindexGeometry(polys, skin);

			const Skeleton& skeleton = FindSkeleton(controllerInstance);

			// Convert the bone influences into VertexBlend structures for the PMD:

			bool hasComplainedAboutNonexistentJoints = false; // because we want to emit a warning only once

			std::vector<VertexBlend> boneWeights; // one per vertex

			const FCDSkinControllerVertex* vertexInfluences = skin->GetVertexInfluences();
			for (size_t i = 0; i < skin->GetInfluenceCount(); ++i)
			{
				VertexBlend influences = defaultInfluences;

				assert(vertexInfluences[i].GetPairCount() <= maxInfluences);
					// guaranteed by ReduceInfluences; necessary for avoiding
					// out-of-bounds writes to the VertexBlend

				for (size_t j = 0; j < vertexInfluences[i].GetPairCount(); ++j)
				{
					uint32 jointIdx = vertexInfluences[i].GetPair(j)->jointIndex;
					REQUIRE(jointIdx <= 0xFF, "sensible number of joints (<256)"); // because we only have a u8 to store them in

					// Find the joint on the skeleton, after checking it really exists
					FCDSceneNode* joint = NULL;
					if (jointIdx < controllerInstance.GetJointCount())
						joint = controllerInstance.GetJoint(jointIdx);

					// Complain on error
					if (! joint)
					{
						if (! hasComplainedAboutNonexistentJoints)
						{
							Log(LOG_WARNING, "Vertexes influenced by nonexistent joint");
							hasComplainedAboutNonexistentJoints = true;
						}
						continue;
					}

					// Store into the VertexBlend
					int boneId = skeleton.GetBoneID(joint->GetName().c_str());
					if (boneId < 0)
					{
						// The relevant joint does exist, but it's not a recognised
						// bone in our chosen skeleton structure
						Log(LOG_ERROR, "Vertex influenced by unrecognised bone '%s'", joint->GetName().c_str());
						continue;
					}

					influences.bones[j] = (uint8)boneId;
					influences.weights[j] = vertexInfluences[i].GetPair(j)->weight;
				}

				boneWeights.push_back(influences);
			}

			// Convert the bind pose into BoneTransform structures for the PMD:

			BoneTransform boneDefault  = { { 0, 0, 0 }, { 0, 0, 0, 1 } }; // identity transform
			std::vector<BoneTransform> boneTransforms (skeleton.GetBoneCount(), boneDefault);

			for (size_t i = 0; i < jointCount; ++i)
			{
				FCDSceneNode* joint = controllerInstance.GetJoint(i);

				int boneId = skeleton.GetRealBoneID(joint->GetName().c_str());
				if (boneId < 0)
				{
					// unrecognised joint - it's probably just a prop point
					// or something, so ignore it
					continue;
				}

				FMMatrix44 bindPose = skin->GetJoint(i)->GetBindPoseInverse().Inverted();

				HMatrix matrix;
				memcpy(matrix, bindPose.Transposed().m, sizeof(matrix));
					// set matrix = bindPose^T, to match what decomp_affine wants

				AffineParts parts;
				decomp_affine(matrix, &parts);

				BoneTransform b = {
					{ parts.t.x, parts.t.y, parts.t.z },
					{ parts.q.x, parts.q.y, parts.q.z, parts.q.w }
				};

				boneTransforms[boneId] = b;
			}

			// Construct the list of prop points.
			// Currently takes all objects that are directly attached to a
			// standard bone, and whose name begins with "prop-" or "prop_".

			std::vector<PropPoint> propPoints;
			AddDefaultPropPoints(propPoints);

			for (size_t i = 0; i < jointCount; ++i)
			{
				FCDSceneNode* joint = controllerInstance.GetJoint(i);

				int boneId = skeleton.GetBoneID(joint->GetName().c_str());
				if (boneId < 0)
				{
					// unrecognised joint name - ignore, same as before
					continue;
				}

				// Check all the objects attached to this bone
				for (size_t j = 0; j < joint->GetChildrenCount(); ++j)
				{
					FCDSceneNode* child = joint->GetChild(j);
					if (child->GetName().find("prop-") != 0 && child->GetName().find("prop_") != 0)
					{
						// doesn't begin with "prop-", so skip it
						continue;
					}
					// Strip off the "prop-" from the name
					std::string propPointName (child->GetName().substr(5));

					Log(LOG_INFO, "Adding prop point %s", propPointName.c_str());

					// Get translation and orientation of local transform

					FMMatrix44 localTransform = child->ToMatrix();

					HMatrix matrix;
					memcpy(matrix, localTransform.Transposed().m, sizeof(matrix));

					AffineParts parts;
					decomp_affine(matrix, &parts);

					// Add prop point to list

					PropPoint p = {
						propPointName,
						{ parts.t.x, parts.t.y, parts.t.z },
						{ parts.q.x, parts.q.y, parts.q.z, parts.q.w },
						(uint8)boneId
					};
					propPoints.push_back(p);
				}
			}

			// Get the raw vertex data

			FCDGeometryPolygonsInput* inputPosition = polys->FindInput(FUDaeGeometryInput::POSITION);
			FCDGeometryPolygonsInput* inputNormal   = polys->FindInput(FUDaeGeometryInput::NORMAL);
			FCDGeometryPolygonsInput* inputTexcoord = polys->FindInput(FUDaeGeometryInput::TEXCOORD);


			const uint32* indicesCombined = inputPosition->GetIndices();
			size_t indicesCombinedCount = inputPosition->GetIndexCount();
			// (ReindexGeometry guarantees position/normal/texcoord have the same indexes)

			FCDGeometrySource* sourcePosition = inputPosition->GetSource();
			FCDGeometrySource* sourceNormal   = inputNormal  ->GetSource();
			FCDGeometrySource* sourceTexcoord = inputTexcoord->GetSource();

			float* dataPosition = sourcePosition->GetData();
			float* dataNormal   = sourceNormal  ->GetData();
			float* dataTexcoord = sourceTexcoord->GetData();
			size_t vertexCount = sourcePosition->GetDataCount() / 3;
			assert(sourcePosition->GetDataCount() == vertexCount*3);
			assert(sourceNormal  ->GetDataCount() == vertexCount*3);
			assert(sourceTexcoord->GetDataCount() == vertexCount*2);

			// Transform model coordinate system to game coordinates

			TransformSkinnedModel(dataPosition, dataNormal, vertexCount, boneTransforms, propPoints,
				converter.GetEntityTransform(), skin->GetBindShapeTransform(),
				converter.IsYUp(), converter.IsXSI());

			WritePMD(output, indicesCombined, indicesCombinedCount, dataPosition, dataNormal, dataTexcoord, vertexCount, boneWeights, boneTransforms, propPoints);
		}
		else
		{
			throw ColladaException("Unrecognised object type");
		}

	}
示例#25
0
//----------------------------------------------------------------------------
PX2::Transform SceneBuilder::GetLocalTransform (INode *node, TimeValue time)
{
	// 计算节点的本地变换。Max节点的变换方法提供的节点的世界变换,所以我们
	// 必须做一些操纵去获得节点的本地变换。

	Matrix3 maxLocal = node->GetObjTMAfterWSM(time) *
		Inverse(node->GetParentNode()->GetObjTMAfterWSM(time));

	// 分解变换
	AffineParts affParts;
	decomp_affine(maxLocal, &affParts);

	// Position
	bool isTranslationZero = 
		fabsf(affParts.t.x) < MIN_DIFFERENCE &&
		fabsf(affParts.t.y) < MIN_DIFFERENCE &&
		fabsf(affParts.t.z) < MIN_DIFFERENCE;

	// Rotation
	float qSign = (affParts.q.w >= 0.0f ? 1.0f : -1.0f);
	bool isRotationIndentity = 
		fabsf(qSign*affParts.q.w - 1.0f) < MIN_DIFFERENCE &&
		fabsf(affParts.q.x) < MIN_DIFFERENCE &&
		fabsf(affParts.q.y) < MIN_DIFFERENCE &&
		fabsf(affParts.q.z) < MIN_DIFFERENCE;

	// Reflect
	bool hasReflection = (affParts.f < 0.0f);

	// Uniform scale
	bool isScaleUniform = (fabsf(affParts.k.x - affParts.k.y)<MIN_DIFFERENCE &&
		fabsf(affParts.k.y - affParts.k.z)<MIN_DIFFERENCE);

	// Unity scale
	bool isScaleUnity = isScaleUniform &&
		fabsf(affParts.k.x - 1.0f) < MIN_DIFFERENCE;

	// Scale orientation is identity?
	float uSign = (affParts.u.w >= 0.0f ? 1.0f : -1.0f);
	bool isOrientIndentity = isScaleUniform || (
		fabsf(uSign*affParts.u.w - 1.0f) < MIN_DIFFERENCE &&
		fabsf(affParts.u.x) < MIN_DIFFERENCE &&
		fabsf(affParts.u.y) < MIN_DIFFERENCE &&
		fabsf(affParts.u.z) < MIN_DIFFERENCE);

	// 计算Phoenix2等价变换
	PX2::Transform local;

	if (!isTranslationZero)
	{
		local.SetTranslate(PX2::APoint(affParts.t.x, affParts.t.y,
			affParts.t.z));
	}

	if (hasReflection)
	{
		affParts.k *= -1.0f;
	}
	
	if (isScaleUniform)
	{
		// 矩阵的形式为R*(s*I),s是统一缩放矩阵。
		if (!isRotationIndentity)
		{
			PX2::HMatrix rot;
			PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y,
				-affParts.q.z).ToRotationMatrix(rot);
			local.SetRotate(rot);
		}

		if (!isScaleUnity)
		{
			local.SetUniformScale(affParts.k.x);
		}
	}
	else if (isOrientIndentity)
	{
		if (!isRotationIndentity)
		{
			PX2::HMatrix rot;
			PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y,
				-affParts.q.z).ToRotationMatrix(rot);
			local.SetRotate(rot);
		}

		local.SetScale(PX2::APoint(affParts.k.x, affParts.k.y, affParts.k.z));
	}
	else
	{
		PX2::Matrix3f mat(
			maxLocal.GetAddr()[0][0],
			maxLocal.GetAddr()[1][0],
			maxLocal.GetAddr()[2][0],
			maxLocal.GetAddr()[0][1],
			maxLocal.GetAddr()[1][1],
			maxLocal.GetAddr()[2][1],
			maxLocal.GetAddr()[0][2],
			maxLocal.GetAddr()[1][2],
			maxLocal.GetAddr()[2][2]);

		local.SetMatrix(PX2::HMatrix(mat));
	}

	return local;
}
示例#26
0
void ISCExport::saveISC(const TCHAR *name,ExpInterface *ei,Interface *i)
{
	SceneEnumerator enumerator(ei,i);

	// No triobjects to export -> quit
	if (enumerator.numTriobjects()==0) return;

	size_t objnum=0;
	unsigned long chunksize,namessize=0;

	FILE *outfile=fopen(name,"wb");
	if (!outfile) return;

	for (objnum=0;objnum<enumerator.numTriobjects();++objnum)
		namessize+=(unsigned long)(enumerator.triobjectname(objnum).length())+1;


	fwrite("isc0",1,4,outfile);


	fwrite("objt",1,4,outfile);
	chunksize=(unsigned long)(enumerator.numTriobjects()*(3*sizeof(float)+4*sizeof(float)+4))+namessize;
	fwrite(&chunksize,1,4,outfile);
	{ DWORD numobjs=(DWORD)(enumerator.numTriobjects()); fwrite(&numobjs,1,4,outfile); }

	for (objnum=0;objnum<enumerator.numTriobjects();++objnum) {
		TriObject *pTriobj=enumerator.triobject(objnum);
		std::string objname=enumerator.triobjectname(objnum);
		Matrix3 *pTM=enumerator.triobjecttransform(objnum);

		/*Point3 trans=pTM->GetTrans();
		Quat rot(*pTM);*/
		AffineParts parts;
		decomp_affine(*pTM,&parts);
		Point3 trans=parts.t;
		Quat rot=parts.q;

		//float ang[3];
		//QuatToEuler(rot,ang);
		/*rot.GetEuler(&ang[0],&ang[1],&ang[2]);
		//{ float f=ang[1]; ang[1]=ang[2]; ang[2]=f; }
		rot.SetEuler(ang[0],ang[2],ang[1]);*/

		trans.x=trans.y=trans.z=0;
		rot.Identity();

		fwrite(objname.c_str(),1,objname.length()+1,outfile);

		//trans.x*=-1;

		fwrite(&(trans.x),1,sizeof(float),outfile);
		fwrite(&(trans.y),1,sizeof(float),outfile);
		fwrite(&(trans.z),1,sizeof(float),outfile);

		fwrite(&(rot.x),1,sizeof(float),outfile);
		fwrite(&(rot.y),1,sizeof(float),outfile);
		fwrite(&(rot.z),1,sizeof(float),outfile);
		fwrite(&(rot.w),1,sizeof(float),outfile);

		fwrite(&objnum,1,4,outfile);
	}


	fwrite("mesh",1,4,outfile);
	chunksize=(unsigned long)(enumerator.numTriobjects()*(2*4 + 3*4 + 4 + (3+3+2+3+3)*sizeof(float)))+namessize;
	fwrite(&chunksize,1,4,outfile);
	{ DWORD numobjs=(DWORD)(enumerator.numTriobjects()); fwrite(&numobjs,1,4,outfile); }

	for (objnum=0;objnum<enumerator.numTriobjects();++objnum) {
		Matrix3 *pTM=enumerator.triobjecttransform(objnum);

		TriObject *pTriobj=enumerator.triobject(objnum);
		std::string objname=enumerator.triobjectname(objnum);
		fwrite(objname.c_str(),1,objname.length()+1,outfile);
		saveMesh(outfile,pTriobj,pTM,enumerator.triobjectmaterial(objnum),enumerator);
	}


	fwrite("mtrl",1,4,outfile);
	chunksize=0;
	fwrite(&chunksize,1,4,outfile);
	{ DWORD nummtrls=(DWORD)(enumerator.numMaterials()); fwrite(&nummtrls,1,4,outfile); }

	for (size_t mtrlnum=0;mtrlnum<enumerator.numMaterials();++mtrlnum) {
		Mtl* pMtl=enumerator.material(mtrlnum);
		saveMaterial(outfile,pMtl);
	}


	fclose(outfile);
}