织梦CMS - 轻松建站从此开始!

罗索

Qt下学习OpenGL之OBJ模型

落鹤生 发布于 2012-06-07 09:41 点击:次 
我这里的OBJ格式不是c++代码产生的中间文件,而是那个g什么wave公司的OBJ格式,格式很简单,作用就是拿来存储3D模型的一些基本信息。以前在VS2005下能很轻松读取,这次换QT了,幸好QT公司对客户很用心和负责,在其QtLab下发现了不错的类和代码。加以运用,成功导入 OBJ~
TAG:

我这里的OBJ格式不是c++代码产生的中间文件,而是那个g什么wave公司的OBJ格式,格式很简单,作用就是拿来存储3D模型的一些基本信 息。以前在VS2005下能很轻松读取,这次换QT了,幸好QT公司对客户很用心和负责,在其QtLab下发现了不错的类和代码。加以运用,成功导入 OBJ~

切入正题。
首先这个类会需要引用该文件point3d.h,其内容如下:

  1. #ifndef POINT3D_H 
  2. #define POINT3D_H 
  3.  
  4. #include “math.h” 
  5.  
  6. #include <qglobal.h> 
  7.  
  8. struct Point3d 
  9.     float x, y, z; 
  10.  
  11.     Point3d() 
  12.         : x(0) 
  13.         , y(0) 
  14.         , z(0) 
  15.     { 
  16.     } 
  17.  
  18.     Point3d(float x_, float y_, float z_) 
  19.         : x(x_) 
  20.         , y(y_) 
  21.         , z(z_) 
  22.     { 
  23.     } 
  24.  
  25.     Point3d operator+(const Point3d &p) const 
  26.     { 
  27.         return Point3d(*this) += p; 
  28.     } 
  29.  
  30.     Point3d operator-(const Point3d &p) const 
  31.     { 
  32.         return Point3d(*this) -= p; 
  33.     } 
  34.  
  35.     Point3d operator*(float f) const 
  36.     { 
  37.         return Point3d(*this) *= f; 
  38.     } 
  39.     Point3d &operator+=(const Point3d &p) 
  40.     { 
  41.         x += p.x; 
  42.         y += p.y; 
  43.         z += p.z; 
  44.         return *this
  45.     } 
  46.  
  47.     Point3d &operator-=(const Point3d &p) 
  48.     { 
  49.         x -= p.x; 
  50.         y -= p.y; 
  51.         z -= p.z; 
  52.         return *this
  53.     } 
  54.  
  55.     bool operator==(const Point3d &p) 
  56.     { 
  57.         if((x==p.x)&&(y==p.y)&&(z==p.z)) 
  58.             return true
  59.         return false
  60.     } 
  61.  
  62.     Point3d &operator*=(float f) 
  63.     { 
  64.         x *= f; 
  65.         y *= f; 
  66.         z *= f; 
  67.         return *this
  68.     } 
  69.  
  70.     Point3d normalize() const 
  71.     { 
  72.         float r = 1. / sqrt(x * x + y * y + z * z); 
  73.         return Point3d(x * r, y * r, z * r); 
  74.     } 
  75.     float &operator[](unsigned int index) { 
  76.         Q_ASSERT(index < 3); 
  77.         return (&x)[index]; 
  78.     } 
  79.  
  80.     const float &operator[](unsigned int index) const { 
  81.         Q_ASSERT(index < 3); 
  82.         return (&x)[index]; 
  83.     } 
  84. }; 
  85.  
  86. inline float dot(const Point3d &a, const Point3d &b) 
  87.     return a.x * b.x + a.y * b.y + a.z * b.z; 
  88.  
  89. inline Point3d cross(const Point3d &a, const Point3d &b) 
  90.     return Point3d(a.y * b.z – a.z * b.y, 
  91.                    a.z * b.x – a.x * b.z, 
  92.                    a.x * b.y – a.y * b.x); 
  93.  
  94. #endif 

然后是Model.h的内容:

  1. #ifndef MODEL_H 
  2. #define MODEL_H 
  3.  
  4. #include <QString> 
  5. #include <QVector> 
  6.  
  7. #include <math.h> 
  8.  
  9. #include “point3d.h” 
  10.  
  11. class Model 
  12. public
  13.     Model() {} 
  14.     Model(const QString &filePath); 
  15.  
  16.     //画出模型 
  17.     void render(bool wireframe = falsebool normals = falseconst
  18.  
  19.     QString fileName() const { return m_fileName; } 
  20.     int faces() const { return m_pointIndices.size() / 3; } 
  21.     int edges() const { return m_edgeIndices.size() / 2; } 
  22.     int points() const { return m_points.size(); } 
  23.  
  24. private
  25.     QString m_fileName;//文件名 
  26.     QVector<Point3d> m_points;//顶点信息 
  27.     QVector<Point3d> m_normals;//向量信息 
  28.     QVector<int> m_edgeIndices;//边索引 
  29.     QVector<int> m_pointIndices;//点索引 
  30. }; 
  31.  
  32. #endif 

最后是Model.cpp的内容:

  1. #include “model.h” 
  2.  
  3. #include <QFile> 
  4. #include <QTextStream> 
  5. #include <QVarLengthArray> 
  6.  
  7. #include <QtOpenGL> 
  8.  
  9. Model::Model(const QString &filePath) 
  10.     : m_fileName(QFileInfo(filePath).fileName()) 
  11.     QFile file(filePath); 
  12.     if (!file.open(QIODevice::ReadOnly)) 
  13.         return
  14.  
  15.     Point3d boundsMin( 1e9, 1e9, 1e9); 
  16.     Point3d boundsMax(-1e9,-1e9,-1e9); 
  17.  
  18.     QTextStream in(&file); 
  19.     while (!in.atEnd()) { 
  20.         QString input = in.readLine(); 
  21.         if (input.isEmpty() || input[0] == ‘#’) 
  22.             continue
  23.  
  24.         QTextStream ts(&input); 
  25.         QString id; 
  26.         ts >> id; 
  27.         if (id == “v”) { 
  28.             Point3d p; 
  29.             for (int i = 0; i < 3; ++i) { 
  30.                 ts >> p[i]; 
  31.                 boundsMin[i] = qMin(boundsMin[i], p[i]); 
  32.                 boundsMax[i] = qMax(boundsMax[i], p[i]); 
  33.             } 
  34.             m_points << p; 
  35.         } else if (id == “f” || id == “fo”) { 
  36.             QVarLengthArray<int, 4> p; 
  37.  
  38.             while (!ts.atEnd()) { 
  39.                 QString vertex; 
  40.                 ts >> vertex; 
  41.                 const int vertexIndex = vertex.split(‘/’).value(0).toInt(); 
  42.                 if (vertexIndex) 
  43. p.append(vertexIndex > 0 ? vertexIndex – 1 : m_points.size() + vertexIndex); 
  44.             } 
  45.  
  46.             for (int i = 0; i < p.size(); ++i) { 
  47.                 const int edgeA = p[i]; 
  48.                 const int edgeB = p[(i + 1) % p.size()]; 
  49.  
  50.                 if (edgeA < edgeB) 
  51.                     m_edgeIndices << edgeA << edgeB; 
  52.             } 
  53.  
  54.             for (int i = 0; i < 3; ++i) 
  55.                 m_pointIndices << p[i]; 
  56.  
  57.             if (p.size() == 4) 
  58.                 for (int i = 0; i < 3; ++i) 
  59.                     m_pointIndices << p[(i + 2) % 4]; 
  60.         } 
  61.     } 
  62.  
  63.     const Point3d bounds = boundsMax – boundsMin; 
  64.     const qreal scale = 1 / qMax(bounds.x, qMax(bounds.y, bounds.z)); 
  65.     for (int i = 0; i < m_points.size(); ++i) 
  66.         m_points[i] = (m_points[i] – (boundsMin + bounds * 0.5)) * scale; 
  67.  
  68.     m_normals.resize(m_points.size()); 
  69.     for (int i = 0; i < m_pointIndices.size(); i += 3) { 
  70.         const Point3d a = m_points.at(m_pointIndices.at(i)); 
  71.         const Point3d b = m_points.at(m_pointIndices.at(i+1)); 
  72.         const Point3d c = m_points.at(m_pointIndices.at(i+2)); 
  73.  
  74.         const Point3d normal = cross(b – a, c – a).normalize(); 
  75.  
  76.         for (int j = 0; j < 3; ++j) 
  77.             m_normals[m_pointIndices.at(i + j)] += normal; 
  78.     } 
  79.  
  80.     for (int i = 0; i < m_normals.size(); ++i) 
  81.         m_normals[i] = m_normals[i].normalize(); 
  82.  
  83. void Model::render(bool wireframe, bool normals) const 
  84.     glEnable(GL_DEPTH_TEST); 
  85.     glEnableClientState(GL_VERTEX_ARRAY); 
  86.     if (wireframe) { 
  87.         glVertexPointer(3, GL_FLOAT, 0, (float *)m_points.data()); 
  88.         glDrawElements(GL_LINES, m_edgeIndices.size()
  89. , GL_UNSIGNED_INT, m_edgeIndices.data()); 
  90.     } else { 
  91.         glEnable(GL_LIGHTING); 
  92.         glEnable(GL_LIGHT0); 
  93.         glEnable(GL_COLOR_MATERIAL); 
  94.         glShadeModel(GL_SMOOTH); 
  95.  
  96.         glEnableClientState(GL_NORMAL_ARRAY); 
  97.         glVertexPointer(3, GL_FLOAT, 0, (float *)m_points.data()); 
  98.         glNormalPointer(GL_FLOAT, 0, (float *)m_normals.data()); 
  99.         glDrawElements(GL_TRIANGLES, m_pointIndices.size()
  100. , GL_UNSIGNED_INT, m_pointIndices.data()); 
  101.  
  102.         glDisableClientState(GL_NORMAL_ARRAY); 
  103.         glDisable(GL_COLOR_MATERIAL); 
  104.         glDisable(GL_LIGHT0); 
  105.         glDisable(GL_LIGHTING); 
  106.     } 
  107.  
  108.     if (normals) { 
  109.         QVector<Point3d> normals; 
  110.         for (int i = 0; i < m_normals.size(); ++i) 
  111. normals << m_points.at(i) << (m_points.at(i) + m_normals.at(i) * 0.02f); 
  112.         glVertexPointer(3, GL_FLOAT, 0, (float *)normals.data()); 
  113.         glDrawArrays(GL_LINES, 0, normals.size()); 
  114.     } 
  115.     glDisableClientState(GL_VERTEX_ARRAY); 
  116.     glDisable(GL_DEPTH_TEST); 

在需要调用外部OBJ模型的地方,声明一个该类的对象,在构造函数里输入模型的uri,然后调用render函数就ok了。呵呵,封装得很彻底很强大,祝你成功。

如果文章中有什么错误的地方,请指出也方便以后看到该日志的人能少走弯路。

如果文章中有内容帮助了你,也希望可以不吝啬点时间留下言,作为我的动力,呵呵~。

(民警小刘)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201206/16069.html]
本文出处:liusir 作者:民警小刘 原文
顶一下
(8)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容