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

📄 nvcomplexmesh.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		{
			D3DXVECTOR3 NormalizedNormal;

  			// Get the cross of the S and T vectors
  			D3DXVec3Cross(&pSxTBasis[i], &pSBasis[i], &pTBasis[i]);
 			D3DXVec3Normalize(&pSxTBasis[i], &pSxTBasis[i]);


			// Need a normalized normal
  			D3DXVec3Normalize(&NormalizedNormal, &pNormal[i]);

	  		// v coordinates go in opposite direction from the texture v increase in xyz
	 		pTBasis[i] = -pTBasis[i];

			// Get the direction of the SxT vector
  			if (D3DXVec3Dot(&pSxTBasis[i], &NormalizedNormal) < 0.0f)
  			{
  				pSxTBasis[i] = -pSxTBasis[i];
  			}
		}
  	}

	return true;

}

bool NVComplexMesh::CreateFromXFile(LPDIRECT3DDEVICE8 pDevice, const char* fileName)
{
	HRESULT hr;
	LPD3DXBUFFER pMaterials = NULL;
	LPD3DXMESH tempMesh = NULL;
	LPD3DXMESH tempMeshOpt = NULL;
	DWORD dwNumMaterials;
	LPDIRECT3DVERTEXBUFFER8 pVB = NULL;
	LPDIRECT3DINDEXBUFFER8 pIB = NULL;
	
	Release();

	// If there's a path to this file, jump to this directory to ensure correct loading of textures, etc.
	m_strDirectory = fileName;
	std::string::size_type Pos = m_strDirectory.find_last_of("\\", m_strDirectory.size());
	if (Pos != m_strDirectory.npos)
	{
		m_strDirectory = m_strDirectory.substr(0, Pos);
	}										
	else
	{
		m_strDirectory = ".";
	}

	// Load the mesh into system memory
	hr = D3DXLoadMeshFromX(const_cast<char*>(fileName), D3DXMESH_SYSTEMMEM, pDevice, NULL, (ID3DXBuffer**)&pMaterials, &dwNumMaterials, &tempMesh);
	if (FAILED(hr))
		return false;

	// Sort the attributes.
	hr = tempMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &tempMeshOpt);
	if (FAILED(hr))
		return false;

	hr = tempMeshOpt->GetVertexBuffer(&pVB);
	if (FAILED(hr))
	{
		SAFE_RELEASE(m_pBoneNames);
		SAFE_RELEASE(m_pBoneTransforms);
		return false;
	}		

	hr = tempMeshOpt->GetIndexBuffer(&pIB);
	if (FAILED(hr))
	{
		SAFE_RELEASE(pVB);
		SAFE_RELEASE(m_pBoneNames);
		SAFE_RELEASE(m_pBoneTransforms);
		return false;
	}

	bool bSuccess = CreateFromXFileData(pDevice, pVB, pIB, pMaterials, dwNumMaterials, tempMeshOpt);
	
	SAFE_RELEASE(pMaterials);
	SAFE_RELEASE(tempMesh);
	SAFE_RELEASE(tempMeshOpt);
	SAFE_RELEASE(pIB);
	SAFE_RELEASE(pVB);
	
	return bSuccess;
}

bool NVComplexMesh::CreateFromXof(LPDIRECT3DDEVICE8 pDevice, LPDIRECTXFILEDATA pxofobjCur)
{
	HRESULT hr;
	LPD3DXSKINMESH tempSkinMesh = NULL;
	LPD3DXMESH tempMesh = NULL;
	LPD3DXMESH tempMeshOpt = NULL;
	LPD3DXBUFFER pMaterials = NULL;
	LPD3DXBUFFER pAdjacency = NULL;
	DWORD dwNumMaterials;
	LPDIRECT3DVERTEXBUFFER8 pVB = NULL;
	LPDIRECT3DINDEXBUFFER8 pIB = NULL;

	Release();

	std::string strPathSize;
	DWORD dwPathSize = GetCurrentDirectory(0, &m_strDirectory[0]);
	m_strDirectory.resize(dwPathSize);
	GetCurrentDirectory(dwPathSize, &m_strDirectory[0]);

	// Remove the 0 off the string so we can sew in more data
	std::string::size_type Pos = m_strDirectory.find_last_of('\0', m_strDirectory.size());
	if (Pos != m_strDirectory.npos)
	{
		m_strDirectory = m_strDirectory.substr(0, Pos);
	}										

    hr = D3DXLoadSkinMeshFromXof(pxofobjCur, D3DXMESH_SYSTEMMEM, pDevice, &pAdjacency, (ID3DXBuffer**)&pMaterials, &dwNumMaterials,
        &m_pBoneNames, &m_pBoneTransforms, &tempSkinMesh);
    if (FAILED(hr))
        return false;

	m_dwNumBones = tempSkinMesh->GetNumBones();
	if (m_dwNumBones != 0)
	{
		DWORD dwMaxFaceInfluences;
		DWORD dwNumFaces;
		DWORD dwNumBoneCombinations;

		m_dwBonePaletteSize = m_dwDesiredPaletteSize;
        
		tempSkinMesh->GetMaxFaceInfluences(&dwMaxFaceInfluences);
	    dwNumFaces = tempSkinMesh->GetNumFaces();

        // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri)
        // can be handled
        dwMaxFaceInfluences = min(dwMaxFaceInfluences, 12);

		// Expand the palette to fit if we have to
		if (m_dwBonePaletteSize < dwMaxFaceInfluences)
			m_dwBonePaletteSize = dwMaxFaceInfluences;

		// PaletteSize is the min of the requested palette size or the number of bones (if there are less bones)
		m_dwBonePaletteSize = min(m_dwBonePaletteSize, m_dwNumBones);

		m_pBoneMatrices = new const D3DXMATRIX*[m_dwNumBones];

		hr = tempSkinMesh->ConvertToIndexedBlendedMesh(D3DXMESH_SYSTEMMEM, (DWORD*)pAdjacency->GetBufferPointer(), m_dwBonePaletteSize, NULL,
			&dwNumBoneCombinations, &m_pBoneCombinations, &tempMesh);
		if (FAILED(hr))
			return false;

		SAFE_RELEASE(tempSkinMesh);
	}
	else
	{
		// Discard the skinning part
		tempSkinMesh->GetOriginalMesh(&tempMesh);
		SAFE_RELEASE(tempSkinMesh);

	}

	// Sort the attributes.
	hr = tempMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &tempMeshOpt);
	if (FAILED(hr))
		return false;
	
	hr = tempMeshOpt->GetVertexBuffer(&pVB);
	if (FAILED(hr))
	{
		SAFE_RELEASE(m_pBoneNames);
		SAFE_RELEASE(m_pBoneTransforms);
		return false;
	}		

	hr = tempMeshOpt->GetIndexBuffer(&pIB);
	if (FAILED(hr))
	{
		SAFE_RELEASE(pVB);
		SAFE_RELEASE(m_pBoneNames);
		SAFE_RELEASE(m_pBoneTransforms);
		return false;
	}

	bool bSuccess = CreateFromXFileData(pDevice, pVB, pIB, pMaterials, dwNumMaterials, tempMeshOpt);
	if (!bSuccess)
	{
		SAFE_RELEASE(m_pBoneNames);
		SAFE_RELEASE(m_pBoneTransforms);
		SAFE_DELETE_ARRAY(m_pBoneMatrices);
	}
	
	SAFE_RELEASE(pMaterials);
	SAFE_RELEASE(tempMesh);
	SAFE_RELEASE(tempMeshOpt);
	SAFE_RELEASE(pIB);
	SAFE_RELEASE(pVB);

	return bSuccess;

}

bool NVComplexMesh::CreateFromXFileData(LPDIRECT3DDEVICE8 pDevice, LPDIRECT3DVERTEXBUFFER8 pVB, LPDIRECT3DINDEXBUFFER8 pIB, LPD3DXBUFFER pMaterials, DWORD dwNumMaterials, LPD3DXMESH pMesh)
{
	DWORD i;
	DWORD dwNumAttributes;
	D3DXATTRIBUTERANGE* pAttributes;
	D3DVERTEXBUFFER_DESC vbdesc;
	D3DINDEXBUFFER_DESC ibdesc;
	DWORD dwTexCount;
	HRESULT hr;

	hr = pMesh->GetAttributeTable(NULL, &dwNumAttributes);
	if (FAILED(hr))
		return false;

	pAttributes = (D3DXATTRIBUTERANGE*)HeapAlloc(GetProcessHeap(), 0, dwNumAttributes * sizeof(D3DXATTRIBUTERANGE));
	hr = pMesh->GetAttributeTable(pAttributes, &dwNumAttributes);

	pIB->GetDesc(&ibdesc);
	pVB->GetDesc(&vbdesc);

	LPD3DXBONECOMBINATION pBoneComb = NULL;
	
	if (m_pBoneCombinations)
		pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(m_pBoneCombinations->GetBufferPointer());

	typedef std::map<DWORD, NVResourceRef> tMapMaterialToResource;
	tMapMaterialToResource MaterialToResource;

	// First store the material data
	for (i = 0; i < dwNumAttributes; i++)
	{
		NVComplexMeshSection Attrib;
		NVMaterialResource* pMaterial;
		DWORD dwMaterialAttrib;
		NVResourceRef Material;

		// The material either matches the attribute, or it is in referred to in the bone combination buffer.
		if (pBoneComb)
		{
			dwMaterialAttrib = pBoneComb[i].AttribId;
		}
		else
		{
			dwMaterialAttrib = i;
		}

		tMapMaterialToResource::const_iterator itrMaterial = MaterialToResource.find(dwMaterialAttrib);
		if (itrMaterial != MaterialToResource.end())
		{
			Material = itrMaterial->second;
			pMaterial = NVMaterialResource::GetMaterialResourcePtr(Material.GetPointer());
		}
		else
		{
			pMaterial = new NVMaterialResource;
			Material = NVRESOURCEMANAGER.AddResource(pMaterial);
			MaterialToResource.insert(tMapMaterialToResource::value_type(dwMaterialAttrib, Material));

			// Create dummy material if there are none in the mesh
			if (!pMaterials)
			{
				// Create named constants for this mesh
				pMaterial->AddValue("diffuse", NVValue(NVV_VECTOR4, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f)));
				pMaterial->AddValue("power", NVValue(NVV_VECTOR4, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 50.0f)));
			}
			else
			{
				NVASSERT(pMaterials->GetBufferSize() >= (dwNumMaterials * sizeof(D3DXMATERIAL)), "Materials buffer is too small");
				D3DXMATERIAL* pMat = (D3DXMATERIAL*)pMaterials->GetBufferPointer();
			
				// Create named constants for this mesh
				pMaterial->AddValue("diffuse", NVValue(NVV_VECTOR4, &pMat[i].MatD3D.Diffuse));
				pMaterial->AddValue("ambient", NVValue(NVV_VECTOR4, &pMat[i].MatD3D.Ambient));
				pMaterial->AddValue("emissive", NVValue(NVV_VECTOR4, &pMat[i].MatD3D.Emissive));

				// Only add specular if there's a specular power
				if (pMat[i].MatD3D.Power != 0.0f)
				{
					pMaterial->AddValue("power", NVValue(NVV_VECTOR4, D3DXVECTOR4(0.0f, 0.0f, 0.0f, pMat[i].MatD3D.Power)));
					pMaterial->AddValue("specular", NVValue(NVV_VECTOR4, &pMat[i].MatD3D.Specular));
				}

				if (pMat[i].pTextureFilename)
				{
					string strFilePath = m_strDirectory + "\\" + pMat[i].pTextureFilename;
					HANDLE hFile = CreateFile(strFilePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
					if (hFile == INVALID_HANDLE_VALUE) 
					{
						// Try without the appended directory
						strFilePath = pMat[i].pTextureFilename;
						hFile = CreateFile(strFilePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
					}
					
					if (hFile != INVALID_HANDLE_VALUE)
					{
						CloseHandle(hFile);
						
						// Add this texture to the resource manager
						NVTextureFileResource* pTexture = new NVTextureFileResource(pDevice, strFilePath);
						pMaterial->AddValue("basemap", NVValue(NVV_RESOURCE, &NVRESOURCEMANAGER.AddResource(pTexture)));
					}
				}			
			}
		}
			
		Attrib.m_dwAttribId = pAttributes[i].AttribId;
		Attrib.m_TriType = NVComplexMeshSection::IndexedTriangleList;
		Attrib.m_dwIndexStart = pAttributes[i].FaceStart * 3;
		Attrib.m_dwIndexCount = pAttributes[i].FaceCount * 3;
		Attrib.m_dwVertexStart = pAttributes[i].VertexStart;
		Attrib.m_dwVertexCount = pAttributes[i].VertexCount;
		Attrib.m_Material = Material;
		m_Sections.push_back(Attrib);
	}

	// Copy the vertex data
	BYTE* pVertex;
	hr = pVB->Lock(0, vbdesc.Size,(BYTE**)&pVertex, 0);

	DWORD dwTextures = ((vbdesc.FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
	DWORD dwStride = D3DXGetFVFVertexSize(vbdesc.FVF);

	// Create array pointers.  May be setup depending on contents of mesh
	D3DXVECTOR3* pPosition = NULL;
	D3DXVECTOR3* pNormal = NULL;
	D3DXVECTOR4* pDiffuse = NULL;
	D3DXVECTOR4* pSpecular = NULL;
	vector<D3DXVECTOR2*> Textures;
	vector<D3DXVECTOR4*> BoneIndices;
	vector<D3DXVECTOR4*> BoneWeights;

	NVVertexData* pData = NULL;

	SetNumVertices(vbdesc.Size / dwStride);

	m_dwNumWeights = 0;
	DWORD dwNumBoneQuadruples = 0;
	if (m_pBoneTransforms)
	{
		if ((vbdesc.FVF & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
		{
			switch(vbdesc.FVF & D3DFVF_POSITION_MASK)
			{
				case D3DFVF_XYZB1:
					m_dwNumWeights = 1;
					break;
				case D3DFVF_XYZB2:
					m_dwNumWeights = 2;
					break;
				case D3DFVF_XYZB3:
					m_dwNumWeights = 3;
					break;
				case D3DFVF_XYZB4:
					m_dwNumWeights = 4;
					break;
				case D3DFVF_XYZB5:
					m_dwNumWeights = 5;
					break;
				default:
					NVASSERT(0, "ERROR: Num weights not known");
					break;
			}
			dwNumBoneQuadruples = (m_dwNumWeights + 3) / 4;
		}
		else
		{
			m_dwNumWeights = 1;
			dwNumBoneQuadruples = 1;
		}
	}

	// Create vertex data in the pass for the geometry we found in the mesh
	if (vbdesc.FVF & D3DFVF_XYZ || m_pBoneTransforms)
	{
		pData = AddVertexData(NVVERT_POSITION, D3DDATATYPE_FLOAT3);
		pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pData);

		for (i = 0; i < dwNumBoneQuadruples; i++)
		{
			pData = AddVertexData(NVVERT_BONEINDICES0 + i, D3DDATATYPE_FLOAT4);
			BoneIndices.push_back(GetDataPointer<D3DXVECTOR4, D3DDATATYPE_FLOAT4>(pData));

			pData = AddVertexData(NVVERT_BONEWEIGHTS0 + i, D3DDATATYPE_FLOAT4);
			BoneWeights.push_back(GetDataPointer<D3DXVECTOR4, D3DDATATYPE_FLOAT4>(pData));

		}
	}

	// Normal
	if (vbdesc.FVF & D3DFVF_NORMAL)
	{
		pData = AddVertexData(NVVERT_NORMAL, D3DDATATYPE_FLOAT3);
		pNormal = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pData);
	}
	// Diffuse
	if (vbdesc.FVF & D3DFVF_DIFFUSE)
	{
		pData = AddVertexData(NVVERT_DIFFUSE, D3DDATATYPE_FLOAT4);
		pDiffuse = GetDataPointer<D3DXVECTOR4, D3DDATATYPE_FLOAT4>(pData);
	}
	// Specular
	if (vbdesc.FVF & D3DFVF_SPECULAR)
	{
		pData = AddVertexData(NVVERT_SPECULAR, D3DDATATYPE_FLOAT4);
		pSpecular = GetDataPointer<D3DXVECTOR4, D3DDATATYPE_FLOAT4>(pData);
	}
	// Up to 8 texture coordinates
	for (dwTexCount = 0; dwTexCount < dwTextures; dwTexCount++)
	{
		pData = AddVertexData(NVVERT_TEXTURE0 + dwTexCount, D3DDATATYPE_FLOAT2);
		Textures.push_back(GetDataPointer<D3DXVECTOR2, D3DDATATYPE_FLOAT2>(pData));
	}

	for (i = 0; i < (vbdesc.Size / dwStride); i++)
	{
		BYTE* pVert = pVertex;
		
		if (m_dwNumWeights == 0)
		{
			// Position
			if (vbdesc.FVF & D3DFVF_XYZ)
			{
				pPosition[i] = (*(D3DXVECTOR3*)pVert);
				pVert += sizeof(D3DXVECTOR3);
			}
		}
		else
		{
			DWORD dwWeightCount;
			DWORD dwIndexCount;
			DWORD dwQuadCount;

			pPosition[i] = (*(D3DXVECTOR3*)pVert);
			pVert += sizeof(D3DXVECTOR3);

			// Add the weights.  We retrieve the list of floats and pack them
			// into vec4's.  The last weight is 1 - totalweights
			float ftotalweight = 0.0f;
			dwQuadCount = 0;
			dwWeightCount = 0;

			BoneWeights[dwQuadCount][i] = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);

			while (1)
			{
				float fweight;
				bool bLastWeight = false;
				if (dwWeightCount == (m_dwNumWeights - 1))
				{
					fweight = 1.0f - ftotalweight;
					bLastWeight = true;
				}
				else
				{
					fweight = (*(float*)pVert);
					pVert += sizeof(float);
					ftotalweight += fweight;
				}

				if ((dwWeightCount & 0x3) == 0)
				{
					BoneWeights[dwQuadCount][i].x = fweight;
				}
				else if ((dwWeightCount & 0x3) == 1)
				{

⌨️ 快捷键说明

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