OpenGL系统设计-高级3D模型接口之OBJ模型(2)
2009-12-26 19:31
477 查看
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
p.MsoBodyText, li.MsoBodyText, div.MsoBodyText
{margin-top:0cm;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
p.MsoBodyTextFirstIndent, li.MsoBodyTextFirstIndent, div.MsoBodyTextFirstIndent
{mso-style-update:auto;
mso-style-parent:正文文本;
mso-style-link:" Char Char";
margin:0cm;
margin-bottom:.0001pt;
text-indent:19.85pt;
mso-pagination:none;
font-size:10.5pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-ansi-language:ZH-CN;}
p.a, li.a, div.a
{mso-style-name:正文(首行不缩进);
margin:0cm;
margin-bottom:.0001pt;
line-height:150%;
mso-pagination:none;
mso-layout-grid-align:none;
text-autospace:none;
font-size:10.5pt;
mso-bidi-font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;}
span.CharChar
{mso-style-name:" Char Char";
mso-style-locked:yes;
mso-style-link:正文首行缩进;
mso-ansi-font-size:10.5pt;
mso-bidi-font-size:10.5pt;
font-family:宋体;
mso-fareast-font-family:宋体;
mso-ansi-language:ZH-CN;
mso-fareast-language:ZH-CN;
mso-bidi-language:AR-SA;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
了解了
OBJ文件的格式后,下面我们就可以使用代码来显示
OBJ三维模型了,为了简便起见,这里我们借用
Nate
Robins的
glm函数库。它包含一个
glm.h头文件和一个
glm.c文件,在
glm.h中是
OBJ中各种数据类型的定义。
/* GLMmaterial:
定义模型中的一种材质
*/
typedef struct _GLMmaterial
{
char* name;
//
材质名称
GLfloat
diffuse[4];
//
漫反射分量
GLfloat
ambient[4];
//
环境光分量
GLfloat
specular[4];
//
镜面光分量
GLfloat
emmissive[4];
//
散射分量
GLfloat
shininess;
} GLMmaterial;
/* GLMtriangle:
定义模型中的一个三角形
*/
typedef struct _GLMtriangle
{
GLuint
vindices[3];
//
三角形顶点
GLuint
nindices[3];
//
法向量
GLuint
tindices[3];
//
纹理坐标
GLuint
findex;
//
面法向量索引
} GLMtriangle;
/* GLMgroup:
定义模型中的一个组
*/
typedef struct _GLMgroup
{
char*
name;
//
组的名字
GLuint
numtriangles;
//
组中的三角形个数
GLuint*
triangles;
//
三角形顶点指针
GLuint
material;
//
组使用的材质索引
struct
_GLMgroup* next;
//
模型中下一个组的指针
} GLMgroup;
/* GLMmodel:
定义一个模型
*/
typedef struct _GLMmodel
{
char*
pathname;
//
模型的路径
char*
mtllibname;
//
材质库的名字
GLuint
numvertices;
//
模型中顶点的数目
GLfloat*
vertices;
//
顶点数据
GLuint
numnormals;
//
模型中法向量数目
GLfloat*
normals;
//
法向量数据
GLuint
numtexcoords;
//
模型中纹理坐标的数目
GLfloat*
texcoords;
//
纹理坐标数据
GLuint
numfacetnorms;
//
模型中面法向量的数目
GLfloat*
facetnorms;
//
面法向量数据
GLuint
numtriangles;
//
模型中三角形的数目
GLMtriangle*
triangles;
//
三角形数据
GLuint
nummaterials;
//
模型中材质的数目
GLMmaterial*
materials;
//
材质数据
GLuint
numgroups;
//
模型中组的数目
GLMgroup*
groups;
//
组的数据
GLfloat
position[3];
//
模型所在的位置
} GLMmodel;
glm.c中几个重要的函数分别是
glmReadOBJ,
glmDraw ,
glmUnitize,
glmFacetNormals,
glmVertexNormals和
glmDelete。
下面是加载
OBJ文件的几个基本步骤。
首先定义一个
OBJ文件和一个用于处理
OBJ模型的
GLMmodel对象
g_model。
char* g_model_fn = " al.obj";
GLMmodel* g_model = NULL;
再使用
glmReadOBJ来读取
OBJ文件,返回一个模型的指针,然后使用
glmUnitize对模型归一化到一个
(-0.5,-0.5,-0.5)-(0.5,0.5,0.5)的盒子内。这时模型的最大尺寸是
1,中心在原点
(0.0,
0.0, 0.0)。使用
glmScale对模型进行比例缩放,这里是放大
1.5倍,使得整个模型的高度为
1.5。然后针对调入的模型生产面法向量和点法向量。
g_model = glmReadOBJ(g_model_fn);
if (!g_model) exit(0);
glmUnitize(g_model);
glmScale(g_model,1.5);
glmFacetNormals(g_model);
glmVertexNormals(g_model, 90.0);
对模型的初始化就完成了。接下来就是显示模型。模型的位置在
ObjPosition,即
(0,
1,
-2)。因为
OBJ模型本身包含了纹理,并且由显示函数
glmDraw来决定显式的模式,因此,这里不需要显式的指定启用纹理,让
glmDraw自己处理。
CVector3
ObjPosition(0, 1, -2);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glTranslatef(ObjPosition.x,
ObjPosition.y, ObjPosition.z);
glmDraw(g_model,GLM_SMOOTH
| GLM_MATERIAL | GLM_TEXTURE);
在最后程序结束时还需要释放模型。
if(g_model)
glmDelete(g_model);
上面的代码分布在
glInit
、
glMain
和
glShutdown
三个函数中
,
下面作详细的说明。
#include "glm.h"
char*
g_model_fn = "al.obj";
GLMmodel*
g_model = NULL;
int glInit(GLvoid)
{
if (!DXInit())
//
初始化DirectInput
{
return FALSE;
//
失败,返回
}
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
g_Camera.PositionCamera(0,
1.5f, 6,
0, 1.5f, 0,
0, 1, 0);
//
增加对OBJ
模型初始化部分
g_model = glmReadOBJ(g_model_fn);
if (!g_model) exit(0);
glmUnitize(g_model);
glmScale(g_model,1.5);
glmFacetNormals(g_model);
glmVertexNormals(g_model, 90.0);
return TRUE;
}
int glMain(GLvoid)
{
HRESULT hr;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clear Screen And Depth Buffer
glLoadIdentity();
CVector3
ObjPosition(2,
1, -2);
//
获取输入设备的数据,保存在buffer
中
hr= g_KDIDev->GetDeviceState(sizeof(buffer), &buffer);
hr=
(g_MDIDev->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&mouseState));
//
对键盘输入进行处理
if(!KeyPressed())
return FALSE;
//
设置视点位置
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y,
g_Camera.m_vPosition.z,
g_Camera.m_vView.x,
g_Camera.m_vView.y,
g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y,
g_Camera.m_vUpVector.z);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
Draw3DSGrid();
CreatePyramid(-6, 0, 6, 1, 1);
CreatePyramid(6, 0, 6, 1, 1);
CreatePyramid(6, 0, -6, 1, 1);
CreatePyramid(-6, 0, -6, 1, 1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glTranslatef(ObjPosition.x, ObjPosition.y,
ObjPosition.z);
glmDraw(g_model,GLM_SMOOTH | GLM_MATERIAL);
SwapBuffers(g_hDC);
return TRUE;
}
void
glShutdown(GLvoid)
{
……
//
释放OBJ
模型对象
if(g_model)
glmDelete(g_model);
}
运行程序后可以看到一个大胖子站立在地面上
,
这个大胖子就是著名的强盗
Al (Al the gangster
),如下图
所示。这一个
OBJ
模型在
很多程序中都作为例子使用。
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
p.MsoBodyText, li.MsoBodyText, div.MsoBodyText
{margin-top:0cm;
margin-right:0cm;
margin-bottom:6.0pt;
margin-left:0cm;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
p.MsoBodyTextFirstIndent, li.MsoBodyTextFirstIndent, div.MsoBodyTextFirstIndent
{mso-style-update:auto;
mso-style-parent:正文文本;
mso-style-link:" Char Char";
margin:0cm;
margin-bottom:.0001pt;
text-indent:19.85pt;
mso-pagination:none;
font-size:10.5pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-ansi-language:ZH-CN;}
p.a, li.a, div.a
{mso-style-name:正文(首行不缩进);
margin:0cm;
margin-bottom:.0001pt;
line-height:150%;
mso-pagination:none;
mso-layout-grid-align:none;
text-autospace:none;
font-size:10.5pt;
mso-bidi-font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;}
span.CharChar
{mso-style-name:" Char Char";
mso-style-locked:yes;
mso-style-link:正文首行缩进;
mso-ansi-font-size:10.5pt;
mso-bidi-font-size:10.5pt;
font-family:宋体;
mso-fareast-font-family:宋体;
mso-ansi-language:ZH-CN;
mso-fareast-language:ZH-CN;
mso-bidi-language:AR-SA;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
了解了
OBJ文件的格式后,下面我们就可以使用代码来显示
OBJ三维模型了,为了简便起见,这里我们借用
Nate
Robins的
glm函数库。它包含一个
glm.h头文件和一个
glm.c文件,在
glm.h中是
OBJ中各种数据类型的定义。
/* GLMmaterial:
定义模型中的一种材质
*/
typedef struct _GLMmaterial
{
char* name;
//
材质名称
GLfloat
diffuse[4];
//
漫反射分量
GLfloat
ambient[4];
//
环境光分量
GLfloat
specular[4];
//
镜面光分量
GLfloat
emmissive[4];
//
散射分量
GLfloat
shininess;
} GLMmaterial;
/* GLMtriangle:
定义模型中的一个三角形
*/
typedef struct _GLMtriangle
{
GLuint
vindices[3];
//
三角形顶点
GLuint
nindices[3];
//
法向量
GLuint
tindices[3];
//
纹理坐标
GLuint
findex;
//
面法向量索引
} GLMtriangle;
/* GLMgroup:
定义模型中的一个组
*/
typedef struct _GLMgroup
{
char*
name;
//
组的名字
GLuint
numtriangles;
//
组中的三角形个数
GLuint*
triangles;
//
三角形顶点指针
GLuint
material;
//
组使用的材质索引
struct
_GLMgroup* next;
//
模型中下一个组的指针
} GLMgroup;
/* GLMmodel:
定义一个模型
*/
typedef struct _GLMmodel
{
char*
pathname;
//
模型的路径
char*
mtllibname;
//
材质库的名字
GLuint
numvertices;
//
模型中顶点的数目
GLfloat*
vertices;
//
顶点数据
GLuint
numnormals;
//
模型中法向量数目
GLfloat*
normals;
//
法向量数据
GLuint
numtexcoords;
//
模型中纹理坐标的数目
GLfloat*
texcoords;
//
纹理坐标数据
GLuint
numfacetnorms;
//
模型中面法向量的数目
GLfloat*
facetnorms;
//
面法向量数据
GLuint
numtriangles;
//
模型中三角形的数目
GLMtriangle*
triangles;
//
三角形数据
GLuint
nummaterials;
//
模型中材质的数目
GLMmaterial*
materials;
//
材质数据
GLuint
numgroups;
//
模型中组的数目
GLMgroup*
groups;
//
组的数据
GLfloat
position[3];
//
模型所在的位置
} GLMmodel;
glm.c中几个重要的函数分别是
glmReadOBJ,
glmDraw ,
glmUnitize,
glmFacetNormals,
glmVertexNormals和
glmDelete。
下面是加载
OBJ文件的几个基本步骤。
首先定义一个
OBJ文件和一个用于处理
OBJ模型的
GLMmodel对象
g_model。
char* g_model_fn = " al.obj";
GLMmodel* g_model = NULL;
再使用
glmReadOBJ来读取
OBJ文件,返回一个模型的指针,然后使用
glmUnitize对模型归一化到一个
(-0.5,-0.5,-0.5)-(0.5,0.5,0.5)的盒子内。这时模型的最大尺寸是
1,中心在原点
(0.0,
0.0, 0.0)。使用
glmScale对模型进行比例缩放,这里是放大
1.5倍,使得整个模型的高度为
1.5。然后针对调入的模型生产面法向量和点法向量。
g_model = glmReadOBJ(g_model_fn);
if (!g_model) exit(0);
glmUnitize(g_model);
glmScale(g_model,1.5);
glmFacetNormals(g_model);
glmVertexNormals(g_model, 90.0);
对模型的初始化就完成了。接下来就是显示模型。模型的位置在
ObjPosition,即
(0,
1,
-2)。因为
OBJ模型本身包含了纹理,并且由显示函数
glmDraw来决定显式的模式,因此,这里不需要显式的指定启用纹理,让
glmDraw自己处理。
CVector3
ObjPosition(0, 1, -2);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glTranslatef(ObjPosition.x,
ObjPosition.y, ObjPosition.z);
glmDraw(g_model,GLM_SMOOTH
| GLM_MATERIAL | GLM_TEXTURE);
在最后程序结束时还需要释放模型。
if(g_model)
glmDelete(g_model);
上面的代码分布在
glInit
、
glMain
和
glShutdown
三个函数中
,
下面作详细的说明。
#include "glm.h"
char*
g_model_fn = "al.obj";
GLMmodel*
g_model = NULL;
int glInit(GLvoid)
{
if (!DXInit())
//
初始化DirectInput
{
return FALSE;
//
失败,返回
}
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
g_Camera.PositionCamera(0,
1.5f, 6,
0, 1.5f, 0,
0, 1, 0);
//
增加对OBJ
模型初始化部分
g_model = glmReadOBJ(g_model_fn);
if (!g_model) exit(0);
glmUnitize(g_model);
glmScale(g_model,1.5);
glmFacetNormals(g_model);
glmVertexNormals(g_model, 90.0);
return TRUE;
}
int glMain(GLvoid)
{
HRESULT hr;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clear Screen And Depth Buffer
glLoadIdentity();
CVector3
ObjPosition(2,
1, -2);
//
获取输入设备的数据,保存在buffer
中
hr= g_KDIDev->GetDeviceState(sizeof(buffer), &buffer);
hr=
(g_MDIDev->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&mouseState));
//
对键盘输入进行处理
if(!KeyPressed())
return FALSE;
//
设置视点位置
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y,
g_Camera.m_vPosition.z,
g_Camera.m_vView.x,
g_Camera.m_vView.y,
g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y,
g_Camera.m_vUpVector.z);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
Draw3DSGrid();
CreatePyramid(-6, 0, 6, 1, 1);
CreatePyramid(6, 0, 6, 1, 1);
CreatePyramid(6, 0, -6, 1, 1);
CreatePyramid(-6, 0, -6, 1, 1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glTranslatef(ObjPosition.x, ObjPosition.y,
ObjPosition.z);
glmDraw(g_model,GLM_SMOOTH | GLM_MATERIAL);
SwapBuffers(g_hDC);
return TRUE;
}
void
glShutdown(GLvoid)
{
……
//
释放OBJ
模型对象
if(g_model)
glmDelete(g_model);
}
运行程序后可以看到一个大胖子站立在地面上
,
这个大胖子就是著名的强盗
Al (Al the gangster
),如下图
所示。这一个
OBJ
模型在
很多程序中都作为例子使用。
相关文章推荐
- OpenGL系统设计-高级3D模型接口之OBJ模型(1)
- OpenGL系统设计-高级3D模型接口之MD2模型(1)
- OpenGL系统设计-高级3D模型接口之MD2模型(2)
- OpenGL系统设计-高级3D模型接口之MD2模型(3)
- 软件工程之系统建模篇【设计接口控制类模型】
- 图像采集系统的Camera Link标准接口设计
- 模型动画系统设计的一些心得
- OpenGL系统设计-扩展建模(3)
- 连载:告诉你如何设计一个日访问量千万级别的系统,谈oracle的高级设计和开发(2)
- 软件工程之系统建模篇【设计接口类模型】
- 架构设计:系统间通信(4)——IO通信模型和JAVA实践 中篇
- 今天我们来聊一个很高级的话题:如何设计一个大规模远程命令执行系统
- OpenGL系统设计-光照与材质(1)
- [学习笔记]UML小结以及基于领域模型的系统设计初步
- 分布式系统接口幂等性设计
- 电商系统中的商品模型的分析与设计
- 基于RBAC模型的权限系统设计(Github开源项目)
- OpenGL -- OBJ 模型加载
- 电商系统中的商品模型的分析与设计—续
- B2C电子商务系统研发——商品数据模型设计