Opengl中导入obj文件

来源:互联网 发布:程序员买什么显示器 编辑:程序博客网 时间:2024/06/10 07:46

首先,我们需要知道obj文件格式是什么样的,他的内部是如何储存模型的.利用ultra edit打开bunny.obj文件观察可以看到如下数据:

我们猜想,这应该是顶点数据组,拖动滚动条后看到出现了左图的数据.

 

¨分析这些数据,不难猜想obj文件由若干行组成,每行开始有一个字母,用来标注改行数据所表示的意思,v 应该是顶点,g应该是一个名字,观察到,f后紧跟着三个整数,opengl中的顶点数组得到,他应该是三角行的三个顶点,后面的三个整数就代表着前端顶点的索引值.
¨好知道了数据结构,就可以提取分析obj文件啦~(整个过程远比我想象的顺利啊~哈哈)
 
,现在我们就来进行编码工作啦~
第一步当然是要定义一个与文件相对应的数据结构啦~我们把它命名为obj3dmodel并有如下头文件结构:
class obj3dmodel
{
      struct vertex{
            double x;
            double y;
            double z;
      };
      struct face{
            unsigned int v1,v2,v3;
      };
      std::vector<vertex> vetexes;
      std::vector<face> faces;
     
   
public:
      void parse(const char* filename);
      void draw();
      obj3dmodel(void);
      ~obj3dmodel(void);
};
 ¨这里,我们定义两个结构体来表示顶点和三角形,并采用vector容器来保存数据组.
¨之所以把两个结构体定义在类的内部,一个是不想污染源代码,另一个是暂时还没有想到会在别的什么地方会用到他们.所以暂且把他们藏起来~省着不好管理~
¨我们同时为他定义了parsedraw方法,分别用来从文件中解析数据和利用opengl绘制
 
定义好数据结构后,就可以着手parse代码的实现啦~
void obj3dmodel::parse(const char *filename)
{
      string s;
      ifstream fin(filename);
      if(!fin)
            return;
      while(fin>>s)
      {
            switch(*s.c_str())
            {
            case 'v':
                  {
                        vertex v;
                        fin>>v.x>>v.y>>v.z;
                        this->vetexes.push_back(v);
                  }
                  break;
            //这里我们暂时不需要名字,直接忽略掉它
            case 'g':
                  break;
            case 'f':
                  {
                        face f;
                        fin>>f.v1>>f.v2>>f.v3;
                        faces.push_back(f);
                  }
                  break;
            }
      }     
}
 紧接着,定义draw的方法,比较简单啦~不过注意顶点索引
方式,obj里面是以1为基数的,所以在索引时要将索引值减1.
则会报越界.
void obj3dmodel::draw()
{
  glBegin(GL_TRIANGLES);
  for(int i=0;i<faces.size();i++)
  {
                         //索引要减去1
  vertex v1= vetexes[faces[i].v1-1];
  vertex v2=vetexes[faces[i].v2-1];
  vertex v3=vetexes[faces[i].v3-1];
  glVertex3f(v1.x,v1.y,v1.z);
  glVertex3f(v2.x,v2.y,v2.z);
  glVertex3f(v3.x,v3.y,v3.z);
  }
  glEnd();
}
 ¨新增数据类型,ply文件的导入
¨从网上下载了个3d模型用来做网格参数化,无奈文件是个.ply的文件,无奈没见过.依然用上述方法用ultra edit打开发现文件格式也是很好猜的.依然可以按照文件格式写代码来解析.
 ¨为使代码便于管理和将来的扩展考虑,我们抽象出一个modelbase,用来表示任何文件格式的模型:
¨并将parsedraw方法

设置为虚,这样就可以在应

用时统一用modelbase

口来访问特定的类型了