由3DS MAX导出的3ds模型的显示很简单。所谓代码之中,了无秘密。接口很简单:
存储:
模型信息和贴图信息,位于全局变量:
//纹理信息
UINT g_Texture[10][MAX_TEXTURES] = {0};
说明,其中MAX_TEXTURES 是100,表示最大的纹理数目。即一个模型文件,可以对应多个贴图。
//模型信息
t3DModel g_3DModel[10];
函数接口:
加载3D模型:
//入参 模型文件路径 模型数组g_3DModel的指定下标
void CLoad3DS::Init(char *filename,int j)
显示3D模型:
//入参 数组g_3DModel下标 显示坐标 缩放倍数
void CLoad3DS::show3ds(int j0,float tx,float ty,float tz,float size)
注意事项:3DS模型文件和对应的贴图文件要放在同一个文件夹中。3DS MAX系统单位的1毫米对应OPENGL中的一个单位。
附:接口类CLoad3DS的头文件和源文件
3ds.h /
#ifndef _3DS_H
#define _3DS_H
#include <math.h>
#include <vector>
// 基本块(Primary Chunk),位于文件的开始
#define PRIMARY 0x4D4D
// 主块(Main Chunks)
#define OBJECTINFO 0x3D3D // 网格对象的版本号
#define VERSION 0x0002 // .3ds文件的版本
#define EDITKEYFRAME 0xB000 // 所有关键帧信息的头部
// 对象的次级定义(包括对象的材质和对象)
#define MATERIAL 0xAFFF // 保存纹理信息
#define OBJECT 0x4000 // 保存对象的面、顶点等信息
// 材质的次级定义
#define MATNAME 0xA000 // 保存材质名称
#define MATDIFFUSE 0xA020 // 对象/材质的颜色
#define MATMAP 0xA200 // 新材质的头部
#define MATMAPFILE 0xA300 // 保存纹理的文件名
#define OBJ_MESH 0x4100 // 新的网格对象
#define MAX_TEXTURES 100 // 最大的纹理数目
// OBJ_MESH的次级定义
#define OBJ_VERTICES 0x4110 // 对象顶点
#define OBJ_FACES 0x4120 // 对象的面
#define OBJ_MATERIAL 0x4130 // 对象的材质
#define OBJ_UV 0x4140 // 对象的UV纹理坐标
using namespace std;
class CVector3 //定义3D点的类,用于保存模型中的顶点
{
public: float x, y, z;
};
class CVector2 //定义2D点类,用于保存模型的UV纹理坐标
{
public: float x, y;
};
struct tFace //面的结构定义
{
int vertIndex[3]; // 顶点索引
int coordIndex[3]; // 纹理坐标索引
};
struct tMatInfo//材质信息结构体
{
char strName[255]; // 纹理名称
char strFile[255]; // 如果存在纹理映射,则表示纹理文件名称
BYTE color[3]; // 对象的RGB颜色
int texureId; // 纹理ID
float uTile; // u 重复
float vTile; // v 重复
float uOffset; // u 纹理偏移
float vOffset; // v 纹理偏移
} ;
struct t3DObject //对象信息结构体
{
int numOfVerts; // 模型中顶点的数目
int numOfFaces; // 模型中面的数目
int numTexVertex; // 模型中纹理坐标的数目
int materialID; // 纹理ID
bool bHasTexture; // 是否具有纹理映射
char strName[255]; // 对象的名称
CVector3 *pVerts; // 对象的顶点
CVector3 *pNormals; // 对象的法向量
CVector2 *pTexVerts; // 纹理UV坐标
tFace *pFaces; // 对象的面信息
};
struct t3DModel //模型信息结构体
{
int numOfObjects; // 模型中对象的数目
int numOfMaterials; // 模型中材质的数目
vector<tMatInfo> pMaterials; // 材质链表信息
vector<t3DObject> pObject; // 模型中对象链表信息
};
struct tChunk //保存块信息的结构
{
unsigned short int ID; // 块的ID
unsigned int length; // 块的长度
unsigned int bytesRead; // 需要读的块数据的字节数
};
//
class CLoad3DS// CLoad3DS类处理所有的装入代码
{
public:
CLoad3DS(); // 初始化数据成员
virtual ~CLoad3DS();
void show3ds(int j0,float tx,float ty,float tz,float size);//显示3ds模型
void Init(char *filename,int j);
void CleanUp(); // 关闭文件,释放内存空间
private:
bool Import3DS(t3DModel *pModel, char *strFileName);// 装入3ds文件到模型结构中
void CreateTexture(UINT textureArray[], LPSTR strFileName, int textureID);// 从文件中创建纹理
int GetString(char *); // 读一个字符串
void ReadChunk(tChunk *); // 读下一个块
void ReadNextChunk(t3DModel *pModel, tChunk *); // 读下一个块
void ReadNextObjChunk(t3DModel *pModel,t3DObject *pObject,tChunk *);// 读下一个对象块
void ReadNextMatChunk(t3DModel *pModel, tChunk *); // 读下一个材质块
void ReadColor(tMatInfo *pMaterial, tChunk *pChunk);// 读对象颜色的RGB值
void ReadVertices(t3DObject *pObject, tChunk *); // 读对象的顶点
void ReadVertexIndices(t3DObject *pObject,tChunk *);// 读对象的面信息
void ReadUVCoordinates(t3DObject *pObject,tChunk *);// 读对象的纹理坐标
void ReadObjMat(t3DModel *pModel,t3DObject *pObject,tChunk *pPreChunk);// 读赋予对象的材质名称
void ComputeNormals(t3DModel *pModel); // 计算对象顶点的法向量
FILE *m_FilePointer; // 文件指针
tChunk *m_CurrentChunk;
tChunk *m_TempChunk;
};
#endif
3ds.cpp /
#include "stdafx.h"
#include "3ds.h"
//纹理信息
UINT g_Texture[10][MAX_TEXTURES] = {0};
//模型信息
t3DModel g_3DModel[10];
//绘制方式
int g_ViewMode = GL_TRIANGLES;
bool g_bLighting = true;
CLoad3DS::CLoad3DS()
{
m_CurrentChunk = new tChunk;
m_TempChunk = new tChunk;
}
CLoad3DS::~CLoad3DS()
{
CleanUp();
for(int j = 0; j <10;j++)
{