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

📄 3dsloader.cpp

📁 三维模型数据格式3DS数据的读取。详细分解3DS数据格式
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	dwMtrlNum	= dwMaterialNum;
	dwObjNum	= dwObjectNum;
	return GL3DSLOADER_OK;
}
//----------------------------------------------------
//Function Name	: RebuildMesh
//Desc			: 重新排列顶点
//Input			:lpMesh		: 重排的对象
//				: lplpMaterial	: 所有的材质对象指针数组
//Output		: lplistVertex	: 重排的顶点链表
//				: lplistTexcoord: 重排的纹理坐标链表
//				: lplpTriangleIndex
//								: 重排的面索引数组
//Notice		: 输入参数的正确性均由调用者保证,
//				: 输出指针由调用者销毁
//----------------------------------------------------
//该函数和GenerateData函数还可以使用更简洁一些的处理方法(用查表的方法确定新的顶点数组)
//两种方法各有优劣,list需要的数据结构更复杂一些,查表需要更多的空间,
//在如果材质很多,而且每个材质对应的面很散的情况下,查表计算的速度不如list
//使用list在重排的时候就可以计算纹理坐标,查表则要到转换的时候才可以
void	CGL3DSLoader::RebuildMesh(	const CGL3DSLoader::MESHDATA* lpMesh,
									const CGL3DSLoader::MATERIALDATA* const * lplpMaterial,
									list<GLVERTEX3>* &lplistVertex,
									list<GLTEXCOORD>* &lplistTexcoord,
									MESHTRIANGLEINDEX**& lplpTriangleIndex )
{
	lplistVertex = new list<GLVERTEX3>[lpMesh->dwMaterialNum];		//每个材质对应的顶点列
	lplistTexcoord = NULL;
	if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
		lplistTexcoord = new list<GLTEXCOORD>[lpMesh->dwMaterialNum];	//每个材质对应的纹理列
	lplpTriangleIndex = new MESHTRIANGLEINDEX*[lpMesh->dwMaterialNum];
	//新顶点在旧顶点数组中的位置
	DWORD*	lptemp = new DWORD[lpMesh->dwVertexNum];
	DWORD	j;
	for( j=0; j<lpMesh->dwMaterialNum; j++ )
	{
		DWORD dwCurrentMaterial = lpMesh->lpMaterialID[j];
		memset( lptemp, 0, sizeof(DWORD)*lpMesh->dwVertexNum );
		//分配面空间
		if( lpMesh->lpFaceMaterialNum[j] )
			lplpTriangleIndex[j] = new MESHTRIANGLEINDEX[lpMesh->lpFaceMaterialNum[j]];
		else
		{
			//如果该材质上没有面
			lplpTriangleIndex[j] = NULL;
			continue;
		}
		//当前新顶点数组的顶点数目
		DWORD dwVertexAdd = 0;
		//局部纹理参数
		const float&	ou= lplpMaterial[dwCurrentMaterial]->fOffsetU;
		const float&	ov= lplpMaterial[dwCurrentMaterial]->fOffsetV;
		const float&	tu= lplpMaterial[dwCurrentMaterial]->fTilingU;
		const float&	tv= lplpMaterial[dwCurrentMaterial]->fTilingV;
		const float&	rw= lplpMaterial[dwCurrentMaterial]->fRotationW;
		for( DWORD k=0; k<lpMesh->lpFaceMaterialNum[j]; k++ )
		{
			//取得面上三个顶点的索引
			const DWORD& index1 = lpMesh->lpTriangles[ lpMesh->lplpFaceMaterialIndex[j][k] ].dwVertexIndex1;
			const DWORD& index2 = lpMesh->lpTriangles[ lpMesh->lplpFaceMaterialIndex[j][k] ].dwVertexIndex2;
			const DWORD& index3 = lpMesh->lpTriangles[ lpMesh->lplpFaceMaterialIndex[j][k] ].dwVertexIndex3;
			//对应的三个顶点
			const GLVERTEX3&	vertex1 = lpMesh->lpVertex[index1];
			const GLVERTEX3&	vertex2 = lpMesh->lpVertex[index2];
			const GLVERTEX3&	vertex3 = lpMesh->lpVertex[index3];
			//新的面索引
			DWORD	newIndex1;
			DWORD	newIndex2;
			DWORD	newIndex3;
			for( DWORD l=0; l<dwVertexAdd; l++ )
				if( lptemp[l] == index1+1 )
					break;
			//若该顶点不存在于新的顶点数组中
			if( l == dwVertexAdd )
			{
				//加入到链表中
				lplistVertex[j].push_back( vertex1 );
				//如果使用纹理
				if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
					//将变幻后的纹理坐标放入链表
					lplistTexcoord[j].push_back( TranslateTexcoord( lpMesh->lpTexcoord[index1],ou,ov,tu,tv,rw ) );
				//置标志
				lptemp[dwVertexAdd] = index1+1;
				//对应的新索引
				newIndex1 = dwVertexAdd;
				dwVertexAdd ++;
			}
			else
				//否则==旧索引
				newIndex1 = l;
			//同上
			for( l=0; l<dwVertexAdd; l++ )
				if( lptemp[l] == index2+1 )
					break;
			if( l == dwVertexAdd )
			{
				lplistVertex[j].push_back( vertex2 );
				if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
					lplistTexcoord[j].push_back( TranslateTexcoord( lpMesh->lpTexcoord[index2],ou,ov,tu,tv,rw ) );
				lptemp[dwVertexAdd] = index2+1;
				newIndex2 = dwVertexAdd;
				dwVertexAdd ++;
			}
			else
				newIndex2 = l;

			for( l=0; l<dwVertexAdd; l++ )
				if( lptemp[l] == index3+1 )
					break;
			if( l == dwVertexAdd )
			{
				lplistVertex[j].push_back( vertex3 );
				if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
					lplistTexcoord[j].push_back( TranslateTexcoord( lpMesh->lpTexcoord[index3],ou,ov,tu,tv,rw ) );
				lptemp[dwVertexAdd] = index3+1;
				newIndex3 = dwVertexAdd;
				dwVertexAdd ++;
			}
			else
				newIndex3 = l;
			//填入索引,建立面信息
			lplpTriangleIndex[j][k].dwVertexIndex1 = newIndex1;
			lplpTriangleIndex[j][k].dwVertexIndex2 = newIndex2;
			lplpTriangleIndex[j][k].dwVertexIndex3 = newIndex3;
		}//for k
	}//for j
	//释放空间
	SAFE_DELETE_ARRAY( lptemp );
}
//----------------------------------------------------
//Function Name	: GenerateData
//Desc			: 从输入数据中填充this对象数据
//Input			:dwIndex		: 网格对象索引(第几个)
//				: lpMesh		: 填充的网格对象指针
//				: lplpMaterial	: 材质对象指针数组
//Output		: NUL
//Notice		: 参数完备性由使用者保证
//----------------------------------------------------

void	CGL3DSLoader::GenerateData( DWORD dwIndex, const CGL3DSLoader::MESHDATA* lpMesh, const CGL3DSLoader::MATERIALDATA* const* lplpMaterial )
{
	list<GLVERTEX3>*	lplistVertex		= NULL;		//每个材质对应的顶点列
	list<GLTEXCOORD>*	lplistTexcoord		= NULL;
	MESHTRIANGLEINDEX**	lplpTriangleIndex	= NULL;
	//重排所有顶点
	if( !(lpMesh->dwMaterialNum) )	//如果没有材质关联到该对象上
	{
		//直接拷贝所有顶点和面信息
		if( lpMesh->dwVertexNum )
		{
			m_lpVertexNum[dwIndex]	= lpMesh->dwVertexNum;
			m_lplpVertex[dwIndex]	= new GLVERTEX3[m_lpVertexNum[dwIndex]];
			memcpy( m_lplpVertex[dwIndex], lpMesh->lpVertex, m_lpVertexNum[dwIndex]*sizeof(GLVERTEX3) );
			if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
			{
				m_lplpTexcoord[dwIndex] = new GLTEXCOORD[m_lpVertexNum[dwIndex]];
				memcpy( m_lplpTexcoord[dwIndex], lpMesh->lpTexcoord, m_lpVertexNum[dwIndex]*sizeof(GLTEXCOORD) );
			}
		}
		if( lpMesh->dwFaceNum )
		{
			m_lpFaceNum[dwIndex]	= lpMesh->dwFaceNum;
			m_lplpFaceIndex[dwIndex]= new MESHTRIANGLEINDEX[lpMesh->dwFaceNum];
			memcpy( m_lplpFaceIndex[dwIndex], lpMesh->lpTriangles, sizeof(MESHTRIANGLEINDEX)*lpMesh->dwFaceNum );
		}
		return;
	}
	RebuildMesh( lpMesh, lplpMaterial, lplistVertex, lplistTexcoord, lplpTriangleIndex );

	DWORD	dwTotalVertex	= 0;
	DWORD	dwTotalFace		= 0;
	
	for( DWORD j=0; j<lpMesh->dwMaterialNum; j++ )
	{
		dwTotalVertex	+= lplistVertex[j].size();
		dwTotalFace		+= lpMesh->lpFaceMaterialNum[j];
	}
	//为this对象分配空间
	m_lplpVertex[dwIndex]		= new GLVERTEX3[dwTotalVertex];
	m_lpVertexNum[dwIndex]		= dwTotalVertex;
	if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
		m_lplpTexcoord[dwIndex]	= new GLTEXCOORD[dwTotalVertex];
	m_lplpFaceIndex[dwIndex]	= new MESHTRIANGLEINDEX[dwTotalFace];
	m_lpFaceNum[dwIndex]		= dwTotalFace;
	m_lpFlags[dwIndex]			= lpMesh->dwFlags;
	
	DWORD	dwVertexBegin = 0;
	DWORD	dwFaceBegin = 0;

	//将重排后的顶点放入this对象的数据中
	list<DWORD>		listFaceMaterialID;
	list<DWORD>		listFaceMaterialBegin;
	list<DWORD>		listFaceMaterialEnd;
	for( j=0; j<lpMesh->dwMaterialNum; j++ )
	{
		//顶点
		DWORD	dwVertexNum = lplistVertex[j].size();
		if( !dwVertexNum )
			continue;
		listFaceMaterialID.push_back( lpMesh->lpMaterialID[j] );
		listFaceMaterialBegin.push_back( dwFaceBegin );
		for( DWORD k=0; k<dwVertexNum; k++ )
		{
			m_lplpVertex[dwIndex][k+dwVertexBegin] = lplistVertex[j].front();
			lplistVertex[j].pop_front();
		}
		//纹理坐标
		if( lpMesh->dwFlags & MESH_USINGTEXCOORD )
		{
			for( DWORD k=0; k<dwVertexNum; k++ )
			{
				m_lplpTexcoord[dwIndex][k+dwVertexBegin] = lplistTexcoord[j].front();
				lplistTexcoord[j].pop_front();
			}
		}
		//面信息
		for( k=0; k<lpMesh->lpFaceMaterialNum[j]; k++ )
		{
			m_lplpFaceIndex[dwIndex][k+dwFaceBegin].dwVertexIndex1 = lplpTriangleIndex[j][k].dwVertexIndex1 + dwVertexBegin;
			m_lplpFaceIndex[dwIndex][k+dwFaceBegin].dwVertexIndex2 = lplpTriangleIndex[j][k].dwVertexIndex2 + dwVertexBegin;
			m_lplpFaceIndex[dwIndex][k+dwFaceBegin].dwVertexIndex3 = lplpTriangleIndex[j][k].dwVertexIndex3 + dwVertexBegin;
		}
		dwVertexBegin += dwVertexNum;
		dwFaceBegin	+= lpMesh->lpFaceMaterialNum[j];
		listFaceMaterialEnd.push_back( dwFaceBegin-1 );
	}
	m_lpFaceMaterialNum[dwIndex]	= listFaceMaterialID.size();
	if( m_lpFaceMaterialNum[dwIndex] )
	{
		m_lplpFaceMaterialID[dwIndex]	= new DWORD[m_lpFaceMaterialNum[dwIndex]];
		m_lplpFaceMaterialBegin[dwIndex]= new DWORD[m_lpFaceMaterialNum[dwIndex]];
		m_lplpFaceMaterialEnd[dwIndex]	= new DWORD[m_lpFaceMaterialNum[dwIndex]];
		for( j=0; j<m_lpFaceMaterialNum[dwIndex]; j++ )
		{
			m_lplpFaceMaterialID[dwIndex][j]	= listFaceMaterialID.front();
			listFaceMaterialID.pop_front();
			m_lplpFaceMaterialBegin[dwIndex][j] = listFaceMaterialBegin.front();
			listFaceMaterialBegin.pop_front();
			m_lplpFaceMaterialEnd[dwIndex][j]	= listFaceMaterialEnd.front();
			listFaceMaterialEnd.pop_front();
		}
	}
	//对象的名称
	m_lpstrName[dwIndex] = lpMesh->strName;
	//释放中间变量
	SAFE_DELETE_ARRAY( lplistVertex );
	SAFE_DELETE_ARRAY( lplistTexcoord );
	for( j=0; j<lpMesh->dwMaterialNum; j++ )
		SAFE_DELETE_ARRAY( lplpTriangleIndex[j] );
	SAFE_DELETE_ARRAY( lplpTriangleIndex );
}
//----------------------------------------------------
//Function Name	: TranslateTexcoord
//Desc			: 根据材质参数将局部纹理坐标映射到全局纹理坐标
//Input			:src			: 用于变换的局部纹理坐标
//				: ou ect.		: 材质定义的纹理参数
//Output		: 全局纹理坐标
//Notice		: 参数完备性由使用者保证
//----------------------------------------------------
GLTEXCOORD CGL3DSLoader::TranslateTexcoord( const GLTEXCOORD& src, float ou, float ov, float tu, float tv, float rw )
{
	GLTEXCOORD	tex;
	float x = src.x;
	float y = src.y;
	float ou1 = ou;
	float ov1 = ov;
	//先计算旋转后的纹理坐标
	if( MyMath::abs( rw - 0.0f ) >= 0.00001 )
	{
		float x1 = x, y1 = y;
		float theta = -(float)(PI*rw)/180.0f;
		x = (float)cos(theta)*(x1-0.5f) - (float)sin(theta)*(y1-0.5f) + 0.5f;
		y = (float)sin(theta)*(x1-0.5f) + (float)cos(theta)*(y1-0.5f) + 0.5f;
		ou1 = (float)cos(theta)*ou - (float)sin(theta)*ov;
		ov1 = (float)sin(theta)*ou + (float)cos(theta)*ov;
	}
	//根据offset和tiling计算在全局纹理中的位置
	tex.x = ( x - ou1 -0.5f ) * tu + 0.5f;
	tex.y = ( y - ov1 -0.5f ) * tv + 0.5f;
	return tex;
}

//----------------------------------------------------
//Function Name	: Create
//Desc			: 根据输入的文件名创建对象
//Input			:filename		: 重排的对象
//Output		: 成功返回GL3DSLOADER_OK,否则返回错误代码
//Notice		: 文件不存在或者文件不是3DS文件调用均失败
//----------------------------------------------------
HRESULT	CGL3DSLoader::Create( string filename )
{
	MESHDATA**		lplpMesh		= NULL;
	MATERIALDATA**	lplpMaterial	= NULL;
	DWORD			dwMesh		= 0;
	DWORD			dwMaterial	= 0;
	HRESULT			hr = GL3DSLOADER_OK;
	//导入数据
	if( hr = LoadData( filename, lplpMaterial, lplpMesh, dwMaterial, dwMesh ) != GL3DSLOADER_OK )
		return hr;
	//释放空间
	Cleanup();
	m_dwObjectNum	= dwMesh;
	m_dwMaterialNum	= dwMaterial;
	m_lplpVertex	= new GLVERTEX3*[m_dwObjectNum];
	m_lplpTexcoord	= new GLTEXCOORD*[m_dwObjectNum];
	for( DWORD i=0; i<m_dwObjectNum; i++ )
		m_lplpTexcoord[i] = NULL;
	m_lpVertexNum	= new DWORD[m_dwObjectNum];
	m_lplpFaceIndex	= new MESHTRIANGLEINDEX*[m_dwObjectNum];
	m_lpFaceNum		= new DWORD[m_dwObjectNum];
	m_lpFlags		= new DWORD[m_dwObjectNum];
	m_lpstrName		= new string[m_dwObjectNum];
	m_lpFaceMaterialNum		= new DWORD[m_dwObjectNum];
	m_lplpFaceMaterialID	= new DWORD*[m_dwObjectNum];
	m_lplpFaceMaterialBegin	= new DWORD*[m_dwObjectNum];
	m_lplpFaceMaterialEnd	= new DWORD*[m_dwObjectNum];
	memset( m_lplpFaceMaterialEnd, 0, sizeof(DWORD*)*m_dwObjectNum);
	memset( m_lplpFaceMaterialBegin, 0, sizeof(DWORD*)*m_dwObjectNum);
	memset( m_lplpFaceMaterialID, 0, sizeof(DWORD*)*m_dwObjectNum);
	memset( m_lpFaceMaterialNum, 0, sizeof(DWORD)*m_dwObjectNum);
	memset( m_lpFlags, 0, sizeof(DWORD)*m_dwObjectNum);
	memset( m_lpFaceNum, 0, sizeof(DWORD)*m_dwObjectNum);
	memset( m_lplpFaceIndex, 0, sizeof(MESHTRIANGLEINDEX*)*m_dwObjectNum);
	memset( m_lpVertexNum, 0, sizeof(DWORD)*m_dwObjectNum);
	//重排每个对象的顶点数据
	for( i=0; i<m_dwObjectNum; i++ )
		GenerateData( i, lplpMesh[i], lplpMaterial );
	list<string>	listTexture;
	for( i=0; i<m_dwMaterialNum; i++ )
		if( find( listTexture.begin(), listTexture.end(), lplpMaterial[i]->strTexture ) == listTexture.end() )
			listTexture.push_back( lplpMaterial[i]->strTexture );
	m_dwTextureNum	= listTexture.size();
	
	//重建Texture列表
	m_lpstrTexture = new string[m_dwTextureNum];
	for( i=0; i<m_dwTextureNum; i++ )
	{
		m_lpstrTexture[i] = listTexture.front();
		listTexture.pop_front();
	}
	
	//重建Material列表
	m_dwMaterialNum = dwMaterial;
	m_lpMaterial = new GL3DSMATERIAL[dwMaterial];
	for( i=0; i<m_dwMaterialNum; i++ )
	{
		m_lpMaterial[i].m_IsOK = true;
		
		m_lpMaterial[i].m_lpAmbient[0] = lplpMaterial[i]->pAmbient[0];
		m_lpMaterial[i].m_lpAmbient[1] = lplpMaterial[i]->pAmbient[1];
		m_lpMaterial[i].m_lpAmbient[2] = lplpMaterial[i]->pAmbient[2];
		m_lpMaterial[i].m_lpAmbient[3] = lplpMaterial[i]->pAmbient[3];
	
		m_lpMaterial[i].m_lpDiffuse[0] = lplpMaterial[i]->pDiffuse[0];
		m_lpMaterial[i].m_lpDiffuse[1] = lplpMaterial[i]->pDiffuse[1];
		m_lpMaterial[i].m_lpDiffuse[2] = lplpMaterial[i]->pDiffuse[2];
		m_lpMaterial[i].m_lpDiffuse[3] = lplpMaterial[i]->pDiffuse[3];
		
		m_lpMaterial[i].m_lpSpecular[0] = lplpMaterial[i]->pSpecular[0];
		m_lpMaterial[i].m_lpSpecular[1] = lplpMaterial[i]->pSpecular[1];
		m_lpMaterial[i].m_lpSpecular[2] = lplpMaterial[i]->pSpecular[2];
		m_lpMaterial[i].m_lpSpecular[3] = lplpMaterial[i]->pSpecular[3];
		
		for( DWORD j=0; j<m_dwTextureNum; j++ )
			if( lplpMaterial[i]->strTexture == m_lpstrTexture[j] )
				break;
		//纹理使用ID表示
		if( j != m_dwTextureNum )
			m_lpMaterial[i].m_dwTexture = j+1;		//纹理索引
		else
			m_lpMaterial[i].m_dwTexture = 0;
	}
	//释放中间变量
	if( lplpMesh )
	{
		for( DWORD i=0; i<dwMesh; i++ )
			SAFE_DELETE( lplpMesh[i] );
	}
	if( lplpMaterial )
	{
		for( DWORD i=0; i<dwMaterial; i++ )
			SAFE_DELETE( lplpMaterial[i] );
	}
	SAFE_DELETE_ARRAY( lplpMesh );
	SAFE_DELETE_ARRAY( lplpMaterial );
	//建立成功
	m_IsOK = true;
	return GL3DSLOADER_OK;
}

⌨️ 快捷键说明

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