📄 nvcomplexmesh.cpp
字号:
}
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_MaterialID = NVRESOURCEMANAGER.AddResource(pMaterial);
m_Passes[0]->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
tVec3Array* pPosition = NULL;
tVec3Array* pNormal = NULL;
tVec4Array* pDiffuse = NULL;
tVec4Array* pSpecular = NULL;
tVec2Array* pTexture[NV_MAX_TEXTURES];
for (i = 0; i < NV_MAX_TEXTURES; i++)
{
pTexture[i] = NULL;
}
NVComplexMeshVertexData* pData = NULL;
SetNumVertices(vbdesc.Size / dwStride);
// Create vertex data in the pass for the geometry we found in the mesh
if (vbdesc.FVF & D3DFVF_XYZ)
{
pData = AddVertexData("position", NVCOMPLEXMESH_FLOAT3);
if (pData)
pPosition = &pData->GetVec3Array();
}
// Normal
if (vbdesc.FVF & D3DFVF_NORMAL)
{
pData = AddVertexData("normal", NVCOMPLEXMESH_FLOAT3);
if (pData)
pNormal = &pData->GetVec3Array();
}
// Diffuse
if (vbdesc.FVF & D3DFVF_DIFFUSE)
{
pData = AddVertexData("diffuse", NVCOMPLEXMESH_FLOAT4);
if (pData)
pDiffuse = &pData->GetVec4Array();
}
// Specular
if (vbdesc.FVF & D3DFVF_SPECULAR)
{
pData = AddVertexData("specular", NVCOMPLEXMESH_FLOAT4);
if (pData)
pSpecular = &pData->GetVec4Array();
}
// Up to 8 texture coordinates
for (dwTexCount = 0; dwTexCount < dwTextures; dwTexCount++)
{
string strBuff;
strBuff.resize(2);
ultoa(dwTexCount, &strBuff[0], 2);
string texname = "texture" + strBuff;
texname = texname.substr(0, strlen(texname.c_str()));
pData = AddVertexData(texname, NVCOMPLEXMESH_FLOAT2);
if (pData)
pTexture[dwTexCount] = &pData->GetVec2Array();
}
for (i = 0; i < (vbdesc.Size / dwStride); i++)
{
BYTE* pVert = pVertex;
// Position
if (vbdesc.FVF & D3DFVF_XYZ)
{
if (pPosition)
(*pPosition)[i] = (*(D3DXVECTOR3*)pVert);
pVert += sizeof(D3DXVECTOR3);
}
// Normal
if (vbdesc.FVF & D3DFVF_NORMAL)
{
if (pNormal)
(*pNormal)[i] = (*(D3DXVECTOR3*)pVert);
pVert += sizeof(D3DXVECTOR3);
}
// Diffuse
if (vbdesc.FVF & D3DFVF_DIFFUSE)
{
if (pDiffuse)
(*pDiffuse)[i] = (*(D3DXVECTOR4*)pVert);
pVert += sizeof(D3DXVECTOR4);
}
// Specular
if (vbdesc.FVF & D3DFVF_SPECULAR)
{
if (pSpecular)
(*pSpecular)[i] = (*(D3DXVECTOR4*)pVert);
pVert += sizeof(D3DXVECTOR4);
}
// Up to 8 texture coordinates
for (dwTexCount = 0; dwTexCount < dwTextures; dwTexCount++)
{
if (pTexture[dwTexCount])
(*pTexture[dwTexCount])[i] = (*(D3DXVECTOR2*)pVert);
pVert += sizeof(D3DXVECTOR2);
}
pVertex += dwStride;
// Sanity check to confirm sizes
NVASSERT(pVert == pVertex, "Vertex size check wrong");
}
pVB->Unlock();
// Copy the index data
BYTE* pIndex;
hr = pIB->Lock(0, ibdesc.Size,(BYTE**)&pIndex, 0);
NVASSERT(ibdesc.Format == D3DFMT_INDEX16, "Index buffer should be INDEX16");
m_Indices.resize(ibdesc.Size / 2);
memcpy(&m_Indices[0], pIndex, ibdesc.Size);
pIB->Unlock();
SAFE_RELEASE(tempMesh);
SAFE_RELEASE(tempMeshOpt);
SAFE_RELEASE(pMaterials);
SAFE_RELEASE(pIB);
SAFE_RELEASE(pVB);
if (pAttributes)
HeapFree(GetProcessHeap(), 0, pAttributes);
return true;
}
bool NVComplexMesh::CreateFromMFile(LPDIRECT3DDEVICE8 pDevice, const char* fileName)
{
FILE* fp;
char line[256];
char* token;
DWORD dwIndex = 0;
DWORD dwNumVertices = 0;
NVComplexMeshVertexData* pData = NULL;
typedef std::map<DWORD, DWORD> tPositionIndexLookup;
tPositionIndexLookup PositionIndexLookup;
if((fp = fopen(fileName, "r")) == NULL)
return false;
Release();
m_Passes.push_back(new NVComplexMeshPass(this));
// Create vertex data in for the geometry we find in the mesh
pData = AddVertexData("position", NVCOMPLEXMESH_FLOAT3);
if (!pData)
return false;
tVec3Array& PositionData = pData->GetVec3Array();
fgets(line, 256, fp);
while(!feof(fp))
{
if(line[0] == '#')
{
//it's a comment
fgets(line, 256, fp);
continue;
}
else if(line[0] == 'V')
{
//it's a vertex
float x, y, z;
DWORD dwID;
//get Vertex
token = strtok(line, " ");
//get the number
token = strtok(NULL, " ");
dwID = atoi(token);
//get the vertex info
token = strtok(NULL, " ");
x = atof(token);
token = strtok(NULL, " ");
y = atof(token);
token = strtok(NULL, " ");
z = atof(token);
PositionData.push_back(D3DXVECTOR3(x, y, z));
PositionIndexLookup.insert(tPositionIndexLookup::value_type(dwID, dwIndex++) );
dwNumVertices++;
}
else if(line[0] == 'F')
{
DWORD Index[3];
//it's a face
//get Face
token = strtok(line, " ");
//get number
token = strtok(NULL, " ");
//get index data
token = strtok(NULL, " ");
Index[0] = atoi(token);
token = strtok(NULL, " ");
Index[1] = atoi(token);
token = strtok(NULL, " ");
Index[2] = atoi(token);
tPositionIndexLookup::iterator itrIndex[3];
itrIndex[0] = PositionIndexLookup.find(Index[0]);
itrIndex[1] = PositionIndexLookup.find(Index[1]);
itrIndex[2] = PositionIndexLookup.find(Index[2]);
// Some files may have faces, but no vertices to match them
if ((itrIndex[0] != PositionIndexLookup.end()) &&
(itrIndex[1] != PositionIndexLookup.end()) &&
(itrIndex[2] != PositionIndexLookup.end()))
{
// Add the indices
m_Indices.push_back(itrIndex[0]->second);
m_Indices.push_back(itrIndex[1]->second);
m_Indices.push_back(itrIndex[2]->second);
}
}
else if(line[0] == 'E')
{
//edge, do nothing
}
else
{
}
fgets(line, 256, fp);
}
fclose(fp);
if (PositionData.empty() || m_Indices.empty())
return false;
SetNumVertices(dwNumVertices);
// Create named constants for this mesh
NVMaterialResource* pMaterial = new NVMaterialResource;
pMaterial->AddConstant("diffuse", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
pMaterial->AddConstant("ambient", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f));
pMaterial->AddConstant("specular", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f));
// No sections in a .m file
NVComplexMeshSection Attrib;
Attrib.m_dwAttribId = 0;
Attrib.m_dwIndexStart = 0;
Attrib.m_dwIndexCount = m_Indices.size();
Attrib.m_dwVertexStart = 0;
Attrib.m_dwVertexCount = dwNumVertices;
Attrib.m_MaterialID = NVRESOURCEMANAGER.AddResource(pMaterial);
m_Passes[0]->m_Sections.push_back(Attrib);
return true;
}
bool NVComplexMesh::CreateFromSphere(float fRadius, WORD wNumRings, WORD wNumSections, const D3DXVECTOR3& PositionScaling, const D3DXVECTOR2& TextureScaling)
{
float x, y, z, v, rsintheta; // Temporary variables
WORD i, j, n, m; // counters
D3DXVECTOR3 vPoint;
NVComplexMeshVertexData* pVertexData = NULL;
NVComplexMeshVertexData* pTextureData = NULL;
Release();
m_Passes.push_back(new NVComplexMeshPass(this));
//Generate space for the required triangles and vertices.
WORD wNumTriangles = (wNumRings + 1) * wNumSections * 2;
DWORD dwNumIndices = wNumTriangles*3;
DWORD dwNumVertices = (wNumRings + 1) * wNumSections + 2;
SetNumVertices(dwNumVertices);
// Create vertex data for the geometry we find in the mesh
pVertexData = AddVertexData("position", NVCOMPLEXMESH_FLOAT3);
if (!pVertexData)
return false;
pTextureData = AddVertexData("texture0", NVCOMPLEXMESH_FLOAT2);
if (!pTextureData)
return false;
tVec3Array& PositionData = pVertexData->GetVec3Array();
tVec2Array& TextureData = pTextureData->GetVec2Array();
m_Indices.resize(dwNumIndices);
// Generate vertices at the top and bottom points.
D3DXVECTOR3 vTopPoint = D3DXVECTOR3( 0.0f, +PositionScaling.y*fRadius, 0.0f);
D3DXVECTOR3 vBotPoint = D3DXVECTOR3( 0.0f, -PositionScaling.y*fRadius, 0.0f);
D3DXVECTOR3 vNormal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
PositionData[0] = D3DXVECTOR3(vTopPoint.x, vTopPoint.y, vTopPoint.z);
TextureData[0] = D3DXVECTOR2(0.0f, 0.0f);
PositionData[dwNumVertices-1] = D3DXVECTOR3(vBotPoint.x, vBotPoint.y, vBotPoint.z);
TextureData[dwNumVertices-1] = D3DXVECTOR2(0.0f, 0.0f);
// Generate vertex points for rings
float dtheta = (float)(D3DX_PI / (wNumRings + 2)); //Angle between each ring
float dphi = (float)(2*D3DX_PI / (wNumSections)); //Angle between each section
float theta = dtheta;
n = 1; //vertex being generated, begins at 1 to skip top point
for( i = 0; i < (wNumRings+1); i++ )
{
y = fRadius * (float)cos(theta); // y is the same for each ring
v = theta / D3DX_PI; // v is the same for each ring
rsintheta = fRadius * (float)sin(theta);
float phi = 0.0f;
for( j = 0; j < wNumSections; j++ )
{
x = rsintheta * (float)sin(phi);
z = rsintheta * (float)cos(phi);
float u = 1.0f - (float)(phi / (2 * D3DX_PI) );
NVASSERT(u <= 1.001f, "Invalid texture coord");
NVASSERT(u >= 0.0f, "Invalid texture coord");
vPoint = D3DXVECTOR3(PositionScaling.x * x, PositionScaling.y * y, PositionScaling.z * z );
PositionData[n] = D3DXVECTOR3(vPoint.x, vPoint.y, vPoint.z);
TextureData[n] = D3DXVECTOR2(u * TextureScaling.x, v * TextureScaling.y);
phi += dphi;
++n;
}
theta += dtheta;
}
// Generate triangles for top and bottom caps.
for( i = 0; i < wNumSections; i++ )
{
m_Indices[3*i+0] = 0;
m_Indices[3*i+1] = i + 1;
m_Indices[3*i+2] = 1 + ((i + 1) % wNumSections);
m_Indices[3*(wNumTriangles - wNumSections + i)+0] = (WORD)( dwNumVertices - 1 );
m_Indices[3*(wNumTriangles - wNumSections + i)+1] = (WORD)( dwNumVertices - 2 - i );
m_Indices[3*(wNumTriangles - wNumSections + i)+2] = (WORD)( dwNumVertices - 2 -
((1 + i) % wNumSections) );
}
// Generate triangles for the rings
m = 1; // first vertex in current ring,begins at 1 to skip top point
n = wNumSections; // triangle being generated, skip the top cap
for( i = 0; i < wNumRings; i++ )
{
for( j = 0; j < (wNumSections); j++ )
{
m_Indices[3*n+0] = m + j;
m_Indices[3*n+1] = m + wNumSections + j;
m_Indices[3*n+2] = m + wNumSections + ((j + 1) % wNumSections);
m_Indices[3*(n+1)+0] = m_Indices[3*n+0];
m_Indices[3*(n+1)+1] = m_Indices[3*n+2];
m_Indices[3*(n+1)+2] = m + ((j + 1) % wNumSections);
n += 2;
}
m += wNumSections;
}
// Create named constants for this mesh
NVMaterialResource* pMaterial = new NVMaterialResource;
pMaterial->AddConstant("diffuse", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
pMaterial->AddConstant("ambient", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f));
pMaterial->AddConstant("specular", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f));
// No sections in a .m file
NVComplexMeshSection Attrib;
Attrib.m_dwAttribId = 0;
Attrib.m_dwIndexStart = 0;
Attrib.m_dwIndexCount = m_Indices.size();
Attrib.m_dwVertexStart = 0;
Attrib.m_dwVertexCount = dwNumVertices;
Attrib.m_MaterialID = NVRESOURCEMANAGER.AddResource(pMaterial);
m_Passes[0]->m_Sections.push_back(Attrib);
return true;
}
bool NVComplexMesh::Render(LPDIRECT3DDEVICE8 pDevice)
{
// Draw each pass.
DWORD dwPass = 0;
while (dwPass < m_Passes.size())
{
NVComplexMeshPass* pPass = m_Passes[dwPass];
if (pPass)
{
pPass->Render(pDevice);
}
dwPass++;
}
return true;
}
bool NVComplexMesh::Translate(const D3DXVECTOR3& Translation)
{
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())
{
Position[i] += Translation;
i++;
}
return true;
}
bool NVComplexMesh::Scale(float fScale)
{
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())
{
Position[i] *= fScale;
i++;
}
return true;
}
bool NVComplexMesh::Transform(const D3DXMATRIX& Transform)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -