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