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

📄 nvcomplexmesh.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	DWORD i = 0;
	NVComplexMeshVertexData* pPositionData = FindVertexData("position");
	if (!pPositionData || (pPositionData->GetDataType() != NVCOMPLEXMESH_FLOAT3))
	{
		NVASSERT(0, "No position data in mesh, or wrong format");
		return false;
	}

	tVec3Array& Position = pPositionData->GetVec3Array();
	while (i < Position.size())
	{
		D3DXVec3TransformCoord(&Position[i], &Position[i], &Transform);
		i++;
	}
	
	return true;
}
bool NVComplexMesh::ComputeBounds(NVComplexMeshBounds& Bounds)
{
	Bounds.m_vecCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	Bounds.m_fRadius = 0.0f;
	Bounds.m_vecMinExtents = D3DXVECTOR3(FLT_MAX, FLT_MAX, FLT_MAX);
	Bounds.m_vecMaxExtents = D3DXVECTOR3(-FLT_MAX, -FLT_MAX, -FLT_MAX);

	DWORD i = 0;
	NVComplexMeshVertexData* pPositionData = FindVertexData("position");
	if (!pPositionData || (pPositionData->GetDataType() != NVCOMPLEXMESH_FLOAT3))
	{
		NVASSERT(0, "No position data in mesh or wrong format");
		return false;
	}

	tVec3Array& Position = pPositionData->GetVec3Array();

	while (i < Position.size())
	{
		float x = Position[i].x;
		float y = Position[i].y;
		float z = Position[i].z;
		
		if (Bounds.m_vecMaxExtents.x < x)
			Bounds.m_vecMaxExtents.x = x;

		if (Bounds.m_vecMaxExtents.y < y)
			Bounds.m_vecMaxExtents.y = y;

		if (Bounds.m_vecMaxExtents.z < z)
			Bounds.m_vecMaxExtents.z = z;

		if (Bounds.m_vecMinExtents.x > x)
			Bounds.m_vecMinExtents.x = x;

		if (Bounds.m_vecMinExtents.y > y)
			Bounds.m_vecMinExtents.y = y;

		if (Bounds.m_vecMinExtents.z > z)
			Bounds.m_vecMinExtents.z = z;

		
		i++;
	}

	Bounds.m_vecCenter = (Bounds.m_vecMinExtents + Bounds.m_vecMaxExtents) / 2.0f;

	// The bounding radius will either be from the center to the min or the center to the max
	// The max & min distance should be about the same, but I have seen differences, so we will select
	//  the max of the two anyway to ensure we get it right
	D3DXVECTOR3 maxDirection(Bounds.m_vecMaxExtents - Bounds.m_vecCenter);
	D3DXVECTOR3 minDirection(Bounds.m_vecMinExtents - Bounds.m_vecCenter);

	float fRadiusSquared1 = D3DXVec3Dot(&maxDirection, &maxDirection);
	float fRadiusSquared2 = D3DXVec3Dot(&minDirection, &minDirection);
	Bounds.m_fRadius = (fRadiusSquared1 > fRadiusSquared2) ? sqrtf(fRadiusSquared1) : sqrtf(fRadiusSquared2);

	return true;
}

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

	pVertexData = FindVertexData("normal");
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		dwFVF |= D3DFVF_NORMAL;
	}

	pVertexData = FindVertexData("diffuse");
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		dwFVF |= D3DFVF_DIFFUSE;
	}

	pVertexData = FindVertexData("specular");
	if (pVertexData)
	{
		pVertexData->SetLocation(dwLocation++);
		dwFVF |= D3DFVF_SPECULAR;
	}

	for (DWORD i = 0; i < NV_MAX_TEXTURES; i++)
	{
		string strBuff;
		strBuff.resize(2);
		ultoa(i, &strBuff[0], 2);
		string texname = "texture" + strBuff;
		texname = texname.substr(0, strlen(texname.c_str()));

		pVertexData = FindVertexData(texname);
		if (pVertexData)
		{
			pVertexData->SetLocation(dwLocation++);
			dwFVF &= ~D3DFVF_TEXCOUNT_MASK;
			dwFVF |= ((i + 1) << D3DFVF_TEXCOUNT_SHIFT);
		}
	}
	

	// Get a list of sections.  We assume we only have pass1 for now
	tSectionList& Sections = GetPass(0)->GetSections();
	tSectionList::iterator itrSections = Sections.begin();

	// Walk all the model sections in this pass
	while (itrSections != Sections.end())
	{
		D3DMATERIAL8 D3DMaterial;
		ZeroMemory(&D3DMaterial, sizeof(D3DMATERIAL8));

		// Set the constants and vertex shaders in this section
		NVMaterialResource* pMaterial = static_cast<NVMaterialResource*>(NVRESOURCEMANAGER.FindResource((*itrSections).GetMaterialID()));
		if (pMaterial)
		{
			NVConstant* pConstant;

			// Tell the mesh where to place it's constants
			pConstant = pMaterial->FindConstant("diffuse");
			if (pConstant)
			{
				D3DMaterial.Diffuse.r = pConstant->GetConstant().x;
				D3DMaterial.Diffuse.g = pConstant->GetConstant().y;
				D3DMaterial.Diffuse.b = pConstant->GetConstant().z;
				D3DMaterial.Diffuse.a = pConstant->GetConstant().w;
			}

			pConstant = pMaterial->FindConstant("ambient");
			if (pConstant)
			{
				D3DMaterial.Ambient.r = pConstant->GetConstant().x;
				D3DMaterial.Ambient.g = pConstant->GetConstant().y;
				D3DMaterial.Ambient.b = pConstant->GetConstant().z;
				D3DMaterial.Ambient.a = pConstant->GetConstant().w;
			}

			pConstant = pMaterial->FindConstant("specular");
			if (pConstant)
			{
				D3DMaterial.Specular.r = pConstant->GetConstant().x;
				D3DMaterial.Specular.g = pConstant->GetConstant().y;
				D3DMaterial.Specular.b = pConstant->GetConstant().z;
				D3DMaterial.Specular.a = pConstant->GetConstant().w;

				pMaterial->AddRenderState(D3DRS_SPECULARENABLE, TRUE);
			}
			else
			{
				pMaterial->AddRenderState(D3DRS_SPECULARENABLE, FALSE);
			}
			
			pConstant = pMaterial->FindConstant("power");
			if (pConstant)
			{
				D3DMaterial.Power = pConstant->GetConstant().w;
			}
						
		    pMaterial->AddD3DMaterial(&D3DMaterial);

		    pMaterial->AddRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
			pMaterial->AddTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
			pMaterial->AddTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
			pMaterial->AddTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
			pMaterial->AddVertexShader(dwFVF);

			if ((pMaterial->GetTextureID(0) != NVINVALID_RESOURCEID) &&
				(NVTextureResource::GetTexture(pMaterial->GetTextureID(0)) != NULL))
			{
				pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);	
			}
			else
			{
				pMaterial->AddTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);	
			}
			pMaterial->AddTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
		}
		itrSections++;
	}

	return true;
}

class DataSorter
{
public:
	bool operator()(const NVComplexMeshVertexData* lhs, const NVComplexMeshVertexData* 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<NVComplexMeshVertexData*> SortedDataList;
	vector<NVComplexMeshVertexData*>::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())
	{
		NVComplexMeshVertexData* pVertexData = &itrVertexData->second;
		if (pVertexData->GetLocation() != NVCOMPLEXMESH_NO_VERTEX)
		{
			SortedDataList.push_back(pVertexData);
			switch(pVertexData->GetDataType())
			{
				case NVCOMPLEXMESH_FLOAT4:
					m_dwStride += sizeof(D3DXVECTOR4);
					break;
				case NVCOMPLEXMESH_FLOAT3:
					m_dwStride += sizeof(D3DXVECTOR3);
					break;
				case NVCOMPLEXMESH_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 = 0;
	switch(SortedDataList.front()->GetDataType())
	{
		case NVCOMPLEXMESH_FLOAT4:
			dwArraySize = ((SortedDataList.front())->GetVec4Array()).size();
			break;
		case NVCOMPLEXMESH_FLOAT3:
			dwArraySize = ((SortedDataList.front())->GetVec3Array()).size();
			break;
		case NVCOMPLEXMESH_FLOAT2:
			dwArraySize = ((SortedDataList.front())->GetVec2Array()).size();
			break;
		default:
			NVASSERT(0, "Unknown vertex data format");
			break;
	}

	// 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())
		{
			NVComplexMeshVertexData* pWriteData = *itrDataList;
			
			switch(pWriteData->GetDataType())
			{
				case NVCOMPLEXMESH_FLOAT4:
					NVASSERT(pWriteData->GetVec4Array().size() == dwArraySize, "Array size mismatch");
					*(D3DXVECTOR4*)pDest = pWriteData->GetVec4Array()[i];
					pDest += sizeof(D3DXVECTOR4);
					break;
				case NVCOMPLEXMESH_FLOAT3:
					NVASSERT(pWriteData->GetVec3Array().size() == dwArraySize, "Array size mismatch");
					*(D3DXVECTOR3*)pDest = pWriteData->GetVec3Array()[i];
					pDest += sizeof(D3DXVECTOR3);
					break;
				case NVCOMPLEXMESH_FLOAT2:
					NVASSERT(pWriteData->GetVec2Array().size() == dwArraySize, "Array size mismatch");
					*(D3DXVECTOR2*)pDest = pWriteData->GetVec2Array()[i];
					pDest += sizeof(D3DXVECTOR2);
					break;
			}
			itrDataList++;
		}
	}
	m_pVB->Unlock();
	

	return true;
}

NVComplexMeshVertexData* NVComplexMesh::AddVertexData(const std::string& strName, eNVComplexMeshVertexDataType DataType, DWORD dwLocation)
{
	NVComplexMeshVertexData* pData = FindVertexData(strName);
	if (pData)
		return pData;

	std::pair<tVertexDataMap::iterator, bool> Ret = m_VertexData.insert(tVertexDataMap::value_type(strName, NVComplexMeshVertexData(DataType, dwLocation)));
	if (Ret.second == true)
	{
		pData = &((Ret.first)->second);

		// All streams must be the same length
		switch(pData->GetDataType())
		{
			case NVCOMPLEXMESH_FLOAT4:
				pData->GetVec4Array().resize(m_dwNumVertices);
				break;
			case NVCOMPLEXMESH_FLOAT3:
				pData->GetVec3Array().resize(m_dwNumVertices);
				break;
			case NVCOMPLEXMESH_FLOAT2:
				pData->GetVec2Array().resize(m_dwNumVertices);
				break;
		}

		return pData;
	}

	return NULL;
}

// Find vertex data
NVComplexMeshVertexData* NVComplexMesh::FindVertexData(const std::string& strName)
{
	tVertexDataMap::iterator itrVertex = m_VertexData.find(strName);
	if (itrVertex != m_VertexData.end())
		return &itrVertex->second;
	return NULL;
}

NVComplexMeshPass* NVComplexMesh::DuplicatePass(DWORD dwSource, DWORD dwDest)
{
	if (m_Passes.size() <= dwSource)
		return false;

	if (m_Passes.size() <= dwDest)
	{
		m_Passes.resize(dwDest + 1);
	}

	if (m_Passes[dwDest] != NULL)
	{
		*m_Passes[dwDest] = *m_Passes[dwSource];
	}
	else
	{
		// Allocate new pass and copy it
		m_Passes[dwDest] = new NVComplexMeshPass(*m_Passes[dwSource]);
	}

	typedef map<NVResourceID, NVResourceID> tMapMaterialToNewMaterial;
	tMapMaterialToNewMaterial mapMat;
	
	tSectionList& Sections = m_Passes[dwDest]->GetSections();
	tSectionList::iterator itrSections = Sections.begin();

	// Walk all the model sections in this pass
	while (itrSections != Sections.end())
	{
		NVResourceID MaterialID = (*itrSections).GetMaterialID();
		// Set the constants and vertex shaders in this section
		if (MaterialID != NVINVALID_RESOURCEID)
		{
			// Find this material in our mapping
			tMapMaterialToNewMaterial::iterator itrMaterials = mapMat.find(MaterialID);

			// If there, then simply remap the sections material to the new material
			if (itrMaterials != mapMat.end())
			{
				(*itrSections).SetMaterialID(itrMaterials->second);
			}
			// Otherwise create a new material, add it to the map, and map the section to it.
			else
			{
				NVMaterialResource* pMaterialNew = new NVMaterialResource(*static_cast<NVMaterialResource*>(NVRESOURCEMANAGER.FindResource(MaterialID)));
				NVResourceID NewMaterialID = NVRESOURCEMANAGER.AddResource(pMaterialNew);
				mapMat[MaterialID] = NewMaterialID;
				(*itrSections).SetMaterialID(NewMaterialID);
			}
		}
		itrSections++;
	}
	return m_Passes[dwDest];
}

}; // nv_objects

⌨️ 快捷键说明

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