-
Notifications
You must be signed in to change notification settings - Fork 1
/
ObjMeshObject.h
161 lines (147 loc) · 7.95 KB
/
ObjMeshObject.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
// Created by rthier on 2016.04.12..
//
#ifndef OBJMASTER_OBJMESHOBJECT_H
#define OBJMASTER_OBJMESHOBJECT_H
#include "Obj.h"
#include "FaceElement.h"
#include "VertexStructure.h"
#include <memory>
#include <vector>
#include <stdint.h>
// Define this if your device only handles 16 bit indices and want to build like that!
// This means that less model data will fit in the per-group or per-mesh memory, but
// devices like Raspberry or Orange Pis and old phones will not complain. Of course
// you can also save graphics memory this way or let the 32 bit indices work and do
// post-processing on your own (for example you can cut a too big object to fit).
#if USE_16BIT_INDICES
#define OM_INDEX_TYPE uint16_t
#else
#define OM_INDEX_TYPE uint32_t
#endif /* USE_16BIT_INDICES */
namespace ObjMaster {
/**
* A 3d mesh out of a *.OBJ file. This can be used to show the object in a scene as it has proper
* buffers one can use with most CG rendering methods (like OpenGL).
*/
class ObjMeshObject {
public:
/**
* Says if the mesh has been initialized or not.
* This is useful when using non-pointer object and you cannot see
* if it is "nullptr" in that case but need extremal element to decide caching etc.
*/
bool inited = false;
// These are pointers as they are useful for optimized shared vectors in bigger models!
// In other case we use them to point to our locally created vectors that we create with new!
// If someone is trying to use the library in that way that each object is one mesh that still
// still needs to be as fast as it can be and there is a slight overhead in shared_ptr too so
// it is better to do a little housekeeping than to make the implementation easier for me.
/** If true the mesh object is owning the pointer, otherwise the other object that logically contains the (multiple) meshes */
bool ownsVertexData = false; // ownership flag
/** If true the mesh object is owning the pointer, otherwise the other object that logically contains the (multiple) meshes */
bool ownsIndices = false; // ownership flag
// Render-ready data with inlined vertex attributes. Inlining is usually better for GPU
// cache hitting.
/**
* Pointer to the vector of vertex data.
* - Beware as this can be a shared vector in case of the mesh is being part of a complex model!
* - Because of this, one should use baseVertexLocation to find the start vertex and vertexCount
* for the mesh-specific size! (the vector would return the whole model vertices count otherwise)
*/
std::vector<VertexStructure> *vertexData;
/**
* Pointer to the vector of index data.
* - Beware as this can be a shared vector in case of the mesh is being part of a complex model!
* - Because of this, one should use startIndexLocation to find the start index and indexCount
* for the mesh-specific size! (the vector would return the whole model index-count otherwise)
*/
std::vector<OM_INDEX_TYPE> *indices;
// Helper variables to aid optimized one-vbo rendering of multi-mesh models
/**
* MULTIMESH: The location of the first index for the GPU to read from the index buffer.
* When a model contains multiple meshes, it is much better to put all the mesh data into
* the one and same vertex and index buffers (given that the object is not too big). In
* that case, we of course need to know where the data would start in a big buffer like
* that. Because the model loading process has this information, we provide it here so
* using the vertex data for this mesh and the other meshes, one can construct the big
* continous array if that is what you want!
*
* In non-multimesh cases this will be just 0
*/
unsigned int startIndexLocation;
/**
* MULTIMESH: A value added to each index before reading a vertex from the vertex buffer.
* When a model contains multiple meshes, it is much better to put all the mesh data into
* the one and same vertex and index buffers (given that the object is not too big). In
* that case, we of course need to know where the data would start in a big buffer like
* that. Because the model loading process has this information, we provide it here so
* using the vertex data for this mesh and the other meshes, one can construct the big
* continous array if that is what you want!
*
* In non-multimesh cases this will be just 0
*/
unsigned int baseVertexLocation;
/** The number of indices (the per-mesh value - not the indices.size() which might be bigger because of sharing!!!) */
unsigned int indexCount;
/** The number of vertices (the per-mesh value - not the vertexData.size() which might be bigger because of sharing!!!) */
unsigned int vertexCount;
/** The biggest index value that belongs to this mesh */
OM_INDEX_TYPE lastIndex;
// Empty constructor
ObjMeshObject() {};
/** Create an obj mesh object using all faces available in the given Obj */
ObjMeshObject(const Obj& obj);
/**
* Create and obj mesh object using the explicitly given faces from the given Obj.
* The parameter variables should be in synch with each other and refer to data from the
* same *.obj file / same Obj data.
*/
ObjMeshObject(const Obj& obj, const FaceElement *meshFaces, int meshFaceCount);
/**
* Create and obj mesh object using the explicitly given faces from the given Obj.
* The parameter variables should be in synch with each other and refer to data from the
* same *.obj file / same Obj data. The index and vertex data will be collected in the
* given vectors instead of creating new vectors here in the constructor for this
* purpose! The passed pointers are not owned by the mesh and freeing them is the job
* of the caller. Also this kind of construction creates a tighter coupling of the
* life-cycles of the vectors provided by the caller and the created object! The reason
* why this is useful is that using the mesh for creating parts of a big model can be done
* in a much more resource effective way. In case any of the last two parameters are null,
* the constructor creates the vector for them. The lastIndexBase parameter is useful for
* defining from which point the indices should start. Basically this should be max(indexVector)
* if the indexVector is a non-null and non-empty pointer and zero otherwise!!!
*/
ObjMeshObject(const Obj& obj, const FaceElement *meshFaces, int meshFaceCount, std::vector<VertexStructure> *vertexVector, std::vector<OM_INDEX_TYPE> *indexVector, OM_INDEX_TYPE lastIndexBase);
/**
* The copy ctor - necessary because of the possible pointer sharing stuff!
* In case of non-shared vectors we copy, in case of shared vectors we copy only the pointer!
*/
ObjMeshObject(const ObjMeshObject &other);
/**
* The copy assignment op - necessary because of the possible pointer sharing stuff!
* In case of non-shared vectors we copy, in case of shared vectors we copy only the pointer!
*/
ObjMeshObject& operator=(const ObjMeshObject& other);
/**
* The move assignment op - necessary because of the possible pointer sharing stuff!
* In case of non-shared vectors we move, in case of shared vectors we move only the pointer!
*/
ObjMeshObject(ObjMeshObject &&other);
/**
* The move assignment op - necessary because of the possible pointer sharing stuff!
* In case of non-shared vectors we move, in case of shared vectors we move only the pointer!
*/
ObjMeshObject& operator=(ObjMeshObject&& other);
// The destructor needs to delete the pointed vectors only in case we own them!
~ObjMeshObject() {
if (ownsVertexData) { delete vertexData; }
if (ownsIndices) { delete indices; }
}
private:
void creationHelper(const Obj& obj, const FaceElement *meshFaces, int meshFaceCount, std::vector<VertexStructure> *vertexVector, std::vector<OM_INDEX_TYPE> *indexVector, OM_INDEX_TYPE lastIndexBase);
void copyHelper(const ObjMeshObject &other);
void moveHelper(ObjMeshObject &&other);
};
}
#endif