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

📄 smdlexp.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				BitmapTex *pbmptex = (BitmapTex*)ptexmap;
				strcpy(szBitmapName, pbmptex->GetMapName());
				TSTR strPath, strFile;
				SplitPathFile(TSTR(szBitmapName), &strPath, &strFile);
				strcpy(szBitmapName,strFile);
			}
		}

		UVVert UVvertex0( 0, 0, 0 );
		UVVert UVvertex1( 1, 0, 0 );
		UVVert UVvertex2( 0, 1, 0 );
		
		// All faces must have textures assigned to them
		if (ptvface && (pface->flags & HAS_TVERTS))
		{
			// Get TVface's 3 indexes into the Mesh's TVertex array(s).
			DWORD iTVertex0 = ptvface->getTVert(0);
			DWORD iTVertex1 = ptvface->getTVert(1);
			DWORD iTVertex2 = ptvface->getTVert(2);
			ASSERT_AND_ABORT((int)iTVertex0 < pmesh->getNumTVerts(), "Bogus TVertex 0 index");
			ASSERT_AND_ABORT((int)iTVertex1 < pmesh->getNumTVerts(), "Bogus TVertex 1 index");
			ASSERT_AND_ABORT((int)iTVertex2 < pmesh->getNumTVerts(), "Bogus TVertex 2 index");

			// Get the 3 TVertex's for this TVFace
			// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
			UVvertex0 = pmesh->getTVert(iTVertex0);
			UVvertex1 = pmesh->getTVert(iTVertex1);
			UVvertex2 = pmesh->getTVert(iTVertex2);
		}
		else 
		{
			//sprintf(st_szDBG, "ERROR--Node %s has a textureless face.  All faces must have an applied texture.", (char*)strNodeName);
			//ASSERT_AND_ABORT(FALSE, st_szDBG);
		}
		
		/*
		const char *szExpectedExtension = ".bmp";
		if (stricmp(szBitmapName+strlen(szBitmapName)-strlen(szExpectedExtension), szExpectedExtension) != 0)
			{
			sprintf(st_szDBG, "Node %s uses %s, which is not a %s file", (char*)strNodeName, szBitmapName, szExpectedExtension);
			ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
		*/

		// Determine owning bones for the vertices.
		int iNodeV0, iNodeV1, iNodeV2;
		// Simple 3dsMax model: the vertices are owned by the object, and hence the node
		iNodeV0 = iNode;
		iNodeV1 = iNode;
		iNodeV2 = iNode;
		
		// Rotate the face vertices out of object-space, and into world-space space
		Point3 v0 = pt3Vertex0 * mat3ObjectTM;
		Point3 v1 = pt3Vertex1 * mat3ObjectTM;
		Point3 v2 = pt3Vertex2 * mat3ObjectTM;


		Matrix3 mat3ObjectNTM = mat3ObjectTM;
		mat3ObjectNTM.NoScale( );
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus pre normal 0" );
		pt3Vertex0Normal = VectorTransform(mat3ObjectNTM, pt3Vertex0Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus post normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus pre normal 1" );
		pt3Vertex1Normal = VectorTransform(mat3ObjectNTM, pt3Vertex1Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus post normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus pre normal 2" );
		pt3Vertex2Normal = VectorTransform(mat3ObjectNTM, pt3Vertex2Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus post normal 2" );

		// Finally dump the bitmap name and 3 lines of face info
		fprintf(m_pfile, "%s\n", szBitmapName);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f",
				iNodeV0, v0.x, v0.y, v0.z,
				pt3Vertex0Normal.x, pt3Vertex0Normal.y, pt3Vertex0Normal.z,
				UVvertex0.x, UVvertex0.y);
		DumpWeights( iVertex0 );
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f",
				iNodeV1, v1.x, v1.y, v1.z,
				pt3Vertex1Normal.x, pt3Vertex1Normal.y, pt3Vertex1Normal.z,
				UVvertex1.x, UVvertex1.y);
		DumpWeights( iVertex1 );
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f",
				iNodeV2, v2.x, v2.y, v2.z,
				pt3Vertex2Normal.x, pt3Vertex2Normal.y, pt3Vertex2Normal.z,
				UVvertex2.x, UVvertex2.y);
		DumpWeights( iVertex2 );
	}	

	cleanup( );	
	return TREE_CONTINUE;
}


#define MAX_BLEND_WEIGHTS 8

static struct {
	int iNode;
	float flWeight;
} aWeights[MAX_BLEND_WEIGHTS+1];

int AddWeight( int iCount, int iNode, float flWeight )
{
	if (flWeight < 0.001)
		return iCount;

	for (int i = 0; i < iCount; i++)
	{
		if (aWeights[i].flWeight < flWeight)
		{
			for (int j = iCount; j > i; j--)
			{
				aWeights[j] = aWeights[j-1];
			}
			break;
		}
	}
	aWeights[i].iNode = iNode;
	aWeights[i].flWeight = flWeight;

	iCount++;
	if (iCount > MAX_BLEND_WEIGHTS)
		iCount = MAX_BLEND_WEIGHTS;

	return iCount;
}


void DumpModelTEP::DumpWeights(int iVertex)
{
	if (m_mcExport)
	{
		IPhyVertexExport *vtxExport = m_mcExport->GetVertexInterface(iVertex);

		if (vtxExport)
		{
			if (vtxExport->GetVertexType() & BLENDED_TYPE)
			{
				IPhyBlendedRigidVertex *pBlend = ((IPhyBlendedRigidVertex *)vtxExport);
				int iCount = 0;

				for (int i = 0; i < pBlend->GetNumberNodes(); i++)
				{
					iCount = AddWeight( iCount, GetIndexOfINode( pBlend->GetNode( i ) ), pBlend->GetWeight( i ) );
				}

				fprintf(m_pfile, " %2d  ", iCount );
				for (i = 0; i < iCount; i++)
				{
					fprintf(m_pfile, " %2d %5.3f ", aWeights[i].iNode, aWeights[i].flWeight );
				}
			}
			else 
			{
				INode *Bone = ((IPhyRigidVertex *)vtxExport)->GetNode();

				fprintf(m_pfile, "  1   %2d 1.000", GetIndexOfINode(Bone) );
			}
			m_mcExport->ReleaseVertexInterface(vtxExport);
		}
	} 
	else if (m_wa != NULL)
	{
		int iCount = 0;

		for ( int iBone = 0; iBone < m_wa->nb; iBone++)
		{
			if (m_wa->w[iVertex * m_wa->nb + iBone] > 0.0)
			{
				BonesPro_Bone bone;
				bone.t = BP_TIME_ATTACHED;
				bone.index = iBone;
				m_bonesProMod->SetProperty( BP_PROPID_GET_BONE_STAT, &bone );
				if (bone.node != NULL)
				{
					iCount = AddWeight( iCount, GetIndexOfINode( bone.node ), m_wa->w[iVertex * m_wa->nb + iBone] );
				}
			}
		}

		fprintf(m_pfile, " %2d  ", iCount );
		for (int i = 0; i < iCount; i++)
		{
			fprintf(m_pfile, " %2d %5.3f ", aWeights[i].iNode, aWeights[i].flWeight );
		}
	}

	fprintf(m_pfile, "\n" );
	fflush( m_pfile );
}

void DumpModelTEP::cleanup(void)
{
	if (m_phyMod && m_phyExport)
	{
		if (m_mcExport)
		{
			m_phyExport->ReleaseContextInterface(m_mcExport);
			m_mcExport = NULL;
        }
        m_phyMod->ReleaseInterface(I_PHYINTERFACE, m_phyExport);
		m_phyExport = NULL;
		m_phyMod = NULL;
	}
}


Point3 DumpModelTEP::Pt3GetRVertexNormal(RVertex *prvertex, DWORD smGroupFace)
{
	// Lookup the appropriate vertex normal, based on smoothing group.
	int cNormals = prvertex->rFlags & NORCT_MASK;

	ASSERT_MBOX((cNormals == 1 && prvertex->ern == NULL) ||
				(cNormals > 1 && prvertex->ern != NULL), "BOGUS RVERTEX");
	
	if (cNormals == 1)
		return prvertex->rn.getNormal();
	else
	{
		for (int irn = 0; irn < cNormals; irn++)
			if (prvertex->ern[irn].getSmGroup() & smGroupFace)
				break;

		if (irn >= cNormals) 
		{
			irn = 0;
			// ASSERT_MBOX(irn < cNormals, "unknown smoothing group\n");
		}
		return prvertex->ern[irn].getNormal();
	}
}





//===========================================================
// Dialog proc for export options
//
static BOOL CALLBACK ExportOptionsDlgProc(
	HWND	hDlg,
	UINT	message,
	WPARAM	wParam,
	LPARAM	lParam)
{
	static SmdExportClass *pexp;
	switch (message)
	{
	case WM_INITDIALOG:
		pexp = (SmdExportClass*) lParam;
		CheckRadioButton(hDlg, IDC_CHECK_SKELETAL, IDC_CHECK_REFFRAME, IDC_CHECK_SKELETAL);
		SetFocus(GetDlgItem(hDlg,IDOK));
		return FALSE;
	case WM_DESTROY:
		return FALSE;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			pexp->m_fReferenceFrame	= IsDlgButtonChecked(hDlg, IDC_CHECK_REFFRAME);
			EndDialog(hDlg, 1);		// 1 indicates "ok to export"
			return TRUE;
		case IDCANCEL:				// 0 indicates "cancel export"
			EndDialog(hDlg, 0);
			return TRUE;
		case IDC_CHECK_SKELETAL:
		case IDC_CHECK_REFFRAME:
			CheckRadioButton(hDlg, IDC_CHECK_SKELETAL, IDC_CHECK_REFFRAME, LOWORD(wParam));
			break;
		}
	}
	return FALSE;
}



//========================================================================
// Utility functions for getting/setting the personal "node index" property.
// NOTE: I'm storing a string-property because I hit a 3DSMax bug in v1.2 when I
// NOTE: tried using an integer property.
// FURTHER NOTE: those properties seem to change randomly sometimes, so I'm
// implementing my own.

typedef struct
{
	char	szNodeName[SmdExportClass::MAX_NAME_CHARS];
	int		iNode;
} NAMEMAP;
const int MAX_NAMEMAP = 512;
static NAMEMAP g_rgnm[MAX_NAMEMAP];

int GetIndexOfINode(INode *pnode, BOOL fAssertPropExists)
{
	TSTR strNodeName(pnode->GetName());
	for (int inm = 0; inm < g_inmMac; inm++)
	{
		if (FStrEq(g_rgnm[inm].szNodeName, (char*)strNodeName))
		{
			return g_rgnm[inm].iNode;
		}
	}

	if (fAssertPropExists)
		ASSERT_MBOX(FALSE, "No NODEINDEXSTR property");
	return -7777;
}

	
void SetIndexOfINode(INode *pnode, int inode)
{
	TSTR strNodeName(pnode->GetName());
	NAMEMAP *pnm;
	for (int inm = 0; inm < g_inmMac; inm++)
		if (FStrEq(g_rgnm[inm].szNodeName, (char*)strNodeName))
			break;
	if (inm < g_inmMac)
		pnm = &g_rgnm[inm];
	else
	{
		ASSERT_MBOX(g_inmMac < MAX_NAMEMAP, "NAMEMAP is full");
		pnm = &g_rgnm[g_inmMac++];
		strcpy(pnm->szNodeName, (char*)strNodeName);
	}
	pnm->iNode = inode;
}


//=============================================================
// Returns TRUE if a node should be ignored during tree traversal.
//
BOOL FUndesirableNode(INode *pnode)
{
	// Get Node's underlying object, and object class name
	Object *pobj = pnode->GetObjectRef();

	// Don't care about lights, dummies, and cameras
	if (pobj->SuperClassID() == CAMERA_CLASS_ID)
		return TRUE;
	if (pobj->SuperClassID() == LIGHT_CLASS_ID)
		return TRUE;

	return FALSE;
}


//=============================================================
// Returns TRUE if a node has been marked as skippable
//
BOOL FNodeMarkedToSkip(INode *pnode)
{
	return (::GetIndexOfINode(pnode) == SmdExportClass::UNDESIRABLE_NODE_MARKER);
}

	
//=============================================================
// Reduces a rotation to within the -2PI..2PI range.
//
static float FlReduceRotation(float fl)
{
	while (fl >= TWOPI)
		fl -= TWOPI;
	while (fl <= -TWOPI)
		fl += TWOPI;
	return fl;
}

⌨️ 快捷键说明

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