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

📄 nvcomplexmesh.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}

		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 + -