📄 3dsloader.cpp
字号:
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 + -