2
* Stellarium Scenery3d Plug-in
4
* Copyright (C) 2011 Simon Parzer, Peter Neubauer, Georg Zotti, Andrei Borza
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
/** OBJ loader based on dhpoware's glObjViewer (http://www.dhpoware.com/demos/glObjViewer.html) See license below **/
23
//-----------------------------------------------------------------------------
24
// Copyright (c) 2007 dhpoware. All Rights Reserved.
26
// Permission is hereby granted, free of charge, to any person obtaining a
27
// copy of this software and associated documentation files (the "Software"),
28
// to deal in the Software without restriction, including without limitation
29
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
30
// and/or sell copies of the Software, and to permit persons to whom the
31
// Software is furnished to do so, subject to the following conditions:
33
// The above copyright notice and this permission notice shall be included in
34
// all copies or substantial portions of the Software.
36
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
37
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
41
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
43
//-----------------------------------------------------------------------------
49
#include <QOpenGLBuffer>
50
#include <QOpenGLVertexArrayObject>
52
#include "StelTexture.hpp"
53
#include "VecMath.hpp"
58
//! A basic Wavefront .OBJ format model loader.
60
//! FS: The internal loader still is not very robust, uses many C IO functions (fopen,fscanf...)
61
//! and will have serious problems handling a malformed file including many potential buffer overflows.
62
//! Meaning: **Do NOT use for untrusted, downloaded files!**
66
//! OBJ files can have vertices encoded in different order.
67
//! Only XYZ and XZY may occur in real life, but we can cope with all...
68
enum vertexOrder { XYZ, XZY, YXZ, YZX, ZXY, ZYX };
70
//! Encapsulates all information that the describes the surface appearance of a StelModel
73
//! MTL Illumination models, do not use externally anymore. See the developer doc for info.
74
//! @deprecated This is from the old illum model, do not consider this outside this class!
75
enum Illum { I_NONE=-1, I_DIFFUSE=0, I_DIFFUSE_AND_AMBIENT=1, I_SPECULAR=2, I_TRANSLUCENT=9 };
78
//! Creates a material with the default values
98
hasSpecularity = false;
99
hasTransparency = false;
102
//! Needs to be called after everything is loaded
112
//! Shininess [0..128]
114
//! Transparency [0..1]
116
//! If to perform binary alpha testing. Default off.
118
//! If to perform backface culling. Default on.
120
//! Quick check if this material has specularity
122
//! Quick check if this material has "real" transparency (i.e. needs blending)
123
bool hasTransparency;
127
//!< Shared pointer to texture of the model. This can be null.
128
StelTextureSP texture;
131
//!< Shared pointer to bump map texture of the model. This can be null.
132
StelTextureSP bump_texture;
134
QString heightMapName;
135
//!< Shared pointer to height map texture of the model. This can be null.
136
StelTextureSP height_texture;
137
//! Name of emissive texture
138
QString emissiveMapName;
139
//!< Shared pointer to emissive texture of the model. This can be null.
140
StelTextureSP emissive_texture;
144
//! A vertex struct holds the vertex itself (position), corresponding texture coordinates, normals, tangents and bitangents
145
//! It does not use Vec3f etc. to be POD compliant (needed for offsetof in some compilers)
152
GLfloat bitangent[3];
154
static const Vertex EmptyVertex;
157
//! Structure for a Mesh, will be used with Stellarium to render
158
//! Holds the starting index, the number of triangles and a pointer to the MTL
161
int startIndex, triangleCount;
162
//materials are managed by OBJ
163
const Material* pMaterial;
164
//AABB is managed by this
166
//The centroid location of all vertices of this model
170
//! Initializes values
175
//! Cleanup, will be called inside the destructor
177
//! Loads the given obj file and, if specified rebuilds normals
178
bool load(const QString& filename, const enum vertexOrder order, bool rebuildNormals = false);
179
//! Transform all the vertices through multiplication with a 4x4 matrix.
180
//! @param mat Matrix to multiply vertices with.
181
void transform(QMatrix4x4 mat);
182
//! Returns a Material
183
Material &getMaterial(int i);
184
//! Returns a StelModel
185
const StelModel& getStelModel(int i) const;
187
//! This should be called after textures are loaded, and will re-order the StelModels to be grouped by their material.
188
//! Furthermore, this is a prerequisite for transparencyDepthSort.
189
void finalizeForRendering();
191
//! Sorts the transparent StelModels according to their distance to the specified position.
192
//! They are sorted so that they can be drawn back-to-front.
193
void transparencyDepthSort(const Vec3f& position);
195
//! Getters for various datastructures
196
int getNumberOfIndices() const;
197
int getNumberOfStelModels() const;
198
int getNumberOfTriangles() const;
199
int getNumberOfVertices() const;
200
int getNumberOfMaterials() const;
202
//! Returns a vertex reference
203
const Vertex& getVertex(int i) const;
204
//! Returns the vertex array
205
const Vertex* getVertexArray() const;
206
//! Returns the vertex size
207
int getVertexSize() const;
210
bool isLoaded() const;
211
bool hasPositions() const;
212
bool hasTextureCoords() const;
213
bool hasNormals() const;
214
bool hasTangents() const;
215
bool hasStelModels() const;
217
//! Returns the bounding box for this OBJ
218
//const BoundingBox* getBoundingBox() const;
219
const AABB& getBoundingBox();
223
//! Returns an estimate of the memory usage of this instance (not fully accurate, but good enough)
224
size_t memoryUsage();
226
//! Uploads the textures to GL (requires valid context)
227
void uploadTexturesGL();
228
//! Uploads the vertex and index data to GL buffers (requires valid context)
229
void uploadBuffersGL();
231
//! Binds the necessary GL objects, making the OBJ ready for drawing. Uses a VAO if the platform supports it.
233
//! Unbinds this object's GL objects
236
//! Set up some stuff that requires a valid OpenGL context.
237
static void setupGL();
238
//! Returns the OpenGL index buffer type supported on this hardware.
239
//! OpenGL ES may not support integer indices, so this is necessary.
240
static inline GLenum getIndexBufferType() { return indexBufferType; }
241
static inline size_t getIndexBufferTypeSize() { return indexBufferTypeSize; }
243
//! Copy assignment operator. No deep copies are performed, but QVectors have copy-on-write semantics, so this is no problem. Does not copy GL objects.
244
OBJ& operator=(const OBJ& other);
246
struct FaceAttributes
252
typedef QVector<FaceAttributes> AttributeVector;
253
typedef QVector<Vec3f> VF3Vector;
254
typedef QVector<Vec2f> VF2Vector;
256
typedef QVector<Vec3f> PosVector;
257
typedef QMap<QString,int> MatCacheT;
258
typedef QMap<int, QVector<int> > VertCacheT;
260
void addFaceAttrib(AttributeVector& attributeArray, uint index, int material, int object);
261
void addTrianglePos(const PosVector& vertexCoords, VertCacheT &vertexCache, unsigned int index, int v0, int v1, int v2);
262
void addTrianglePosNormal(const PosVector &vertexCoords, const VF3Vector& normals, VertCacheT &vertexCache, unsigned int index,
263
int v0, int v1, int v2,
264
int vn0, int vn1, int vn2);
265
void addTrianglePosTexCoord(const PosVector &vertexCoords, const VF2Vector &textureCoords, VertCacheT &vertexCache, unsigned int index,
266
int v0, int v1, int v2,
267
int vt0, int vt1, int vt2);
268
void addTrianglePosTexCoordNormal(PosVector &vertexCoords, const VF2Vector &textureCoords, const VF3Vector &normals, VertCacheT &vertexCache, unsigned int index,
269
int v0, int v1, int v2,
270
int vt0, int vt1, int vt2,
271
int vn0, int vn1, int vn2);
272
int addVertex(VertCacheT &vertexCache, int hash, const Vertex* pVertex);
273
//! Builds the StelModels based on material
274
void buildStelModels(const AttributeVector &attributeArray);
275
//! Generates normals in case they aren't specified/need rebuild
276
void generateNormals();
277
//! Generates tangents (and bitangents/binormals) (useful for NormalMapping, Parallax Mapping, ...)
278
void generateTangents();
279
//! First pass - scans the file for memory allocation
280
void importFirstPass(QFile& pFile, MatCacheT &materialCache);
281
//! Second pass - actual parsing step
282
void importSecondPass(FILE *pFile, const enum vertexOrder order, const MatCacheT &materialCache);
283
//! Imports material file and fills the material datastructure
284
bool importMaterials(const QString& filename, MatCacheT& materialCache);
285
QString absolutePath(QString path);
286
//! Determine the bounding box extrema
288
//! Binds the GL buffers to the vertex attributes
289
void bindBuffersGL();
290
//! Releases vertex attribute bindings and buffers
291
void unbindBuffersGL();
293
//! Returns the file for this filename, handling decompression if necessary
294
QFile* getFile(const QString& filename);
296
//! Used for parsing a texture string
297
QString parseTextureString(const char *buffer) const;
302
bool m_hasTextureCoords;
305
bool m_hasStelModels;
306
static bool vertexArraysSupported;
308
//! The type of the index buffer, may be GL_UNSIGNED_INT or GL_UNSIGNED_SHORT (on ES where GL_OES_element_index_uint is unsupported)
309
static GLenum indexBufferType;
310
//! The sizeof() of the indexBufferType
311
static size_t indexBufferTypeSize;
312
int m_firstTransparentIndex;
315
unsigned int m_numberOfVertexCoords;
316
unsigned int m_numberOfTextureCoords;
317
unsigned int m_numberOfNormals;
318
unsigned int m_numberOfTriangles;
319
unsigned int m_numberOfMaterials;
320
unsigned int m_numberOfStelModels;
322
//! Bounding box for the entire scene
325
//! Base path to this file
329
QVector<StelModel> m_stelModels;
330
QVector<Material> m_materials;
331
QVector<Vertex> m_vertexArray;
332
QVector<unsigned int> m_indexArray;
335
QOpenGLBuffer m_vertexBuffer;
336
QOpenGLBuffer m_indexBuffer;
337
QOpenGLVertexArrayObject* m_vertexArrayObject;
339
static QOpenGLFunctions* gl;
342
friend class Heightmap;
345
inline OBJ::Material& OBJ::getMaterial(int i) { return m_materials[i]; }
347
inline const OBJ::StelModel& OBJ::getStelModel(int i) const { return m_stelModels[i]; }
349
inline int OBJ::getNumberOfIndices() const { return m_numberOfTriangles * 3; }
351
inline int OBJ::getNumberOfStelModels() const { return m_numberOfStelModels; }
353
inline int OBJ::getNumberOfTriangles() const { return m_numberOfTriangles; }
355
inline int OBJ::getNumberOfVertices() const { return static_cast<int>(m_vertexArray.size()); }
357
inline int OBJ::getNumberOfMaterials() const {return m_numberOfMaterials; }
359
inline const OBJ::Vertex& OBJ::getVertex(int i) const { return m_vertexArray[i]; }
361
inline const OBJ::Vertex* OBJ::getVertexArray() const { return &m_vertexArray[0]; }
363
inline int OBJ::getVertexSize() const { return static_cast<int>(sizeof(Vertex)); }
365
inline bool OBJ::isLoaded() const{ return m_loaded; }
367
inline bool OBJ::hasNormals() const{ return m_hasNormals; }
369
inline bool OBJ::hasPositions() const { return m_hasPositions; }
371
inline bool OBJ::hasTangents() const { return m_hasTangents; }
373
inline bool OBJ::hasTextureCoords() const { return m_hasTextureCoords; }
375
inline bool OBJ::hasStelModels() const { return m_hasStelModels; }
377
//inline const OBJ::BoundingBox* OBJ::getBoundingBox() const { return pBoundingBox; }
378
inline const AABB &OBJ::getBoundingBox() {return pBoundingBox; }
380
inline QString OBJ::absolutePath(QString path) { return m_basePath + path; }