在OpenGL中渲染3DMAX模型

1、前言

  OpenGL是一个硬件和图形软件接口,由于它在三维真实感图形制作中性能优秀,诸如MicrosoftSGIIBMDEC SUN等计算机主导公司都采用了OpenGL标准,OpenGL已经成为事实上的高性能和交互式视景标准。Microsoft 公司在Window95/NT操作系统中支持OpenGL前,只有在昂贵的图形工作站上才能运行OpenGL程序,随着支持OpenGL图形加速卡的出现和PC机性能的提高,OpenGLPC机上得到广泛的应用。OpenGL中很容易实现模型的各种变换、着色、光照、纹理、交互操作和动画,但是它只能提供基本几何元素的造型函数,使得复杂模型的建模相对困难。3DMAXKinetix公司的三维图形建模和动画软件,能方便建立各种复杂物体模型,但是很难进行程序控制。因此,我们自然想到在3DMAX中建立好复杂模型后,在OpenGL中实现对其方便控制和变换。

    2OpenGL的基本操作
  
    1
)物体的绘制:通过点、线、多边形实现。
  
    2
)变换:投影变换、几何变换、裁剪变换、视口变换。
  
    3
)着色:OpenGL提供RGBA模式和颜色索引模式,提供224种颜色。
  
    4
)纹理映射:在具体模型表面加上现实世界中物体的纹理,可使三维模型更生动。
  
    5
)交互操作和动画:OpenGL辅助函数库提供了消息响应函数,可以较方便的实现交互程序控制。
  
    6
)其它:光照、反走样、混合、雾化等功能。

    33DMAX ASE模型描述及OpenGL控制

  3.1 C语言数据结构描述3DMAX模型

  在3DMAX中建立好模型后,仅以三角形网格方式存为ASE文件(ASCII文件),在程序中我们需建立对应的模型数据结构,本文以C语言数据结构为例。 例子ASE文件包含简单的一个金字塔和球体,具体内容如下(略去头部):

  *GEOMOBJECT
  
{
    // 单个物体模型的开头

    *NODENAME "Pyramid01"  // 物体名称
    ... ...
    
*MESH
    {
      // 网格

      *TIMEVALUE    0
      *MESHNUMVERTEX  6  // 物体的顶点数

      *MESHNUMFACES   8  // 物体的三角形面数
      *MESHVERTEXLIST
      
{
        *MESHVERTEX00.00000.000030.0000  // 顶点坐标

        ... ...
        
*MESHVERTEX50.00000.00000.0000
      
}
      
*MESHFACELIST
      
{
        // 面号和构成面的顶点

        *MESHFACE0:A:0 B:1 C:2 AB:1 BC:1 CA:0
        
... ...
        
*MESHFACE7:A:4 B:5 C:1 AB:0 BC:1 CA:1
      
}
    
}
    
... ...
  }

  *GEOMOBJECT
  
{
    // 格式同上个物体

    *NODENAME "Sphere01"
    
... ...
  }

  分析上面的ASE文件结构,可得到通用的对应ASE文件的C模型数据结构如下。
  点的定义:

  typedef struct PointType
  
{
    
double x,x,y;
  }POINTTYPE;

  三角形面的定义:

  typedef struct FaceType
  
{
    
int a,b,c;
  }FACETYPE;

  单个物体的定义:

  typedef struct ObjectType
  
{
    int VertexNum;      // 点的个数

    POINTTYPE *PointList;  // 点列表
    int FaceNum;       // 面的个数
    FACETYPE *FaceList;   // 面列表
    OBJECTTYPE *Next;    // 指向下一物体的指针
  }OBJECTTYPE;

  多个物体:

  typedef struct ObjectsHead
  
{
    int ObjectNum;       // 物体的个数

    OBJECTTYPE *ObjectList;  // 物体的列表
  }OBJECTSHEAD;

3.2 读入3DMAX物体数据以OpenGL实现动画

    ASE文件导入物体数据:

  int GetObjects(char *FileName,OBJECTSHEAD *Objects)  // 从文件中读入到Objects
  {
    FILE fp;      // 文件指针

    char line[200];  // 存储文件中一行的数据
    OBJECTTYPE *p,q;
    
POINTTYPE tempoint;
    FACETYPE tempface;

    if (fp=open(FileName,"r")<=0)
      then return -1;  // 读文件失败

    Objects->ObjectList=NULL;
    Objects->ObjectNum=0;

    while(not eof(fp))
    
{
      getlint(fp,line); // 从文件中读入一行到Line;自定义函数
;
      
if(JudgeIn(line,"GEOMOBJECT"))
      
{
        // 物体定义的头部

        q=malloc sizeof(OBJECTTYPE); // 为物体分配空间
        q->Next:=NULL;
        if (Objects
ObjectList=NULL)
          
p=ObjectList=q;
        
else
        
{
          
p->Next:=q;
          p=p
Next;
        
}
        
++Objects->ObjectNum;
      
}
      
if (JudgeIn(line,"*MESHNUMVERTEX"))
      
{
        q->VertexNum=GetVertexNum(line);  // 读入点数

        q->PointList=(POINTTYPE *) malloc(sizeof(POINTTYPE)*qVertexNum);
      
}
      
if (JudgeIn(line,"*MESHNUMFACES") )
      
{
        q->FaceNum=GetFaceNum(line);  // 读入面数

        q->FaceList=(FACETYPE *) malloc(sizeof(FACETYPE)*q->FaceNum);
      
}
      
if (JudgeIn(line," *MESHVERTEX"))
      
{
        GetPoint(line,tempoint);  // 读入点座标

        AddPoint(q->PointList,tempoint);
      }

      // 将点加入点列表中
      if(JudgeIn(line," * MESHFACE"))
      
{
        GetFace(line,temface);  // 读入面

        AddFace(q->PointList,temface);
      } // 将面加入面列表中

    } // While语句结束

    fclose(fp);
    
return 1;
  }

  在OpenGL中实现动画控制:

  #include    // OpenGL核心库
  #include   // OpenGL实用库
  #include  // OpenGL辅助库

  OBJECTSHEAD *Objects;
  Gldouble rx="0",ry=0,rz=0;  // rx,ry,rz为物体旋转的角度

  void CALLBACK myReshape(GLSize w,Glsize h)  // 窗口改变尺寸回调函数
  {
    
glViewPort(0,0,w,h);
  
}
  void CALLBACK display() // 显示物体回调函数

  {
    
int j,k;
    
OBJECTTYPE *p;
    
Delay(1000);
    
Rx=rx+0.1;
    
Ry=ry+0.1;
    Rz=rz+0.1;

    glClear(GLCOLORBUFFERBIT);  // 清除OpenGL的颜色缓冲
    glPushMatrix();
    glRotate(rx,ry,rz,0.0);    // 旋转物体

    p=Objects->ObjectList;

    for( j="1";jnum;j++)
    
{
      
for(k=1;k>p->FaceNum;k++)
      
{
        glBegin(GLTRIANGLES);  // OpenGL命令绘制三角形网格

          glVertex3f(p->PointList[(p->Face-List[i]).a], p->PointList[(p->Face-List[i]).b]);
          
glVertex3f(p->PointList[(p->Face-List[i]).b], p->PointList[(p->Face-List[i]).c]);
          
glVertex3f(p->PointList[(p->Face-List[i]).c], p->PointList[(p->Face-List[i]).a]);
        
glEnd();
      
}
      
p=p->Next;
    
}
    
glPopMatrix();
    glFlush()l;  // 与显示区交换数据

  }

  void main(void)
  
{
    auxInitDisplayMode(AUXSINGLE|AUXRGB);  // 初始化显示模式

    auxInitPosition(0,0,400,400);      // 初始化窗口位置和大小
    auInitWindow("OPENGL-3DMAX例子");    // 标题
    glClearColor(0.0,0.0,0.0,0.0);      // 清除显示区
    auxReshapeFunc(myReshape);
    
auxMainLoop(display);
  }

    4、结束语
  
   
3DMAX模型应用于OpenGL中,降低了OpenGL复杂建模的难度,我们可以得到较真实的复杂物体模型。在飞机运动模拟和远程姿态监控的具体应用中,我们在OpenGL程序中引入3DMAX飞机模型,得到了满意的三维动画效果。同样,我们还可以编制AutoCADUG等多种图形接口程序,把在AutoCADUGCAD软件中建立的物体模型引入OpenGL的应用程序中,将可应用于飞行模拟、运动虚拟仿真、商业广告、游戏制作、影视采辑等多个领域。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值