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

📄 nvcomplexmesh.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
   		float y = pPosition[i].y;
   		float z = pPosition[i].z;
   		
   		if (pBounds->m_vecMaxExtents.x < x)
   			pBounds->m_vecMaxExtents.x = x;
   
   		if (pBounds->m_vecMaxExtents.y < y)
   			pBounds->m_vecMaxExtents.y = y;
   
   		if (pBounds->m_vecMaxExtents.z < z)
   			pBounds->m_vecMaxExtents.z = z;
   
   		if (pBounds->m_vecMinExtents.x > x)
   			pBounds->m_vecMinExtents.x = x;
   
   		if (pBounds->m_vecMinExtents.y > y)
   			pBounds->m_vecMinExtents.y = y;
   
   		if (pBounds->m_vecMinExtents.z > z)
   			pBounds->m_vecMinExtents.z = z;
   
   		
   		i++;
   	}
   
	pBounds->CalculateCenterRadius();

	return true;
}

// Setup the data streams for fixed function rendering.
bool NVComplexMesh::SetupFVFStream()
{
	m_dwFVF = 0;
	DWORD dwLocation = 0;
	NVVertexData* pVertexData;
	
	pVertexData = FindVertexData(NVVERT_POSITION);
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		m_dwFVF |= D3DFVF_XYZ;
	}

	pVertexData = FindVertexData(NVVERT_NORMAL);
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		m_dwFVF |= D3DFVF_NORMAL;
	}

	pVertexData = FindVertexData(NVVERT_DIFFUSE);
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		m_dwFVF |= D3DFVF_DIFFUSE;
	}

	pVertexData = FindVertexData(NVVERT_SPECULAR);
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		m_dwFVF |= D3DFVF_SPECULAR;
	}

	for (DWORD i = 0; i < NV_MAX_TEXTURES; i++)
	{
		pVertexData = FindVertexData(NVVERT_TEXTURE0 + i);
		if (pVertexData)
		{
			pVertexData->SetLocation(dwLocation++);
			m_dwFVF &= ~D3DFVF_TEXCOUNT_MASK;
			m_dwFVF |= ((i + 1) << D3DFVF_TEXCOUNT_SHIFT);
		}
	}
	
	return true;
}

class DataSorter
{
public:
	bool operator()(const NVVertexData* lhs, const NVVertexData* rhs) const
	{
		if (lhs->GetLocation() < rhs->GetLocation())
			return true;

		return false;
	}
};
// ComplexMeshPass members
// Store internal info about the current set of buffers for this pass.
bool NVComplexMesh::PrepareDeviceObjects(LPDIRECT3DDEVICE8 pDevice)
{
	DWORD i;
	HRESULT hr;
	vector<NVVertexData*> SortedDataList;
	vector<NVVertexData*>::iterator itrDataList;
	
	m_dwStride = 0;

	SAFE_RELEASE(m_pVB);

	tIndexBufferArray::iterator itrIndices = m_IndexBuffers.begin();
	while (itrIndices != m_IndexBuffers.end())
	{
		SAFE_RELEASE(*itrIndices);
		itrIndices++;
	}
	m_IndexBuffers.clear();
	
	tVertexDataMap::iterator itrVertexData = m_VertexData.begin();
	while (itrVertexData != m_VertexData.end())
	{
		NVVertexData* pVertexData = itrVertexData->second;
		if (pVertexData->GetLocation() != NVCOMPLEXMESH_NO_VERTEX)
		{
			SortedDataList.push_back(pVertexData);
			switch(pVertexData->GetDataType())
			{
				case D3DDATATYPE_FLOAT4:
					m_dwStride += sizeof(D3DXVECTOR4);
					break;
				case D3DDATATYPE_FLOAT3:
					m_dwStride += sizeof(D3DXVECTOR3);
					break;
				case D3DDATATYPE_FLOAT2:
					m_dwStride += sizeof(D3DXVECTOR2);
					break;
				default:
					NVASSERT(0, "Unknown vertex data type");
					break;
			}
		}
		itrVertexData++;
	}

	sort(SortedDataList.begin(), SortedDataList.end(), DataSorter());
	
	NVASSERT(m_dwStride != 0, "Stride shouldn't be 0");
	if (m_dwStride == 0)
		return true;

	// Find the first data element
	DWORD dwArraySize = SortedDataList.front()->size();

	// Create a VB to match
	hr = pDevice->CreateVertexBuffer(m_dwStride * dwArraySize, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pVB);
	if (FAILED(hr))	
	{
		NVASSERT(0, "Failed VB create");
		return false;
	}

	BYTE* pDest;
	DWORD dwIndicesToCreate = m_Indices.size();
	DWORD dwIndicesCreated = 0;
	while(dwIndicesCreated < dwIndicesToCreate)
	{
		DWORD dwNumIndices;
		LPDIRECT3DINDEXBUFFER8 pIB;

		dwNumIndices = dwIndicesToCreate - dwIndicesCreated;
		if (dwNumIndices > NV_MAX_INDICES_IN_BUFFER)
		{
			dwNumIndices = NV_MAX_INDICES_IN_BUFFER;
		}

		// Create an IB to match
		hr = pDevice->CreateIndexBuffer(dwNumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIB);
		if (FAILED(hr))
		{
			NVASSERT(0, "Failed IB create");
			SAFE_RELEASE(m_pVB);
			return false;
		}

		pIB->Lock(0, dwNumIndices * sizeof(WORD), (BYTE**)&pDest, 0);
		memcpy(pDest, &m_Indices[0] + dwIndicesCreated, dwNumIndices * sizeof(WORD));
		pIB->Unlock();

		m_IndexBuffers.push_back(pIB);

		dwIndicesCreated += dwNumIndices;
	}

	m_pVB->Lock(0, m_dwStride * dwArraySize, (BYTE**)&pDest, 0);
	// For each vertex
	for (i = 0; i < dwArraySize; i++)
	{
		// For each data item
		itrDataList = SortedDataList.begin();
		while (itrDataList != SortedDataList.end())
		{
			NVVertexData* pWriteData = *itrDataList;
			NVASSERT(pWriteData->size() == dwArraySize, "Array size mismatch");

			switch(pWriteData->GetDataType())
			{
				case D3DDATATYPE_DWORD:
					*(DWORD*)pDest = *(((DWORD*)pWriteData->GetPointer()) + i);
					pDest += sizeof(DWORD);
					break;
				case D3DDATATYPE_FLOAT4:
					*(D3DXVECTOR4*)pDest = *(((D3DXVECTOR4*)pWriteData->GetPointer()) + i);
					pDest += sizeof(D3DXVECTOR4);
					break;
				case D3DDATATYPE_FLOAT3:
					*(D3DXVECTOR3*)pDest = *(((D3DXVECTOR3*)pWriteData->GetPointer()) + i);
					pDest += sizeof(D3DXVECTOR3);
					break;
				case D3DDATATYPE_FLOAT2:
					*(D3DXVECTOR2*)pDest = *(((D3DXVECTOR2*)pWriteData->GetPointer()) + i);
					pDest += sizeof(D3DXVECTOR2);
					break;
				case D3DDATATYPE_FLOAT1:
					*(float*)pDest = *(((float*)pWriteData->GetPointer()) + i);
					pDest += sizeof(float);
					break;
			}
			itrDataList++;
		}
	}
	m_pVB->Unlock();
	

	return true;
}

NVVertexData* NVComplexMesh::AddVertexData(NVVERTNAME Name, eD3DDATATYPE DataType)
{
	NVVertexData* pData = FindVertexData(Name);
	if (pData)
		return pData;

	std::pair<tVertexDataMap::iterator, bool> Ret;
	switch(DataType)
	{
		case D3DDATATYPE_DWORD:
			Ret = m_VertexData.insert(tVertexDataMap::value_type(Name, new tNVData_dword()));
			break;
		case D3DDATATYPE_FLOAT1:
			Ret = m_VertexData.insert(tVertexDataMap::value_type(Name, new tNVData_float1()));
			break;
		case D3DDATATYPE_FLOAT2:
			Ret = m_VertexData.insert(tVertexDataMap::value_type(Name, new tNVData_float2()));
			break;
		case D3DDATATYPE_FLOAT3:
			Ret = m_VertexData.insert(tVertexDataMap::value_type(Name, new tNVData_float3()));
			break;
		case D3DDATATYPE_FLOAT4:
			Ret = m_VertexData.insert(tVertexDataMap::value_type(Name, new tNVData_float4()));
			break;
		default:
			NVASSERT(0, "Unknown data type!");
			break;
	}

	if (Ret.second == true)
	{
		pData = ((Ret.first)->second);

		// All streams must be the same length
		pData->resize(m_dwNumVertices);
		return pData;
	}

	return NULL;
}

// Find vertex data
NVVertexData* NVComplexMesh::FindVertexData(NVVERTNAME Name)
{
	tVertexDataMap::iterator itrVertex = m_VertexData.find(Name);
	if (itrVertex != m_VertexData.end())
		return itrVertex->second;
	return NULL;
}

bool NVComplexMesh::ClearVertexLocations()
{
	tVertexDataMap::iterator itrVertex = m_VertexData.begin();
	while (itrVertex != m_VertexData.end())
	{
		itrVertex->second->SetLocation(NVCOMPLEXMESH_NO_VERTEX);
		itrVertex++;
	}

	return true;
}

bool NVComplexMesh::Render(LPDIRECT3DDEVICE8 pDevice)
{
	tSectionList::const_iterator itrSections = m_Sections.begin();
	while (itrSections != m_Sections.end())
	{
		const NVComplexMeshSection& Attrib = *itrSections;

		NVMaterialResource* pMaterial = NVMaterialResource::GetMaterialResourcePtr(Attrib.m_Material);
		NVASSERT(pMaterial, "ERROR: No material");

		// Switch to each section's material.  And apply the section's renderstyle
		NVRenderStyleResource* pRenderStyle = NVRenderStyleResource::GetRenderStyleResourcePtr(Attrib.GetRenderStyle().GetPointer());
		NVASSERT(pRenderStyle, "ERROR: No renderstyle");

		for (DWORD dwPass = 0; dwPass < pRenderStyle->GetNumPasses(); dwPass++)
		{
			NVRenderStylePass* pPass = pRenderStyle->GetPass(dwPass);
			if (pPass)
			{
				pPass->ApplyRenderStyle(Attrib.GetMaterial());

				RenderSection(pDevice, itrSections);
				
				pPass->RestoreRenderStyle();
			}
		}
	
		itrSections++;
	}
	return true;
}

void NVComplexMesh::SetRenderStyle(NVResourceRef RenderStyle)
{
	tSectionList::iterator itrSections = m_Sections.begin();
	while (itrSections != m_Sections.end())
	{
		NVComplexMeshSection& Attrib = *itrSections;

		Attrib.SetRenderStyle(RenderStyle);
		
		itrSections++;
	}
	return;
}

bool NVComplexMesh::RenderSection(LPDIRECT3DDEVICE8 pDevice, tSectionList::const_iterator itrSections)
{

	// Can't render without VB's.
	if (m_IndexBuffers.empty() || !m_pVB)
	{
		NVASSERT(0, "IB Empty or no VB");
		return false;
	}

	const NVComplexMeshSection& Attrib = *itrSections;

	if (m_dwNumBones != 0)
	{
		LPD3DXBONECOMBINATION pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(m_pBoneCombinations->GetBufferPointer());
        D3DXMATRIX* pBoneTransforms = reinterpret_cast<D3DXMATRIX*>(m_pBoneTransforms->GetBufferPointer());


		for (DWORD i = 0; i < m_dwBonePaletteSize; ++i)
		{
			DWORD matid = pBoneComb[Attrib.m_dwAttribId].BoneId[i];
			if (matid != UINT_MAX)
			{
				D3DXMATRIX tempMat;
				D3DXMatrixMultiply(&tempMat, &pBoneTransforms[matid], m_pBoneMatrices[matid]);
				
				D3DXMatrixTranspose(&tempMat, &tempMat);
				NVSTATEMANAGER.SetVertexShaderConstant(i * 3, &tempMat, 3);
			}
		}
	}

	// Setup the stream and index buffers for the mesh
	// We don't Save/Restore this data, because it should always be set - there's no 'default' stream
	NVSTATEMANAGER.SetStreamSource(0, m_pVB, m_dwStride);

	if (Attrib.m_TriType == NVComplexMeshSection::TriangleList)
	{
		// Draw it.
		NVASSERT(0, "FIXME: Check counts and triangles/vertices drawn");
		NVSTATEMANAGER.DrawPrimitive(D3DPT_TRIANGLELIST, Attrib.m_dwIndexStart, Attrib.m_dwIndexCount);
		AddTrianglesDrawn(Attrib.m_dwIndexCount);
		AddVerticesDrawn(Attrib.m_dwIndexCount);
	}
	else
	{
		LONG lAttribIndexStart;
		LONG lAttribIndexCount;

		lAttribIndexStart = Attrib.m_dwIndexStart;
		lAttribIndexCount = Attrib.m_dwIndexCount;

		LONG lMaxEntries = (LONG)NV_MAX_INDICES_IN_BUFFER;
		LONG lThisCount;
		tIndexBufferArray::const_iterator itrIndices = m_IndexBuffers.begin();
		while (itrIndices != m_IndexBuffers.end())
		{
			// Can render in this section?
			if (lAttribIndexStart < lMaxEntries)
			{
				break;
			}
			lAttribIndexStart -= lMaxEntries;
			itrIndices++;
		}

		NVASSERT(lAttribIndexStart >= 0, "No attributes");

		while((itrIndices != m_IndexBuffers.end()) && (lAttribIndexCount > 0))
		{
			if ((lMaxEntries - lAttribIndexCount) < 0)
			{
				lThisCount = lMaxEntries;
			}
			else
			{
				lThisCount = lAttribIndexCount;
			}

			NVSTATEMANAGER.SetIndices(*itrIndices, 0);

			if (Attrib.m_TriType == NVComplexMeshSection::IndexedTriangleList)
			{
				// Draw it.
				NVSTATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, Attrib.m_dwVertexStart, Attrib.m_dwVertexCount, (DWORD)lAttribIndexStart, (DWORD)(lThisCount / 3));
				AddTrianglesDrawn(lThisCount / 3);
				AddVerticesDrawn(lThisCount);
			}
			else if (Attrib.m_TriType == NVComplexMeshSection::IndexedTriangleStrip)
			{
				// Draw it.
				NVSTATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, Attrib.m_dwVertexStart, Attrib.m_dwVertexCount, (DWORD)lAttribIndexStart, (DWORD)(lThisCount - 2));
				AddTrianglesDrawn(lThisCount);
				AddVerticesDrawn(lThisCount);
			}
			else
			{
				NVASSERT(0, "Invalid triangle type!");
			}

			lAttribIndexStart = 0;
			lAttribIndexCount -= lThisCount;

			itrIndices++;
		}
	}

	return true;
}

const char* NVComplexMesh::GetBoneName(DWORD i) const
{
	NVASSERT(m_pBoneNames->GetBufferSize() > i, "Invalid bone ID");
	char** pBoneNames = static_cast<char**>(m_pBoneNames->GetBufferPointer()); 
	return pBoneNames[i];
}

void NVComplexMesh::SetBoneMatrixPtr(DWORD i, const D3DXMATRIX* pMat)
{
	NVASSERT(m_dwNumBones > i, "Invalid bone ID");
	m_pBoneMatrices[i] = pMat;
}

}; // nv_objects

⌨️ 快捷键说明

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