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

📄 3dsfile.cpp

📁 VC++ DEMO, used for the beginners and the amour
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	INT numb_faces = ReadInt();
	Mesh.m_vFaces.resize(numb_faces);
	for (INT nNum=0;nNum<numb_faces;nNum++)
	{
		Mesh.m_vFaces[nNum].m_usIndices[0] = ReadInt();
		Mesh.m_vFaces[nNum].m_usIndices[1] = ReadInt();
		Mesh.m_vFaces[nNum].m_usIndices[2] = ReadInt();
		Mesh.m_vFaces[nNum].m_usInfo = ReadInt();
		teller += 8L;
	}

	while ( bEnd == FALSE )
	{
		UINT temp_int = ReadInt();
		
		switch( temp_int )
		{
		case TRI_FACEMATL:
			{
				_3DSUseMat Mat;
				teller += ReadMeshUseMatChunk(Mat);
				Mesh.m_vUseMaterials.push_back(Mat);
			}
			break;		
		case TRI_SMOOTH:	
			teller += ReadUnknownChunk(); break;
		}

		if ( teller == temp_pointer )
			bEnd = TRUE;
	}

	ChangeChunkPointer(current_pointer+temp_pointer);
	return (temp_pointer);
}

DWORD _3DS::ReadMeshUseMatChunk(_3DSUseMat &Mat)
{
	DWORD current_pointer = 0;
	DWORD temp_pointer = 0;
	DWORD teller = 8L;// id:2 + pointer:4 + number:2
	UINT face_indices = 0;
	
	current_pointer = GetChunkPointer();
	temp_pointer = ReadChunkPointer();
	
	teller += ReadName(Mat.m_strName,256);
	face_indices = ReadInt();
	Mat.m_vFaceIndices.resize(face_indices);
	for( UINT nNum = 0; nNum < Mat.m_vFaceIndices.size(); ++nNum)
	{
		Mat.m_vFaceIndices[nNum] = ReadInt();
		teller += 2L;
	}
	
	ChangeChunkPointer(current_pointer+temp_pointer);
	return (temp_pointer);
}

DWORD _3DS::ReadMeshTexCoordChunk(_3DSTriMesh &Mesh)
{
	DWORD current_pointer = 0;
	DWORD temp_pointer = 0;
	DWORD teller = 8L;// id:2 + pointer:4 + number:2
	
	current_pointer = GetChunkPointer();
	temp_pointer = ReadChunkPointer();

	Mesh.m_vTexCoords.resize(ReadInt());
	for( UINT nNum = 0; nNum < Mesh.m_vTexCoords.size(); ++nNum)
	{
		Mesh.m_vTexCoords[nNum].u = ReadFloat();
		Mesh.m_vTexCoords[nNum].v = ReadFloat();
		teller += 8L;
	}

	ChangeChunkPointer(current_pointer+temp_pointer);
	return (temp_pointer);
}

VOID _3DS::DrawModel(LPDIRECT3DVERTEXBUFFER8 vb)
{
	INT numOfModel = 0;
	INT numOfObject = 0;
	INT numOfMesh = 0;
	INT numOfUseMat = 0;
	INT numOfFace = 0;
	
	BYTE bHasTex = TRUE;
	
	for (numOfMesh = 0; numOfMesh < m_3DSFile.m_vModels.size(); ++numOfMesh)
	{
		_3DSModel & Model = m_3DSFile.m_vModels[numOfMesh];
		for ( numOfObject = 0; numOfObject < Model.m_vObjects.size(); ++numOfObject)
		{
			_3DSObject & Object = Model.m_vObjects[numOfObject];
			for ( numOfMesh = 0; numOfMesh < Object.m_vTriMeshs.size(); ++numOfMesh)
			{
				_3DSTriMesh & Mesh = Object.m_vTriMeshs[numOfMesh];
				if ( Mesh.m_vTexCoords.size() == 0 ) bHasTex = FALSE;
				for ( numOfUseMat = 0; numOfUseMat< Mesh.m_vUseMaterials.size();++numOfUseMat)
				{
					_3DSUseMat & UseMat = Mesh.m_vUseMaterials[numOfUseMat];
					if ( (INT)UseMat.m_usMatIdx < 0 )
					{
						if ( UseMat.m_vFaceIndices.size() < 1 )
							continue;
						D3DMATERIAL8 mat = {{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f}};
						m_pD3DDevice->SetMaterial(&mat);
						m_pD3DDevice->SetTexture(0,NULL);
					}
					else
					{
						m_pD3DDevice->SetMaterial(&Model.m_vUseMaterials[UseMat.m_usMatIdx]);
						m_pD3DDevice->SetTexture(0,Model.m_vTextures[UseMat.m_usMatIdx]);
					}

					m_pD3DDevice->SetStreamSource(0, vb, sizeof(D3DVERTEX));
					m_pD3DDevice->SetVertexShader(D3DVERTEX::D3DFVF_D3DVERTEX);
					
					D3DVERTEX *Ptr;
					if (FAILED(vb->Lock(0, 0, (BYTE **)&Ptr, 0)))
						return;
					LONG FLUSH = 0;
					for (numOfFace = 0; numOfFace < UseMat.m_vFaceIndices.size(); ++numOfFace)
					{
						_3DSFace &Face = Mesh.m_vFaces[UseMat.m_vFaceIndices[numOfFace]];
						
						for (INT iVert = 0; iVert < 3; iVert++)
						{
							_3DSVert & v = Mesh.m_vVertices[Face.m_usIndices[iVert]];
							if ( bHasTex == TRUE )
							{
								_3DSTexCoord & tex = Mesh.m_vTexCoords[Face.m_usIndices[iVert]];
								Ptr[0] = D3DVERTEX(D3DXVECTOR3(v.vPos.x,v.vPos.y,v.vPos.z),
									D3DXVECTOR3(v.vNormal.x,v.vNormal.y,v.vNormal.z),
									tex.u,tex.v);
							}
							else
							{
								Ptr[0] = D3DVERTEX(D3DXVECTOR3(v.vPos.x,v.vPos.y,v.vPos.z),
									D3DXVECTOR3(v.vNormal.x,v.vNormal.y,v.vNormal.z),
									0,0);
							}
							Ptr++;
						}
						FLUSH++;
						
						if ( FLUSH >= MAX_DRAW_FACES )
						{
							vb->Unlock();
							m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, FLUSH);
							
							if (FAILED(vb->Lock(0, 0, (BYTE **)&Ptr, 0)))
								return;
							FLUSH = 0;
						}
					}
					vb->Unlock();
					m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, FLUSH);
				}
			}	
		}
	}
}

VOID _3DS::Parse3DSFile()
{
	INT numOfModel = 0;
	INT numOfObject = 0;
	INT numOfMaterial = 0;
	INT numOfUseMat = 0;
	INT numOfTriMesh = 0;
	INT numOfFace = 0;
	
	TCHAR strPath[MAX_PATH] = {0};
	
	for ( numOfModel = 0; numOfModel < m_3DSFile.m_vModels.size(); ++numOfModel)
	{
		_3DSModel & Model = m_3DSFile.m_vModels[numOfModel];
		
		if ( Model.m_vMaterials.size() == 0 )
		{
			_3DSMaterial DefaultMaterial;
			_tcscpy(DefaultMaterial.m_strName,"%NoName%");
			Model.m_vMaterials.push_back(DefaultMaterial);
			Model.m_vUseMaterials.resize(1);
			Model.m_vTextures.resize(1);
		}
		else
		{
			Model.m_vUseMaterials.resize(Model.m_vMaterials.size());
			Model.m_vTextures.resize(Model.m_vMaterials.size());
		}
		
		for ( numOfMaterial = 0; numOfMaterial < Model.m_vMaterials.size();++numOfMaterial)
		{
			_3DSMaterial & Material = Model.m_vMaterials[numOfMaterial];
			wsprintf(strPath,"%s%s",m_strFilePath,Model.m_vMaterials[numOfMaterial].m_strDiffuseTexture);
			
			if ( FAILED(D3DXCreateTextureFromFile(m_pD3DDevice, strPath, &Model.m_vTextures[numOfMaterial])))
				Model.m_vTextures[numOfMaterial] = NULL;
			
			Model.m_vUseMaterials[numOfMaterial].Diffuse.r = Material.m_fDiffuseclr.r;
			Model.m_vUseMaterials[numOfMaterial].Diffuse.g = Material.m_fDiffuseclr.g;
			Model.m_vUseMaterials[numOfMaterial].Diffuse.b = Material.m_fDiffuseclr.b;
			Model.m_vUseMaterials[numOfMaterial].Diffuse.a = Material.m_fTransparency;
			
			Model.m_vUseMaterials[numOfMaterial].Ambient.r = Material.m_fAmbientclr.r;
			Model.m_vUseMaterials[numOfMaterial].Ambient.g = Material.m_fAmbientclr.g;
			Model.m_vUseMaterials[numOfMaterial].Ambient.b = Material.m_fAmbientclr.b;
			Model.m_vUseMaterials[numOfMaterial].Ambient.a = 1.0f;
			
			Model.m_vUseMaterials[numOfMaterial].Specular.r = Material.m_fSpecularclr.r;
			Model.m_vUseMaterials[numOfMaterial].Specular.g = Material.m_fSpecularclr.g;
			Model.m_vUseMaterials[numOfMaterial].Specular.b = Material.m_fSpecularclr.b;
			Model.m_vUseMaterials[numOfMaterial].Specular.a = 1.0f;
			
			Model.m_vUseMaterials[numOfMaterial].Emissive.r = 0;
			Model.m_vUseMaterials[numOfMaterial].Emissive.g = 0;
			Model.m_vUseMaterials[numOfMaterial].Emissive.b = 0;
			Model.m_vUseMaterials[numOfMaterial].Emissive.a = 0;
			
			Model.m_vUseMaterials[numOfMaterial].Power = 100.0f - Material.m_fShininess*100.0f;
			
			for ( numOfObject = 0; numOfObject < Model.m_vObjects.size(); ++numOfObject)
			{
				_3DSObject & Object = Model.m_vObjects[numOfObject];
				for ( numOfTriMesh = 0; numOfTriMesh < Object.m_vTriMeshs.size(); ++numOfTriMesh)
				{
					_3DSTriMesh & Mesh = Object.m_vTriMeshs[numOfTriMesh];
					if ( Mesh.m_vUseMaterials.size() == 0)
					{
						_3DSUseMat DefaultUseMat;
						_tcscpy(DefaultUseMat.m_strName,"%NoName%");
						DefaultUseMat.m_vFaceIndices.resize(Mesh.m_vFaces.size());
						for ( numOfFace = 0; numOfFace < Mesh.m_vFaces.size(); ++numOfFace)
						{
							DefaultUseMat.m_vFaceIndices[numOfFace] = numOfFace;
						}
						Mesh.m_vUseMaterials.push_back(DefaultUseMat);
					}

					BYTE * bFaceHasMat = new BYTE[Mesh.m_vFaces.size()];					
					for ( numOfUseMat = 0; numOfUseMat < Mesh.m_vUseMaterials.size(); ++numOfUseMat)
					{
						_3DSUseMat & UseMat = Mesh.m_vUseMaterials[numOfUseMat];
						if ( _tcscmp( UseMat.m_strName,Material.m_strName) == 0)
							UseMat.m_usMatIdx = numOfMaterial;
						
						for ( INT i = 0; i<UseMat.m_vFaceIndices.size(); ++i)
						{
							bFaceHasMat[UseMat.m_vFaceIndices[i]] = TRUE;
						}
					}
					// 添加附加Mat.
					_3DSUseMat ExtraMat;
					ExtraMat.m_usMatIdx = -1;
					for ( numOfFace = 0; numOfFace < Mesh.m_vFaces.size(); ++numOfFace)
					{
						if(bFaceHasMat[numOfFace] != TRUE)
						{
							ExtraMat.m_vFaceIndices.push_back(numOfFace);
						}
					}
					if ( ExtraMat.m_vFaceIndices.size() != 0 )
						Mesh.m_vUseMaterials.push_back(ExtraMat);
					
					SAFE_DELETE_ARRAY(bFaceHasMat);
				}		
			}		
		}
	}
}

VOID _3DS::CalculateFaceNormals()
{
	INT numOfModel = 0;
	INT numOfObject = 0;
	INT numOfTriMesh = 0;
	INT numOfFace = 0;
	INT numOfVert = 0;
	
	for ( numOfModel = 0; numOfModel < m_3DSFile.m_vModels.size(); ++numOfModel)
	{
		_3DSModel & Model = m_3DSFile.m_vModels[numOfModel];
		for ( numOfObject = 0; numOfObject < Model.m_vObjects.size(); ++numOfObject)
		{
			_3DSObject & Object = Model.m_vObjects[numOfObject];
			for ( numOfTriMesh = 0; numOfTriMesh < Object.m_vTriMeshs.size(); ++numOfTriMesh)
			{				
				_3DSTriMesh & Mesh = Object.m_vTriMeshs[numOfTriMesh];				
				for ( numOfFace = 0; numOfFace < Mesh.m_vFaces.size(); ++numOfFace)
				{
					_3DSFace & Face = Mesh.m_vFaces[numOfFace];
					_3DSVect & va = Mesh.m_vVertices[Face.m_usIndices[0]].vPos;
					_3DSVect & vb = Mesh.m_vVertices[Face.m_usIndices[1]].vPos;
					_3DSVect & vc = Mesh.m_vVertices[Face.m_usIndices[2]].vPos;
					
					D3DXVECTOR3 vA = D3DXVECTOR3(va.x,va.y,va.z);
					D3DXVECTOR3 vB = D3DXVECTOR3(vb.x,vb.y,vb.z);
					D3DXVECTOR3 vC = D3DXVECTOR3(vc.x,vc.y,vc.z);
					
					D3DXVECTOR3 vAC,vAB,vNormal;
					D3DXVec3Subtract(&vAC,&vA,&vC);
					D3DXVec3Subtract(&vAB,&vB,&vA);
					D3DXVec3Cross(&vNormal, &vAC, &vAB);
					D3DXVec3Normalize(&vNormal,&vNormal);
					Face.m_vecNormal.x = vNormal.x;
					Face.m_vecNormal.y = vNormal.y;
					Face.m_vecNormal.z = vNormal.z;
				}
				
				for ( numOfVert = 0; numOfVert < Mesh.m_vVertices.size(); ++numOfVert)
				{
					INT VertShare = 0;
					_3DSVert & Vert = Mesh.m_vVertices[numOfVert];
					D3DXVECTOR3 vNormal = D3DXVECTOR3(0,0,0);
					for ( numOfFace = 0; numOfFace < Mesh.m_vFaces.size(); ++numOfFace)
					{
						_3DSFace & Face = Mesh.m_vFaces[numOfFace];
						if ( Face.m_usIndices[0] == numOfVert || Face.m_usIndices[1] == numOfVert || Face.m_usIndices[2] == numOfVert )
						{
							vNormal.x += Face.m_vecNormal.x;
							vNormal.y += Face.m_vecNormal.y;
							vNormal.z += Face.m_vecNormal.z;
							VertShare ++;
						}
					}
					vNormal.x /= VertShare;
					vNormal.y /= VertShare;
					vNormal.z /= VertShare;
					
					D3DXVec3Normalize(&vNormal,&vNormal);
					Vert.vNormal.x = vNormal.x;
					Vert.vNormal.y = vNormal.y;
					Vert.vNormal.z = vNormal.z;
				}
			}		
		}
	}
}

VOID _3DS::ArrangeVertex()
{
	INT numOfModel = 0;
	INT numOfObject = 0;
	INT numOfTriMesh = 0;
	INT numOfFace = 0;
	INT numOfVert = 0;
	INT numOfTexCoord = 0;
	
	for ( numOfModel = 0; numOfModel < m_3DSFile.m_vModels.size(); ++numOfModel)
	{
		_3DSModel & Model = m_3DSFile.m_vModels[numOfModel];
		for ( numOfObject = 0; numOfObject < Model.m_vObjects.size(); ++numOfObject)
		{
			_3DSObject & Object = Model.m_vObjects[numOfObject];
			for ( numOfTriMesh = 0; numOfTriMesh < Object.m_vTriMeshs.size(); ++numOfTriMesh)
			{
				_3DSTriMesh & Mesh = Object.m_vTriMeshs[numOfTriMesh];
				for ( numOfVert = 0; numOfVert < Mesh.m_vVertices.size(); ++numOfVert)
				{
					_3DSVert & vert = Mesh.m_vVertices[numOfVert];
					std::swap(vert.vPos.y,vert.vPos.z);
				}

				for ( numOfTexCoord = 0; numOfTexCoord <Mesh.m_vTexCoords.size(); ++numOfTexCoord)
				{
					_3DSTexCoord & tex = Mesh.m_vTexCoords[numOfTexCoord];
					tex.v = -tex.v;
				}

				for ( numOfFace = 0; numOfFace < Mesh.m_vFaces.size(); ++numOfFace)
				{
					_3DSFace & face = Mesh.m_vFaces[numOfFace];
					std::swap(face.m_usIndices[1],face.m_usIndices[2]);
				}
			}
		}
	}
}

VOID _3DS::CalculateBoundingMesh()
{
	INT numOfModel = 0;
	INT numOfObject = 0;
	INT numOfTriMesh = 0;
	INT numOfFace = 0;
	INT numOfVert = 0;
	INT numOfTexCoord = 0;
	
	for ( numOfModel = 0; numOfModel < m_3DSFile.m_vModels.size(); ++numOfModel)
	{
		_3DSModel & Model = m_3DSFile.m_vModels[numOfModel];
		for ( numOfObject = 0; numOfObject < Model.m_vObjects.size(); ++numOfObject)
		{
			_3DSObject & Object = Model.m_vObjects[numOfObject];
			for ( numOfTriMesh = 0; numOfTriMesh < Object.m_vTriMeshs.size(); ++numOfTriMesh)
			{
				_3DSTriMesh & Mesh = Object.m_vTriMeshs[numOfTriMesh];
				if ( Mesh.m_vVertices.size() != 0)
				{
					D3DXComputeBoundingBox((PVOID)Mesh.m_vVertices.begin(),Mesh.m_vVertices.size(),
						D3DVERTEX::D3DFVF_D3DVERTEX,&Mesh.m_vMin,&Mesh.m_vMax);
					D3DXComputeBoundingSphere((PVOID)Mesh.m_vVertices.begin(),Mesh.m_vVertices.size(),
						D3DVERTEX::D3DFVF_D3DVERTEX,&D3DXVECTOR3(0,0,0),&Mesh.m_fRadius);
					m_vMin.x = min(m_vMin.x, Mesh.m_vMin.x);
					m_vMin.y = min(m_vMin.y, Mesh.m_vMin.y);
					m_vMin.z = min(m_vMin.z, Mesh.m_vMin.z);
					m_vMax.x = max(m_vMax.x, Mesh.m_vMax.x);
					m_vMax.y = max(m_vMax.y, Mesh.m_vMax.y);
					m_vMax.z = max(m_vMax.z, Mesh.m_vMax.z);
					m_fRadius = max(m_fRadius, Mesh.m_fRadius);
				}
			}
		}
	}
}

VOID _3DS::Read3DSFile(LPDIRECT3DDEVICE8 device,TCHAR * strFileName,TCHAR * strFilePath)
{
	m_fpBin3ds = NULL;

	m_pD3DDevice = device;
	if ( strFileName == NULL ) 
		return;

	m_fpBin3ds = _tfopen(strFileName,"rb");
	
	if ( m_fpBin3ds == NULL ) 
		return;

	fseek(m_fpBin3ds,28L,SEEK_SET);

	m_3DSFile.Version = ReadChar();

	if ( m_3DSFile.Version < 3 ) 
		return;

	ChangeChunkPointer(0);

	ReadPrimaryChunk();
	
	fclose(m_fpBin3ds);

	_tcscpy(m_strFilePath,strFilePath);


	ArrangeVertex();

	CalculateFaceNormals();

	Parse3DSFile();


	CalculateBoundingMesh();
}

DWORD _3DS::ReadLightChunk(_3DSLight & Light)
{
	DWORD current_pointer = 0;
	DWORD temp_pointer = 0;
	DWORD teller = 6L + 12L;
	BYTE bEnd = FALSE;
	current_pointer = GetChunkPointer();
	temp_pointer = ReadChunkPointer();
	
	Light.m_vPos.x = ReadFloat();
	Light.m_vPos.y = ReadFloat();
	Light.m_vPos.z = ReadFloat();
	
	while ( bEnd == FALSE )
	{
		switch( ReadInt() )
		{
			teller += ReadChunkPointer();
			Light.m_Diffuseclr.r = ReadFloat();
			Light.m_Diffuseclr.g = ReadFloat();
			Light.m_Diffuseclr.b = ReadFloat();
			break;
		case COL_TRU :
			teller += ReadChunkPointer();
			Light.m_Diffuseclr.r = (FLOAT) ReadChar() / 255.0f;
			Light.m_Diffuseclr.g = (FLOAT) ReadChar() / 255.0f;
			Light.m_Diffuseclr.b = (FLOAT) ReadChar() / 255.0f;
			break;
		case LIT_SPOT:
			teller += ReadChunkPointer();
			Light.m_vSpotlightDir.x = ReadFloat();
			Light.m_vSpotlightDir.y = ReadFloat();
			Light.m_vSpotlightDir.z = ReadFloat();
			Light.m_fSpot = ReadFloat();
			Light.m_fAngle = ReadFloat();
			break;
		case LIT_OFF:
			ReadBooleanChunk(&Light.m_bOn);
			break;
		default:
			ReadUnknownChunk();
			break;
		}
		if( teller == temp_pointer)
			bEnd = TRUE;
	}
	
	ChangeChunkPointer(current_pointer+temp_pointer);
	return (temp_pointer);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -