📄 nvcomplexmesh.cpp
字号:
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 + -