OpenGL系统设计-高级3D模型接口之OBJ模型(2)

<!-- /* 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 模型在 很多程序中都作为例子使用。

 


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值