📄 nvcomplexmesh.cpp
字号:
BoneWeights[dwQuadCount][i].y = fweight;
}
else if ((dwWeightCount & 0x3) == 2)
{
BoneWeights[dwQuadCount][i].z = fweight;
}
else if ((dwWeightCount & 0x3) == 3)
{
BoneWeights[dwQuadCount][i].w = fweight;
dwQuadCount++;
if (!bLastWeight)
BoneWeights[dwQuadCount][i] = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
}
if (bLastWeight)
break;
dwWeightCount++;
}
// Add the indices. We retrieve the list of dwords and pack them
// into vec4's.
dwQuadCount = 0;
dwIndexCount = 0;
// Reset to 0
BoneIndices[dwQuadCount][i] = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
do
{
float fIndex;
DWORD dwIndexQuad = (*(DWORD*)pVert);
if ((dwIndexCount & 0x3) == 0)
{
fIndex = (float)(dwIndexQuad & 0x000000FF) * 3.f;
BoneIndices[dwQuadCount][i].x = fIndex;
}
else if ((dwIndexCount & 0x3) == 1)
{
fIndex = (float)((dwIndexQuad & 0x0000FF00) >> 8) * 3.f;
BoneIndices[dwQuadCount][i].y = fIndex;
}
else if ((dwIndexCount & 0x3) == 2)
{
fIndex = (float)((dwIndexQuad & 0x00FF0000) >> 16) * 3.f;
BoneIndices[dwQuadCount][i].z = fIndex;
}
else if ((dwIndexCount & 0x3) == 3)
{
fIndex = (float)((dwIndexQuad & 0xFF000000) >> 24) * 3.f;
BoneIndices[dwQuadCount][i].w = fIndex;
if ((dwIndexCount + 1) < m_dwNumWeights)
{
dwQuadCount++;
pVert += sizeof(DWORD);
BoneIndices[dwQuadCount][i] = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
}
}
dwIndexCount++;
} while (dwIndexCount < m_dwNumWeights);
// Make sure we step over the remaining indices.
pVert += sizeof(DWORD);
}
// 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 ((Textures.size() > dwTexCount) && Textures[dwTexCount])
Textures[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();
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;
NVVertexData* pData = NULL;
typedef std::map<DWORD, DWORD> tPositionIndexLookup;
tPositionIndexLookup PositionIndexLookup;
if((fp = fopen(fileName, "r")) == NULL)
return false;
Release();
// Create vertex data in for the geometry we find in the mesh
tNVData_float3* pVec3Data = static_cast<tNVData_float3*>(AddVertexData(NVVERT_POSITION, D3DDATATYPE_FLOAT3));
if (!pVec3Data)
return false;
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);
pVec3Data->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 (pVec3Data->empty() || m_Indices.empty())
return false;
SetNumVertices(dwNumVertices);
// Create named constants for this mesh
NVMaterialResource* pMaterial = new NVMaterialResource;
pMaterial->AddValue("diffuse", NVValue(NVV_VECTOR4, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f)));
pMaterial->AddValue("ambient", NVValue(NVV_VECTOR4, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f)));
pMaterial->AddValue("specular", NVValue(NVV_VECTOR4, 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_Material = NVRESOURCEMANAGER.AddResource(pMaterial);
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;
NVVertexData* pVertexData = NULL;
NVVertexData* pTextureData = NULL;
Release();
//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(NVVERT_POSITION, D3DDATATYPE_FLOAT3);
if (!pVertexData)
return false;
pTextureData = AddVertexData(NVVERT_TEXTURE0, D3DDATATYPE_FLOAT2);
if (!pTextureData)
return false;
D3DXVECTOR3* pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pVertexData);
D3DXVECTOR2* pTexture = GetDataPointer<D3DXVECTOR2, D3DDATATYPE_FLOAT2>(pTextureData);
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 );
pPosition[0] = D3DXVECTOR3(vTopPoint.x, vTopPoint.y, vTopPoint.z);
pTexture[0] = D3DXVECTOR2(0.0f, 0.0f);
pPosition[dwNumVertices-1] = D3DXVECTOR3(vBotPoint.x, vBotPoint.y, vBotPoint.z);
pTexture[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 );
pPosition[n] = D3DXVECTOR3(vPoint.x, vPoint.y, vPoint.z);
pTexture[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->AddValue("diffuse", NVValue(NVV_VECTOR4, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f)));
pMaterial->AddValue("ambient", NVValue(NVV_VECTOR4, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f)));
pMaterial->AddValue("specular", NVValue(NVV_VECTOR4, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f)));
pMaterial->AddValue("power", NVValue(NVV_VECTOR4, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 30.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_Material = NVRESOURCEMANAGER.AddResource(pMaterial);
m_Sections.push_back(Attrib);
return true;
}
bool NVComplexMesh::Translate(const D3DXVECTOR3& Translation)
{
DWORD i = 0;
NVVertexData* pPositionData = FindVertexData(NVVERT_POSITION);
if (!pPositionData || (pPositionData->GetDataType() != D3DDATATYPE_FLOAT3))
{
NVASSERT(0, "No position data in mesh, or wrong format");
return false;
}
D3DXVECTOR3* pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pPositionData);
while (i < pPositionData->size())
{
pPosition[i] += Translation;
i++;
}
return true;
}
bool NVComplexMesh::Scale(float fScale)
{
DWORD i = 0;
NVVertexData* pPositionData = FindVertexData(NVVERT_POSITION);
if (!pPositionData || (pPositionData->GetDataType() != D3DDATATYPE_FLOAT3))
{
NVASSERT(0, "No position data in mesh, or wrong format");
return false;
}
D3DXVECTOR3* pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pPositionData);
while (i < pPositionData->size())
{
pPosition[i] *= fScale;
i++;
}
return true;
}
bool NVComplexMesh::Transform(const D3DXMATRIX& Transform)
{
DWORD i = 0;
NVVertexData* pPositionData = FindVertexData(NVVERT_POSITION);
if (!pPositionData || (pPositionData->GetDataType() != D3DDATATYPE_FLOAT3))
{
NVASSERT(0, "No position data in mesh, or wrong format");
return false;
}
D3DXVECTOR3* pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pPositionData);
while (i < pPositionData->size())
{
D3DXVec3TransformCoord(&pPosition[i], &pPosition[i], &Transform);
i++;
}
return true;
}
bool NVComplexMesh::ComputeBounds(NVAABounds* pBounds)
{
pBounds->m_vecCenter = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
pBounds->m_fRadius = 0.0f;
pBounds->m_vecMinExtents = D3DXVECTOR3(FLT_MAX, FLT_MAX, FLT_MAX);
pBounds->m_vecMaxExtents = D3DXVECTOR3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
DWORD i = 0;
NVVertexData* pPositionData = FindVertexData(NVVERT_POSITION);
if (!pPositionData || (pPositionData->GetDataType() != D3DDATATYPE_FLOAT3))
{
NVASSERT(0, "No position data in mesh or wrong format");
return false;
}
D3DXVECTOR3* pPosition = GetDataPointer<D3DXVECTOR3, D3DDATATYPE_FLOAT3>(pPositionData);
while (i < pPositionData->size())
{
float x = pPosition[i].x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -