⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smdlexp.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	// Root node has no parent, thus no translation
	if (fNodeIsRoot)
		iNodeParent = -1;
		
	// check to see if the matrix isn't right handed
	m_phec->m_rgmaxnode[iNode].isMirrored = DotProd( CrossProd( m_phec->m_rgmaxnode[iNode].mat3ObjectTM.GetRow(0).Normalize(), m_phec->m_rgmaxnode[iNode].mat3ObjectTM.GetRow(1).Normalize() ).Normalize(), m_phec->m_rgmaxnode[iNode].mat3ObjectTM.GetRow(2).Normalize() ) < 0;

	// Dump node description
	fprintf(m_pfile, "%3d \"%s\" %3d\n", 
		iNode, 
		strNodeName, 
		iNodeParent );

	return TREE_CONTINUE;
}



//=================================================================
// 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;
}



//=================================================================
// Methods for DumpModelTEP
//
Modifier *FindPhysiqueModifier (INode *nodePtr)
{
	// Get object from node. Abort if no object.
	Object *ObjectPtr = nodePtr->GetObjectRef();
	if (!ObjectPtr) return NULL;

	// Is derived object ?
	if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
	{
		// Yes -> Cast.
		IDerivedObject *DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);

		// Iterate over all entries of the modifier stack.
		int ModStackIndex = 0;
		while (ModStackIndex < DerivedObjectPtr->NumModifiers())
		{
			// Get current modifier.
			Modifier *ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);

			// Is this Physique ?
			if (ModifierPtr->ClassID() == Class_ID(	PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B) )
			{
				// Yes -> Exit.
				return ModifierPtr;
			}
			// Next modifier stack entry.
			ModStackIndex++;
		}
	}
	// Not found.
	return NULL;
}

Modifier *FindBonesProModifier (INode *nodePtr)
{
	// Get object from node. Abort if no object.
	Object *ObjectPtr = nodePtr->GetObjectRef();
	if (!ObjectPtr) return NULL;

	// Is derived object ?
	if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
	{
		// Yes -> Cast.
		IDerivedObject *DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr);

		// Iterate over all entries of the modifier stack.
		int ModStackIndex = 0;
		while (ModStackIndex < DerivedObjectPtr->NumModifiers())
		{
			// Get current modifier.
			Modifier *ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);

			// Is this Bones Pro OSM?
			if (ModifierPtr->ClassID() == BP_CLASS_ID_OSM )
			{
				// Yes -> Exit.
				return ModifierPtr;
			}
			// Is this Bones Pro WSM?
			if (ModifierPtr->ClassID() == BP_CLASS_ID_WSM )
			{
				// Yes -> Exit.
				return ModifierPtr;
			}
			// Next modifier stack entry.
			ModStackIndex++;
		}
	}
	// Not found.
	return NULL;
}

// #define DEBUG_MESH_DUMP

//=================================================================
// Methods for DumpModelTEP
//
int DumpModelTEP::callback(INode *pnode)
{
	Object*	pobj;
	int	fHasMat = TRUE;

	// clear physique export parameters
	m_mcExport = NULL;
	m_phyExport = NULL;
    m_phyMod = NULL;
    m_bonesProMod = NULL;

	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

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

	// Actually, if it's not selected, skip it!
	//if (!pnode->Selected())
	//	return TRUE;
	
	int iNode = ::GetIndexOfINode(pnode);
	TSTR strNodeName(pnode->GetName());
	
	// The Footsteps node apparently MUST have a dummy mesh attached!  Ignore it explicitly.
	if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
		return TREE_CONTINUE;

	// Helper nodes don't have meshes
	pobj = pnode->GetObjectRef();
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
		return TREE_CONTINUE;

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

	// Get node's material: should be a multi/sub (if it has a material at all)
	Mtl *pmtlNode = pnode->GetMtl();
	if (pmtlNode == NULL)
	{
		return TREE_CONTINUE;
		fHasMat = FALSE;
	}
	else if (!(pmtlNode->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlNode->IsMultiMtl()))
	{
		// sprintf(st_szDBG, "ERROR--Material on node %s isn't a Multi/Sub-Object", (char*)strNodeName);
		// ASSERT_AND_ABORT(FALSE, st_szDBG);
		// fHasMat = FALSE;
	}
	
	// Get Node's object, convert to a triangle-mesh object, so I can access the Faces
	ObjectState os = pnode->EvalWorldState(m_tvToDump);
	pobj = os.obj;
	TriObject *ptriobj;
	BOOL fConvertedToTriObject = 
		pobj->CanConvertToType(triObjectClassID) &&
		(ptriobj = (TriObject*)pobj->ConvertToType(m_tvToDump, triObjectClassID)) != NULL;
	if (!fConvertedToTriObject)
		return TREE_CONTINUE;
	Mesh *pmesh = &ptriobj->mesh;

	// Shouldn't have gotten this far if it's a helper object
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
	{
		sprintf(st_szDBG, "ERROR--Helper node %s has an attached mesh, and it shouldn't.", (char*)strNodeName);
		ASSERT_AND_ABORT(FALSE, st_szDBG);
	}

	// Ensure that the vertex normals are up-to-date
	pmesh->buildNormals();

	// We want the vertex coordinates in World-space, not object-space
	Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvToDump);


	// initialize physique export parameters
    m_phyMod = FindPhysiqueModifier(pnode);
    if (m_phyMod)
	{
		// Physique Modifier exists for given Node
	    m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);

        if (m_phyExport)
        {
            // create a ModContext Export Interface for the specific node of the Physique Modifier
           m_mcExport = (IPhyContextExport *)m_phyExport->GetContextInterface(pnode);

		   if (m_mcExport)
		   {
		       // convert all vertices to Rigid 
                m_mcExport->ConvertToRigid(TRUE);
		   }
		}
	}

	// initialize bones pro export parameters
	m_wa  = NULL;
	m_bonesProMod = FindBonesProModifier(pnode);
	if (m_bonesProMod)
	{
		m_bonesProMod->SetProperty( BP_PROPID_GET_WEIGHTS, &m_wa );
	}

	// Dump the triangle face info
	int cFaces = pmesh->getNumFaces();
	for (int iFace = 0; iFace < cFaces; iFace++)
	{
		Face*	pface		= &pmesh->faces[iFace];
		TVFace*	ptvface		= (pmesh->tvFace) ? &pmesh->tvFace[iFace] : NULL;
		DWORD	smGroupFace	= pface->getSmGroup();

		// Get face's 3 indexes into the Mesh's vertex array(s).
		DWORD iVertex0 = pface->getVert(0);
		DWORD iVertex1 = pface->getVert(1);
		DWORD iVertex2 = pface->getVert(2);
		ASSERT_AND_ABORT((int)iVertex0 < pmesh->getNumVerts(), "Bogus Vertex 0 index");
		ASSERT_AND_ABORT((int)iVertex1 < pmesh->getNumVerts(), "Bogus Vertex 1 index");
		ASSERT_AND_ABORT((int)iVertex2 < pmesh->getNumVerts(), "Bogus Vertex 2 index");
		
		// Get the 3 Vertex's for this face
		Point3 pt3Vertex0 = pmesh->getVert(iVertex0);
		Point3 pt3Vertex1 = pmesh->getVert(iVertex1);
		Point3 pt3Vertex2 = pmesh->getVert(iVertex2);

		// Get the 3 RVertex's for this face
		// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
		RVertex *prvertex0 = pmesh->getRVertPtr(iVertex0);
		RVertex *prvertex1 = pmesh->getRVertPtr(iVertex1);
		RVertex *prvertex2 = pmesh->getRVertPtr(iVertex2);
		
		// Find appropriate normals for each RVertex
		// A vertex can be part of multiple faces, so the "smoothing group"
		// is used to locate the normal for this face's use of the vertex.
		Point3 pt3Vertex0Normal;
		Point3 pt3Vertex1Normal;
		Point3 pt3Vertex2Normal;
		if (smGroupFace) 
		{
			pt3Vertex0Normal = Pt3GetRVertexNormal(prvertex0, smGroupFace);
			pt3Vertex1Normal = Pt3GetRVertexNormal(prvertex1, smGroupFace);
			pt3Vertex2Normal = Pt3GetRVertexNormal(prvertex2, smGroupFace);
		}
		else 
		{
			pt3Vertex0Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex1Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex2Normal = pmesh->getFaceNormal( iFace );
		}
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus orig normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus orig normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus orig normal 2" );
	
		// Get Face's sub-material from node's material, to get the bitmap name.
		// And no, there isn't a simpler way to get the bitmap name, you have to
		// dig down through all these levels.
		TCHAR szBitmapName[256] = "null.bmp";
		if (fHasMat)
		{
			Texmap *ptexmap = NULL;
			MtlID mtlidFace = pface->getMatID();
			if (pmtlNode->IsMultiMtl())
			{
				if (mtlidFace >= pmtlNode->NumSubMtls())
				{
					sprintf(st_szDBG, "ERROR--Bogus sub-material index %d in node %s; highest valid index is %d",
						mtlidFace, (char*)strNodeName, pmtlNode->NumSubMtls()-1);
					// ASSERT_AND_ABORT(FALSE, st_szDBG);
					mtlidFace = 0;
				}
				Mtl *pmtlFace = pmtlNode->GetSubMtl(mtlidFace);
				ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
 
				/*
				if ((pmtlFace->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlFace->IsMultiMtl()))
				{
					// it's a sub-sub material.  Gads.
					pmtlFace = pmtlFace->GetSubMtl(mtlidFace);			
					ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
				}
				*/

				if (!(pmtlFace->ClassID() == Class_ID(DMTL_CLASS_ID, 0)))
				{

					sprintf(st_szDBG,
						"ERROR--Sub-material with index %d (used in node %s) isn't a 'default/standard' material [%x].",
						mtlidFace, (char*)strNodeName, pmtlFace->ClassID());
					ASSERT_AND_ABORT(FALSE, st_szDBG);
				}
				StdMat *pstdmtlFace = (StdMat*)pmtlFace;
				ptexmap = pstdmtlFace->GetSubTexmap(ID_DI);
			}
			else
			{
				ptexmap = pmtlNode->GetActiveTexmap();
			}

			// ASSERT_AND_ABORT(ptexmap != NULL, "NULL diffuse texture")
			if (ptexmap != NULL) 
			{
				if (!(ptexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)))
				{
					sprintf(st_szDBG,
						"ERROR--Sub-material with index %d (used in node %s) doesn't have a bitmap as its diffuse texture.",
						mtlidFace, (char*)strNodeName);
					ASSERT_AND_ABORT(FALSE, st_szDBG);
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -