My obj format here is not the intermediate file produced by C + + code, but that g what wave company obj format, the format is very simple, the function is to take to store some basic information of the 3D model. Used to be easy to read under the VS2005, this time for Qt, fortunately, QT company to the customer very attentively and responsible, in its qtlab found a good class and code. be used to successfully import obj~
Cut to the chase.
First this class will need to refer to the file point3d.h, which reads as follows:
#ifndef Point3d_h
#define Point3d_h
#include "math.h"
#include <qglobal.h>
struct POINT3D
{
float x, y, Z;
Point3D ()
: X (0)
, y (0)
, Z (0)
{
}
Point3D (float x_, float y_, float z_)
: X (X_)
, Y (Y_)
, Z (z_)
{
}
Point3D operator+ (const Point3D &p) const
{
Return Point3D (*this) + = p;
}
Point3D operator-(const Point3D &p) const
{
Return Point3D (*this)-= p;
}
Point3D operator* (float f) const
{
Return Point3D (*this) *= F;
}
Point3D &operator+= (const Point3D &p)
{
x + = p.x;
Y + = p.y;
z + = p.z;
return *this;
}
Point3D &operator-= (const Point3D &p)
{
X-= p.x;
Y-= p.y;
Z-= p.z;
return *this;
}
BOOL operator== (const Point3D &p)
{
if ((x==p.x) && (y==p.y) && (z==p.z))
return true;
return false;
}
Point3D &operator*= (float f)
{
x *= F;
Y *= F;
Z *= F;
return *this;
}
Point3D normalize () const
{
float R = 1. /sqrt (x * x + y * y + z * z);
return Point3D (x * r, y * r, Z * r);
}
Float &operator[] (unsigned int index) {
Q_assert (Index < 3);
return (&X) [index];
}
Const FLOAT &operator[] (unsigned int index) const {
Q_assert (Index < 3);
return (&X) [index];
}
};
inline float dot (const Point3D &a, const Point3D &b)
{
Return a.x * b.x + a.y * b.y + a.z * B.Z;
}
Inline Point3D Cross (const Point3D &a, const Point3D &b)
{
Return Point3D (A.Y * b.z–a.z * b.y,
A.Z * b.x–a.x * b.z,
a.x * B.Y–A.Y * b.x);
}
#endif
Then there is the content of Model.h:
#ifndef Model_h
#define Model_h
#include <QString>
#include <QVector>
#include <math.h>
#include "Point3d.h"
Class Model
{
Public
Model () {}
Model (const QString &filepath);
Draw a model
void Render (bool wireframe = FALSE, bool Normals = false) const;
QString FileName () const {return m_filename;}
int faces () const {return m_pointindices.size ()/3;}
int edges () const {return m_edgeindices.size ()/2;}
int points () const {return m_points.size ();}
Private
QString m_filename;//file name
qvector<point3d> m_points;//Vertex Information
qvector<point3d> m_normals;//Vector Information
Qvector<int> m_edgeindices;//Edge Index
qvector<int> m_pointindices;//Point Index
};
#endif
Finally, the content of Model.cpp:
#include "model.h"
#include <QFile>
#include <QTextStream>
#include <QVarLengthArray>
#include <QtOpenGL>
Model::model (const QString &filepath)
: M_filename (Qfileinfo (FilePath). FileName ())
{
QFile file (FilePath);
if (!file.open (qiodevice::readonly))
Return
Point3D boundsmin (1e9, 1e9, 1e9);
Point3D Boundsmax ( -1E9,-1E9,-1E9);
Qtextstream in (&file);
while (!in.atend ()) {
QString input = In.readline ();
if (Input.isempty () | | input[0] = = ' # ')
Continue
Qtextstream ts (&input);
QString ID;
TS >> ID;
if (id = = "V") {
Point3D p;
for (int i = 0; i < 3; ++i) {
TS >> P[i];
Boundsmin[i] = Qmin (Boundsmin[i], p[i]);
Boundsmax[i] = QMax (Boundsmax[i], p[i]);
}
M_points << p;
} else if (id = = "F" | | id = = "fo") {
Qvarlengtharray<int, 4> p;
while (!ts.atend ()) {
QString Vertex;
TS >> vertex;
const int vertexindex = Vertex.split ('/'). Value (0). ToInt ();
if (Vertexindex)
P.append (Vertexindex > 0 vertexindex–1:m_points.size () + Vertexindex);
}
for (int i = 0; i < p.size (); ++i) {
const int EDGEA = P[i];
const int EDGEB = p[(i + 1)% p.size ()];
if (Edgea < EDGEB)
M_edgeindices << Edgea << Edgeb;
}
for (int i = 0; i < 3; ++i)
M_pointindices << P[i];
if (p.size () = = 4)
for (int i = 0; i < 3; ++i)
M_pointindices << p[(i + 2)% 4];
}
}
Const Point3D bounds = boundsmax–boundsmin;
Const Qreal scale = 1/qmax (Bounds.x, QMax (Bounds.y, bounds.z));
for (int i = 0; i < m_points.size (); ++i)
M_points[i] = (m_points[i]– (boundsmin + bounds * 0.5)) * scale;
M_normals.resize (M_points.size ());
for (int i = 0; i < m_pointindices.size (); i + = 3) {
Const Point3D A = m_points.at (m_pointindices.at (i));
Const Point3D B = m_points.at (m_pointindices.at (i+1));
Const Point3D c = m_points.at (m_pointindices.at (i+2));
Const Point3D Normal = Cross (B–a, c–a). Normalize ();
for (int j = 0; j < 3; ++j)
m_normals[m_pointindices.at (i + j)] + = normal;
}
for (int i = 0; i < m_normals.size (); ++i)
M_normals[i] = M_normals[i].normalize ();
}
void Model::render (bool wireframe, bool normals) const
{
glenable (gl_depth_test);
glenableclientstate (Gl_vertex_array);
if (wireframe) {
glvertexpointer (3, gl_float, 0 , (float *) m_points.data ());
gldrawelements (Gl_lines, M_edgeindices.size (), Gl_unsigned_int, m_ Edgeindices.data ());
} else {
glenable (gl_lighting);
glenable (GL_LIGHT0);
glenable (gl_color_material);
Glshademodel (gl_smooth);
Glenableclientstate (Gl_normal_array);
Glvertexpointer (3, gl_float, 0, (FLOAT *) m_points.data ());
Glnormalpointer (gl_float, 0, (FLOAT *) m_normals.data ());
Gldrawelements (Gl_triangles, M_pointindices.size (), Gl_unsigned_int, M_pointindices.data ());
Gldisableclientstate (Gl_normal_array);
Gldisable (gl_color_material);
Gldisable (GL_LIGHT0);
Gldisable (gl_lighting);
}
if (normals) {
Qvector<point3d> normals;
for (int i = 0; i < m_normals.size (); ++i)
Normals << m_points.at (i) << (m_points.at (i) + m_normals.at (i) * 0.02f);
Glvertexpointer (3, gl_float, 0, (FLOAT *) normals.data ());
Gldrawarrays (gl_lines, 0, Normals.size ());
}
Gldisableclientstate (Gl_vertex_array);
Gldisable (gl_depth_test);
}
In the place where the external obj model needs to be called, declare an object of that class, enter the URI of the model in the constructor, and then call the Render function OK. Oh, the package is very thorough and powerful, I wish you success.
If there is anything wrong in the article, please point out that it is also convenient for those who see it later to take less detours.
If there is content in the article to help you, but also hope that can not be stingy time to leave words, as my motivation, hehe ~.
Beyond C + + original articles, reproduced please indicate the source and keep the original link
This article link: http://www.beyondc.cn/obj-model-under-the-load-qt.html