~petr-kubanek/stellarium/stellarium

« back to all changes in this revision

Viewing changes to plugins/Scenery3d/src/OBJ.hpp

  • Committer: Georg Zotti
  • Date: 2017-05-16 11:21:44 UTC
  • mfrom: (8454.1.100 SoCiS2016)
  • Revision ID: georg.zotti@univie.ac.at-20170516112144-mckvrgf8acksrghd
Merge-in SoCiS2016: Irregular solar system objects, RemoteSync plugin, Scenery3D improvements. Big merge, and raises Qt requirement to Qt5.4.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Stellarium Scenery3d Plug-in
3
 
 *
4
 
 * Copyright (C) 2011 Simon Parzer, Peter Neubauer, Georg Zotti, Andrei Borza
5
 
 *
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.
10
 
 *
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.
15
 
 *
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.
19
 
 */
20
 
 
21
 
/** OBJ loader based on dhpoware's glObjViewer (http://www.dhpoware.com/demos/glObjViewer.html) See license below **/
22
 
 
23
 
//-----------------------------------------------------------------------------
24
 
// Copyright (c) 2007 dhpoware. All Rights Reserved.
25
 
//
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:
32
 
//
33
 
// The above copyright notice and this permission notice shall be included in
34
 
// all copies or substantial portions of the Software.
35
 
//
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
42
 
// IN THE SOFTWARE.
43
 
//-----------------------------------------------------------------------------
44
 
 
45
 
#ifndef _OBJ_HPP_
46
 
#define _OBJ_HPP_
47
 
 
48
 
#include <QFile>
49
 
#include <QOpenGLBuffer>
50
 
#include <QOpenGLVertexArrayObject>
51
 
 
52
 
#include "StelTexture.hpp"
53
 
#include "VecMath.hpp"
54
 
#include "AABB.hpp"
55
 
 
56
 
class Heightmap;
57
 
 
58
 
//! A basic Wavefront .OBJ format model loader.
59
 
//!
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!**
63
 
class OBJ
64
 
{
65
 
public:
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 };
69
 
 
70
 
        //! Encapsulates all information that the describes the surface appearance of a StelModel
71
 
        struct Material
72
 
        {
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 };
76
 
                Illum illum;
77
 
 
78
 
                //! Creates a material with the default values
79
 
                Material() {
80
 
                        ambient[0] = -1.f;
81
 
                        ambient[1] = -1.f;
82
 
                        ambient[2] = -1.f;
83
 
                        diffuse[0] = 0.8f;
84
 
                        diffuse[1] = 0.8f;
85
 
                        diffuse[2] = 0.8f;
86
 
                        specular[0] = 0.0f;
87
 
                        specular[1] = 0.0f;
88
 
                        specular[2] = 0.0f;
89
 
                        emission[0] = 0.0f;
90
 
                        emission[1] = 0.0f;
91
 
                        emission[2] = 0.0f;
92
 
                        shininess = 8.0f;
93
 
                        name = "<invalid>";
94
 
                        alpha = -1.0f;
95
 
                        alphatest = false;
96
 
                        backfacecull = true;
97
 
                        illum = I_NONE;
98
 
                        hasSpecularity = false;
99
 
                        hasTransparency = false;
100
 
                }
101
 
 
102
 
                //! Needs to be called after everything is loaded
103
 
                void finalize();
104
 
 
105
 
                //! Material name
106
 
                QString name;
107
 
                //! Ka, Kd, Ks, Ke
108
 
                QVector3D ambient;
109
 
                QVector3D diffuse;
110
 
                QVector3D specular;
111
 
                QVector3D emission;
112
 
                //! Shininess [0..128]
113
 
                float shininess;
114
 
                //! Transparency [0..1]
115
 
                float alpha;
116
 
                //! If to perform binary alpha testing. Default off.
117
 
                bool alphatest;
118
 
                //! If to perform backface culling. Default on.
119
 
                bool backfacecull;
120
 
                //! Quick check if this material has specularity
121
 
                bool hasSpecularity;
122
 
                //! Quick check if this material has "real" transparency (i.e. needs blending)
123
 
                bool hasTransparency;
124
 
 
125
 
                //! Texture name
126
 
                QString textureName;
127
 
                //!< Shared pointer to texture of the model. This can be null.
128
 
                StelTextureSP texture;
129
 
                //! Bump map name
130
 
                QString bumpMapName;
131
 
                //!< Shared pointer to bump map texture of the model. This can be null.
132
 
                StelTextureSP bump_texture;
133
 
                //! Height map name
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;
141
 
        };
142
 
 
143
 
 
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)
146
 
        struct Vertex
147
 
        {
148
 
                GLfloat position[3];
149
 
                GLfloat texCoord[2];
150
 
                GLfloat normal[3];
151
 
                GLfloat tangent[4];
152
 
                GLfloat bitangent[3];
153
 
 
154
 
                static const Vertex EmptyVertex;
155
 
        };
156
 
 
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
159
 
        struct StelModel
160
 
        {
161
 
                int startIndex, triangleCount;
162
 
                //materials are managed by OBJ
163
 
                const Material* pMaterial;
164
 
                //AABB is managed by this
165
 
                AABB bbox;
166
 
                //The centroid location of all vertices of this model
167
 
                Vec3f centroid;
168
 
        };
169
 
 
170
 
        //! Initializes values
171
 
        OBJ();
172
 
        //! Destructor
173
 
        ~OBJ();
174
 
 
175
 
        //! Cleanup, will be called inside the destructor
176
 
        void clean();
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;
186
 
 
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();
190
 
 
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);
194
 
 
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;
201
 
 
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;
208
 
 
209
 
        //! Returns flags
210
 
        bool isLoaded() const;
211
 
        bool hasPositions() const;
212
 
        bool hasTextureCoords() const;
213
 
        bool hasNormals() const;
214
 
        bool hasTangents() const;
215
 
        bool hasStelModels() const;
216
 
 
217
 
        //! Returns the bounding box for this OBJ
218
 
        //const BoundingBox* getBoundingBox() const;
219
 
        const AABB& getBoundingBox();
220
 
 
221
 
        void renderAABBs();
222
 
 
223
 
        //! Returns an estimate of the memory usage of this instance (not fully accurate, but good enough)
224
 
        size_t memoryUsage();
225
 
 
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();
230
 
 
231
 
        //! Binds the necessary GL objects, making the OBJ ready for drawing. Uses a VAO if the platform supports it.
232
 
        void bindGL();
233
 
        //! Unbinds this object's GL objects
234
 
        void unbindGL();
235
 
 
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; }
242
 
 
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);
245
 
private:
246
 
        struct FaceAttributes
247
 
        {
248
 
                int materialIndex;
249
 
                int objectIndex;
250
 
        };
251
 
 
252
 
        typedef QVector<FaceAttributes> AttributeVector;
253
 
        typedef QVector<Vec3f> VF3Vector;
254
 
        typedef QVector<Vec2f> VF2Vector;
255
 
        typedef Vec3f VPos;
256
 
        typedef QVector<Vec3f> PosVector;
257
 
        typedef QMap<QString,int> MatCacheT;
258
 
        typedef QMap<int, QVector<int> > VertCacheT;
259
 
 
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
287
 
        void findBounds();
288
 
        //! Binds the GL buffers to the vertex attributes
289
 
        void bindBuffersGL();
290
 
        //! Releases vertex attribute bindings and buffers
291
 
        void unbindBuffersGL();
292
 
 
293
 
        //! Returns the file for this filename, handling decompression if necessary
294
 
        QFile* getFile(const QString& filename);
295
 
 
296
 
        //! Used for parsing a texture string
297
 
        QString parseTextureString(const char *buffer) const;
298
 
 
299
 
        //! Flags
300
 
        bool m_loaded;
301
 
        bool m_hasPositions;
302
 
        bool m_hasTextureCoords;
303
 
        bool m_hasNormals;
304
 
        bool m_hasTangents;
305
 
        bool m_hasStelModels;
306
 
        static bool vertexArraysSupported;
307
 
 
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;
313
 
 
314
 
        //! Structure sizes
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;
321
 
 
322
 
        //! Bounding box for the entire scene
323
 
        AABB pBoundingBox;
324
 
 
325
 
        //! Base path to this file
326
 
        QString m_basePath;
327
 
 
328
 
        //! Datastructures
329
 
        QVector<StelModel> m_stelModels;
330
 
        QVector<Material> m_materials;
331
 
        QVector<Vertex> m_vertexArray;
332
 
        QVector<unsigned int> m_indexArray;
333
 
 
334
 
        //! OpenGL objects
335
 
        QOpenGLBuffer m_vertexBuffer;
336
 
        QOpenGLBuffer m_indexBuffer;
337
 
        QOpenGLVertexArrayObject* m_vertexArrayObject;
338
 
 
339
 
        static QOpenGLFunctions* gl;
340
 
 
341
 
        //! Heightmap
342
 
        friend class Heightmap;
343
 
};
344
 
 
345
 
inline OBJ::Material& OBJ::getMaterial(int i) { return m_materials[i]; }
346
 
 
347
 
inline const OBJ::StelModel& OBJ::getStelModel(int i) const { return m_stelModels[i]; }
348
 
 
349
 
inline int OBJ::getNumberOfIndices() const { return m_numberOfTriangles * 3; }
350
 
 
351
 
inline int OBJ::getNumberOfStelModels() const { return m_numberOfStelModels; }
352
 
 
353
 
inline int OBJ::getNumberOfTriangles() const { return m_numberOfTriangles; }
354
 
 
355
 
inline int OBJ::getNumberOfVertices() const { return static_cast<int>(m_vertexArray.size()); }
356
 
 
357
 
inline int OBJ::getNumberOfMaterials() const {return m_numberOfMaterials; }
358
 
 
359
 
inline const OBJ::Vertex& OBJ::getVertex(int i) const { return m_vertexArray[i]; }
360
 
 
361
 
inline const OBJ::Vertex* OBJ::getVertexArray() const { return &m_vertexArray[0]; }
362
 
 
363
 
inline int OBJ::getVertexSize() const { return static_cast<int>(sizeof(Vertex)); }
364
 
 
365
 
inline bool OBJ::isLoaded() const{ return m_loaded; }
366
 
 
367
 
inline bool OBJ::hasNormals() const{ return m_hasNormals; }
368
 
 
369
 
inline bool OBJ::hasPositions() const { return m_hasPositions; }
370
 
 
371
 
inline bool OBJ::hasTangents() const { return m_hasTangents; }
372
 
 
373
 
inline bool OBJ::hasTextureCoords() const { return m_hasTextureCoords; }
374
 
 
375
 
inline bool OBJ::hasStelModels() const { return m_hasStelModels; }
376
 
 
377
 
//inline const OBJ::BoundingBox* OBJ::getBoundingBox() const { return pBoundingBox; }
378
 
inline const AABB &OBJ::getBoundingBox() {return pBoundingBox; }
379
 
 
380
 
inline QString OBJ::absolutePath(QString path) { return m_basePath + path; }
381
 
 
382
 
#endif