-
Notifications
You must be signed in to change notification settings - Fork 47
/
StaticModel.h
232 lines (178 loc) · 5.83 KB
/
StaticModel.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#pragma once
#include "iundo.h"
#include "imodel.h"
#include "math/AABB.h"
#include "imodelsurface.h"
#include <memory>
class Ray;
/* FORWARD DECLS */
namespace model
{
class StaticModelSurface;
typedef std::shared_ptr<StaticModelSurface> StaticModelSurfacePtr;
}
class RenderableCollector;
class RendererLight;
class SelectionTest;
class Selector;
namespace model
{
/**
* \brief
* IModel implementing class representing a static model
*
* A StaticModel is made up of one or more StaticModelSurface
* objects, each of which contains a number of polygons with the same texture.
* Rendering a StaticModel involves rendering all of its surfaces,
* submitting their geometry via OpenGL calls.
*/
class StaticModel :
public IModel,
public IUndoable
{
private:
// greebo: StaticModelSurfaces are shared objects, the actual shaders
// and the model skin handling are managed by the nodes/imodels referencing them
struct Surface
{
// The (shared) surface object
StaticModelSurfacePtr surface;
// The (unmodified) surface object
StaticModelSurfacePtr originalSurface;
// The shader this surface is using
ShaderPtr shader;
Surface()
{}
// Constructor
Surface(const StaticModelSurfacePtr& surface_) :
surface(surface_),
originalSurface(surface)
{}
};
typedef std::vector<Surface> SurfaceList;
// Vector of renderable surfaces for this model
SurfaceList _surfVec;
// The current working scale
Vector3 _scaleTransformed;
// The scale for this model (is 1,1,1 for an unmodified one)
Vector3 _scale;
// Local AABB for this model
AABB _localAABB;
// Vector of materials used by this model (one for each surface)
mutable std::vector<std::string> _materialList;
// The filename this model was loaded from
std::string _filename;
// The VFS path to this model
std::string _modelPath;
// We need to keep a reference for skin swapping
RenderSystemWeakPtr _renderSystem;
// Undoable stuff
IUndoStateSaver* _undoStateSaver;
private:
// Update the list of materials by querying each surface for its current
// material.
void updateMaterialList() const;
// Ensure all shaders for the active materials
void captureShaders();
void undoSave();
void applyScaleToSurfaces();
void foreachVisibleSurface(const std::function<void(const Surface& s)>& func) const;
public:
/**
* Construct a StaticModel with the given set of surfaces.
*/
StaticModel(const std::vector<StaticModelSurfacePtr>& surfaces);
/**
* Copy constructor: re-use the surfaces from the other model
* but make it possible to assign custom skins to the surfaces.
*/
StaticModel(const StaticModel& other);
void connectUndoSystem(IUndoSystem& undoSystem);
void disconnectUndoSystem(IUndoSystem& undoSystem);
// Delegated render methods called by StaticModelNode (not part of any
// interface)
void renderSolid(RenderableCollector& rend, const Matrix4& localToWorld,
const IRenderEntity& entity, const LitObject& litObj) const;
void renderWireframe(RenderableCollector& rend, const Matrix4& localToWorld,
const IRenderEntity& entity) const;
void setRenderSystem(const RenderSystemPtr& renderSystem);
/**
* Back-end render function from OpenGLRenderable. This is called from the
* model selector but not the main renderer, which uses the front-end render
* method.
*/
void render(const RenderInfo& info) const override;
/**
* Return the number of surfaces in this model.
*/
int getSurfaceCount() const override
{
return static_cast<int>(_surfVec.size());
}
/**
* Return the number of vertices in this model, by summing the vertex
* counts for each surface.
*/
int getVertexCount() const override;
/** Return the polycount (tricount) of this model by summing the surface
* polycounts.
*/
int getPolyCount() const override;
const IModelSurface& getSurface(unsigned surfaceNum) const override;
/**
* Return the enclosing AABB for this model.
*/
const AABB& localAABB() const override
{
return _localAABB;
}
/** Return the list of active materials for this model.
*/
const std::vector<std::string>& getActiveMaterials() const override;
// Sets the filename this model was loaded from
void setFilename(const std::string& name);
// Returns the filename this model was loaded from
virtual std::string getFilename() const override;
// Returns the VFS path to the model file
virtual std::string getModelPath() const override;
void setModelPath(const std::string& modelPath);
/** Apply the given skin to this model.
*/
void applySkin(const ModelSkin& skin) override;
/**
* Selection test. Test each surface against the SelectionTest object and
* if the surface is selected, add it to the selector.
*
* @param selector
* Selector object which builds a list of selectables.
*
* @param test
* The SelectionTest object defining the 3D properties of the selection.
*
* @param localToWorld
* Object to world space transform.
*/
void testSelect(Selector& selector,
SelectionTest& test,
const Matrix4& localToWorld);
// Returns true if the given ray intersects this model geometry and fills in
// the exact point in the given Vector3, returns false if no intersection was found.
bool getIntersection(const Ray& ray, Vector3& intersection, const Matrix4& localToWorld);
/**
* Return the list of StaticModelSurface objects.
*/
const SurfaceList& getSurfaces() const;
// Revert to base scale
void revertScale();
// TransformationChanged, apply the given scale to the "working copy"
void evaluateScale(const Vector3& scale);
// Freeze transform, store new base scale
void freezeScale();
// Undoable implementation
IUndoMementoPtr exportState() const override;
void importState(const IUndoMementoPtr& state) override;
// Returns the current base scale of this model
const Vector3& getScale() const;
};
typedef std::shared_ptr<StaticModel> StaticModelPtr;
}