示例#1
0
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IUnknown::drop() for more information.
SMesh* MDLFileLoader::CreateMesh(FileReader* file)
{
	studiohdr_t* pMDLFile = (studiohdr_t*)new byte[file->GetSize()];
	g_pActiveStudioHdr = pMDLFile;
	file->Read(pMDLFile, file->GetSize());
	mstudiobodyparts_t* pBodyparts = pMDLFile->pBodypart(0);
	mstudiomodel_t* pModel = pBodyparts->pModel(0);
	const mstudio_modelvertexdata_t* pVertexdata = pModel->GetVertexData();

	stringc vtxFile = file->GetFileName();
	vtxFile = vtxFile.subString(0, vtxFile.findLast('.') + 1);
	vtxFile += "dx90.vtx";
	file = m_pFileSystem->CreateAndOpenFile(vtxFile.c_str());

	FileHeader_t* pVtxFile = (FileHeader_t*)new byte[file->GetSize()];
	file->Read(pVtxFile, file->GetSize());
	BodyPartHeader_t* pBodypart = pVtxFile->pBodyPart(0);
	ModelHeader_t* pVtxModel = pBodypart->pModel(0);
	ModelLODHeader_t* pLod = pVtxModel->pLOD(0);

	SMesh* pPirateMesh = new SMesh();
	IDirect3DVertexBuffer9* pVertexBuffer = NULL;

	for (int i=0; i<pLod->numMeshes; i++)
	{
		MeshHeader_t* pMesh = pLod->pMesh(i);
		StripGroupHeader_t* pStripGroup = pMesh->pStripGroup(0);
//		StripHeader_t* pStrip = pStripGroup->pStrip(0);

		SD3D9MeshBuffer* pMeshBuffer = new SD3D9MeshBuffer(m_pDriver, MdlVertexDecl);
		if (i==0)
		{
			pMeshBuffer->CreateVertexBuffer(0, sizeof(MDL_VT), pModel->numvertices, D3DUSAGE_WRITEONLY);
			pVertexBuffer = pMeshBuffer->GetVertexBuffer(0);
			MDL_VT* pVert = NULL;

			pVertexBuffer->Lock(0, 0, (void**)&pVert, 0);
			for (int j=0; j<pModel->numvertices; j++)
			{
				const Vector* p = pVertexdata->Position(j);
				const Vector* n = pVertexdata->Normal(j);
				const Vector2D* t = pVertexdata->Texcoord(j);
				pVert[j].Position[0] = p->x; pVert[j].Position[1] = p->y; pVert[j].Position[2] = p->z;
				pVert[j].Normal[0] = n->x; pVert[j].Normal[1] = n->y; pVert[j].Normal[2] = n->z;
				pVert[j].Texcoord[0] = t->x; pVert[j].Texcoord[1] = t->y;
			}
			pVertexBuffer->Unlock();
		}
		else
		{
			pMeshBuffer->SetVertexBuffer(0, pModel->numvertices, pVertexBuffer);
		}

		mstudiomesh_t* pStudioMesh = pModel->pMesh(i);

		pMeshBuffer->CreateIndexBuffer(pStripGroup->numIndices, D3DUSAGE_WRITEONLY, TRUE);
		u16* pIndices = NULL;

		pMeshBuffer->GetIndexBuffer()->Lock(0, 0, (void**)&pIndices, 0);
		for (int j=0; j<pStripGroup->numIndices; j++)
		{
			pIndices[j] = pStripGroup->pVertex(*(pStripGroup->pIndex(j)))->origMeshVertID + pStudioMesh->vertexoffset;
		}
		pMeshBuffer->GetIndexBuffer()->Unlock();


		mstudiotexture_t* pTexture =  pMDLFile->pTexture(i);
		stringc textureName = file->GetFileName();
		textureName = textureName.subString(0, textureName.findLast('/') + 1);
		textureName = textureName + pTexture->pszName() + ".tga";
		D3D9Texture* pD3DTexture = m_pDriver->GetTexture(textureName.c_str());
		pMeshBuffer->m_Material.Textures[0] = pD3DTexture;

		pPirateMesh->AddMeshBuffer(pMeshBuffer);
		pMeshBuffer->Drop();
	}

	delete[] pVtxFile;
	if (pMDLFile->pVertexBase)
		delete pMDLFile->pVertexBase;
	delete[] pMDLFile;

	file->Drop();

	return pPirateMesh;
}
//-------------------------------------------------------------------------------------------------//
// Class:       CHL2LoaderPlugIn
// 
// Function:    LoadGeometry
// 
// Description: This method gets called by the main application to read in geometry data from
//              a particular file ('strFileName') into the specified model data container
//              ('pModelContainer')
//
//-------------------------------------------------------------------------------------------------//
bool CHL2LoaderPlugIn::LoadGeometry( const RM_TCHAR       *strFileName, 
                                                RmMeshModelContainer *pModelContainer )
{
   //----------------------------------------------------------------------
   // Actual loading code goes here
   //----------------------------------------------------------------------
    HRESULT hr;
	// Store the device pointer
	IDirect3DDevice9 *pd3dDevice = RmGfxGetD3DDevice();

	WCHAR vvdwstr[MAX_PATH];
	WCHAR vtxwstr[MAX_PATH];
	WCHAR mdlwstr[MAX_PATH];

	char vvdstr[MAX_PATH];
	char vtxstr[MAX_PATH];
	char mdlstr[MAX_PATH];

	int vvdFileSize;
	int vtxFileSize;
	int mdlFileSize;
	
	WCHAR tmpStringName[MAX_PATH];
	StringCchCopy( tmpStringName, MAX_PATH, strFileName );
	WCHAR* pch = wcsrchr( tmpStringName, L'\.' );
	*pch='\0';

	StringCchCopy( vvdwstr, MAX_PATH, tmpStringName );
	StringCchCopy( vtxwstr, MAX_PATH, tmpStringName );
	StringCchCopy( mdlwstr, MAX_PATH, tmpStringName );

	StringCchCat( vvdwstr, MAX_PATH, L".vvd" );
	StringCchCat( vtxwstr, MAX_PATH, L".dx90.vtx" );
	StringCchCat( mdlwstr, MAX_PATH, L".mdl" );
    
	WideCharToMultiByte( CP_ACP, 0, vvdwstr, -1, vvdstr, MAX_PATH, NULL, NULL );
	WideCharToMultiByte( CP_ACP, 0, vtxwstr, -1, vtxstr, MAX_PATH, NULL, NULL );
	WideCharToMultiByte( CP_ACP, 0, mdlwstr, -1, mdlstr, MAX_PATH, NULL, NULL );

	ifstream vvdFile( vvdstr,ios::binary );
	ifstream vtxFile( vtxstr,ios::binary );
	ifstream mdlFile( mdlstr,ios::binary );

	vvdFile.seekg(0,ios::end);
	vtxFile.seekg(0,ios::end);
	mdlFile.seekg(0,ios::end);

	vvdFileSize   =   vvdFile.tellg();
	vtxFileSize   =   vtxFile.tellg();
	mdlFileSize   =   mdlFile.tellg();

	vvdFile.seekg(0,ios::beg);
	vtxFile.seekg(0,ios::beg);
	mdlFile.seekg(0,ios::beg);

	char *m_pVvdMem = new char[vvdFileSize];
	char *m_pVtxMem = new char[vtxFileSize];
	char *m_pMdlMem = new char[mdlFileSize];
	vvdFile.read(m_pVvdMem,vvdFileSize);
	vtxFile.read(m_pVtxMem,vtxFileSize);
	mdlFile.read(m_pMdlMem,mdlFileSize);

	vertexFileHeader_t* m_pVvdFileHeader=(vertexFileHeader_t *)m_pVvdMem;
	FileHeader_t*	 m_pVtxFileHeader=(FileHeader_t *)m_pVtxMem;
	studiohdr_t*	 m_pMdlFileHeader=(studiohdr_t *)m_pMdlMem;
	unsigned short    m_iLod=0;
	if (m_pVvdFileHeader->numFixups)
	{
		vertexFileHeader_t *	pNewVvdHdr;
		pNewVvdHdr = new vertexFileHeader_t[vvdFileSize];
		Studio_LoadVertexes( m_pVvdFileHeader, pNewVvdHdr, 0, true );
		free( m_pVvdFileHeader );
		m_pVvdFileHeader = pNewVvdHdr;
	}
	// check mdl header
	if (m_pMdlFileHeader->id != IDSTUDIOHEADER)
	{
		getRmApp()->OutputText( _T(".mdl File id error") );
		return false;
	}
	if (m_pMdlFileHeader->version != STUDIO_VERSION)
	{
		getRmApp()->OutputText( _T(".mdl File version error") );
		return false;
	}

	// check vtx header
	if (m_pVtxFileHeader->version != OPTIMIZED_MODEL_FILE_VERSION)
	{
		getRmApp()->OutputText( _T(".vtd File version error") );
		return false;
	}
	if (m_pVtxFileHeader->checkSum != m_pMdlFileHeader->checksum)
	{
		getRmApp()->OutputText( _T(".vtd File checksum error") );
		return false;
	}

	// check vvd header
	if (m_pVvdFileHeader->id != MODEL_VERTEX_FILE_ID)
	{
		getRmApp()->OutputText( _T(".vvd File id error") );
		return false;
	}
	if (m_pVvdFileHeader->version != MODEL_VERTEX_FILE_VERSION)
	{
		getRmApp()->OutputText( _T(".vvd File version error") );
		return false;
	}
	if (m_pVvdFileHeader->checksum != m_pMdlFileHeader->checksum)
	{
		getRmApp()->OutputText( _T(".vvd File checksum error") );
		return false;
	}

	m_pMdlFileHeader->pVertexBase = (void *)m_pVvdFileHeader;
	m_pMdlFileHeader->pIndexBase  = (void *)m_pVtxFileHeader;

	BodyPartHeader_t* pBodyPart = m_pVtxFileHeader->pBodyPart(0);
	ModelHeader_t*  pModel=pBodyPart->pModel(0);
	ModelLODHeader_t* pLod = pModel->pLOD(m_iLod);

	mstudiobodyparts_t* pStudioBodyPart = m_pMdlFileHeader->pBodypart(0);
	mstudiomodel_t* pStudioModel= pStudioBodyPart->pModel(0);
	int numVerts=0;
	int numIndices=0;
	for (int k=0;k<pStudioModel->nummeshes;k++)
	{
		MeshHeader_t* pMesh = pLod->pMesh(k);
		mstudiomesh_t* pStudioMesh = pStudioModel->pMesh( k );
		for (int j=0;j<pMesh->numStripGroups;j++)
		{
			StripGroupHeader_t* pStripGroup = pMesh->pStripGroup(j);
			numVerts+=pStripGroup->numVerts;
			numIndices+=pStripGroup->numIndices;
		}
	}

	RmMeshModel *pRmMesh = new RmMeshModel();
	pModelContainer->AddMeshModel(pRmMesh);
	pRmMesh->GetVertexArray()->SetNumVertices( numVerts, false );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_BLENDWEIGHT, 0, RMVSDT_FLOAT3 );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_BLENDINDICES, 0, RMVSDT_UBYTE4 );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_POSITION, 0, RMVSDT_FLOAT3 );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_NORMAL, 0, RMVSDT_FLOAT3 );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_TEXCOORD, 0, RMVSDT_FLOAT2 );
	pRmMesh->GetVertexArray()->CreateVertexElementArray( RM_DECLUSAGE_TANGENT, 0, RMVSDT_FLOAT4 );

	RmVertexElementArray *pBlendWeightElementArray  = pRmMesh->GetVertexArray()->GetVertexElementArray( RM_DECLUSAGE_BLENDWEIGHT, 0, RMVSDT_FLOAT3 );
	RmVertexElementArray *pBlendIndicesElementArray  = pRmMesh->GetVertexArray()->GetVertexElementArray( RM_DECLUSAGE_BLENDINDICES, 0, RMVSDT_UBYTE4 );
	RmVertexElementArray *pPositionElementArray  = pRmMesh->GetVertexArray()->GetVertexElementArray( RM_DECLUSAGE_POSITION, 0, RMVSDT_FLOAT3 );
	RmVertexElementArray *pNormalElementArray = pRmMesh->GetVertexArray()->GetVertexElementArray(RM_DECLUSAGE_NORMAL,0,RMVSDT_FLOAT3);
	RmVertexElementArray *pTexCoordElementArray = pRmMesh->GetVertexArray()->GetVertexElementArray(RM_DECLUSAGE_TEXCOORD,0,RMVSDT_FLOAT2);
	RmVertexElementArray *pTangentElementArray = pRmMesh->GetVertexArray()->GetVertexElementArray(RM_DECLUSAGE_TANGENT,0,RMVSDT_FLOAT4);

	unsigned short indexOffset=0;
	unsigned short iVertex=0;
	unsigned short iIndex=0;
	unsigned short iSubset = 0;	

	for (int k=0;k<pStudioModel->nummeshes;k++)
	{
		MeshHeader_t* pMesh = pLod->pMesh(k);
		mstudiomesh_t* pStudioMesh = pStudioModel->pMesh( k );
		for (int j=0;j<pMesh->numStripGroups;j++)
		{
			StripGroupHeader_t* pStripGroup = pMesh->pStripGroup(j);
			for (int i=0;i<pStripGroup->numVerts;i++)
			{
				float *pBoneWeight  = ( float* ) pBlendWeightElementArray->GetBuffer( iVertex );
				float *pBoneIndices = ( float* ) pBlendIndicesElementArray->GetBuffer( iVertex );
				float *pPosition    = ( float* ) pPositionElementArray->GetBuffer( iVertex );
				float *pNormal      = ( float* ) pNormalElementArray->GetBuffer( iVertex );
				float *pTexCoord    = ( float* ) pTexCoordElementArray->GetBuffer( iVertex );
				float *pTangent     = ( float* ) pTangentElementArray->GetBuffer( iVertex );

				float *pVertex = ( float* ) m_pVvdFileHeader->pVertex( pStudioMesh->vertexoffset+pStripGroup->pVertex(i)->origMeshVertID );
				pBoneWeight[0]=	pVertex[0];
				pBoneWeight[1]=	pVertex[1];
				pBoneWeight[2]=	pVertex[2];
				pBoneIndices[0]=pVertex[3];
				pPosition[0]  =	pVertex[4];
				pPosition[1]  =	pVertex[5];
				pPosition[2]  =	pVertex[6];
				pNormal[0]    =	pVertex[7];
				pNormal[1]    =	pVertex[8];
				pNormal[2]    =	pVertex[9];
				pTexCoord[0]  = pVertex[10];
				pTexCoord[1]  = pVertex[11];

				float *pTan = ( float* ) m_pVvdFileHeader->pTangent(pStripGroup->pVertex(i)->origMeshVertID );
				pTangent[0] = pTan[0];
				pTangent[1] = pTan[1];
				pTangent[2] = pTan[2];
				pTangent[3] = pTan[3];
				iVertex++;
			}
			pRmMesh->SetPrimitiveType( RM_PRIMITIVETYPE_TRIANGLELIST );
			pRmMesh->SetNumIndices( numIndices );
			RM_DWORD *pIndices = pRmMesh->GetIndices();
			for (int i=0;i<pStripGroup->numIndices;i+=3)
			{
				pIndices[iIndex]=indexOffset + *pStripGroup->pIndex(i);
				pIndices[iIndex+1]=indexOffset + *pStripGroup->pIndex(i+1);
				pIndices[iIndex+2]=indexOffset + *pStripGroup->pIndex(i+2);
				iIndex+=3;
			}
			indexOffset=iVertex;
		}
	}


	getRmApp()->OutputText( _T("\nLoad '%s' into RenderMonkey.\n"), vvdwstr );
	getRmApp()->OutputText( _T("Load '%s' into RenderMonkey.\n"), vtxwstr );
	getRmApp()->OutputText( _T("Load '%s' into RenderMonkey.\n"), mdlwstr );

	return true;
} // End of LoadGeometry for CHL2LoaderPlugIn