/
Light.h
256 lines (194 loc) · 6.54 KB
/
Light.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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#pragma once
#include "igl.h"
#include "irender.h"
#include "editable.h"
#include "render.h"
#include "irenderable.h"
#include "math/Frustum.h"
#include "transformlib.h"
#include "scene/TransformedCopy.h"
#include "../OriginKey.h"
#include "../RotationKey.h"
#include "../ColourKey.h"
#include "../ModelKey.h"
#include "../SpawnArgs.h"
#include "../KeyObserverDelegate.h"
#include "Renderables.h"
#include "LightShader.h"
#include "RenderableVertices.h"
#include "Doom3LightRadius.h"
#include "generic/callback.h"
namespace entity
{
inline void default_extents(Vector3& extents) {
extents = Vector3(8,8,8);
}
class LightNode;
/**
* \brief
* Main implementation of a light in the scene
*
* greebo: This is the actual light class. It contains the information about
* the geometry of the light and the actual render functions.
*
* This class owns all the keyObserver callbacks, that get invoked as soon as
* the entity key/values get changed by the user.
*
* The subclass Doom3LightRadius contains some variables like the light radius
* and light center coordinates, and there are some "onChanged" callbacks for
* the light radius and light center.
*
* Note: All the selection stuff is handled by the LightInstance class. This is
* just the bare bone light.
*/
class Light: public RendererLight, public sigc::trackable
{
friend class LightNode;
LightNode& _owner;
// The parent entity object that uses this light
SpawnArgs& _entity;
OriginKey m_originKey;
// The "working" version of the origin
Vector3 _originTransformed;
RotationKey m_rotationKey;
RotationMatrix m_rotation;
Doom3LightRadius m_doom3Radius;
// Renderable components of this light
RenderableLightTarget _rCentre;
RenderableLightTarget _rTarget;
RenderableLightRelative _rUp;
RenderableLightRelative _rRight;
RenderableLightTarget _rStart;
RenderableLightTarget _rEnd;
RotationMatrix m_lightRotation;
bool m_useLightRotation;
// Set of values defining a projected light
template<typename T> struct Projected
{
T target;
T up;
T right;
T start;
T end;
};
// Projected light vectors, both base and transformed
scene::TransformedCopy<Projected<Vector3>> _projVectors;
// Projected light vector colours
Projected<Vector3> _projColours;
// Projected light use flags
Projected<bool> _projUseFlags;
mutable AABB m_doom3AABB;
mutable Matrix4 m_doom3Rotation;
// Frustum for projected light (used for rendering the light volume)
mutable Frustum _frustum;
// Transforms local space coordinates into texture coordinates
// To get the complete texture transform this one needs to be
// post-multiplied by the world rotation and translation.
mutable Matrix4 _localToTexture;
mutable bool _projectionChanged;
LightShader m_shader;
// The 8x8 box representing the light object itself
AABB _lightBox;
Callback m_transformChanged;
Callback m_boundsChanged;
Callback m_evaluateTransform;
private:
void construct();
void destroy();
// Ensure the start and end points are set to sensible values
void checkStartEnd();
public:
const Vector3& getUntransformedOrigin() const;
void updateOrigin();
void originChanged();
void lightTargetChanged(const std::string& value);
void lightUpChanged(const std::string& value);
void lightRightChanged(const std::string& value);
void lightStartChanged(const std::string& value);
void lightEndChanged(const std::string& value);
void writeLightOrigin();
void rotationChanged();
void lightRotationChanged(const std::string& value);
/**
* \brief
* Main constructor.
*/
Light(SpawnArgs& entity,
LightNode& owner,
const Callback& transformChanged,
const Callback& boundsChanged,
const Callback& lightRadiusChanged);
/**
* \brief
* Copy constructor.
*/
Light(const Light& other,
LightNode& owner,
SpawnArgs& entity,
const Callback& transformChanged,
const Callback& boundsChanged,
const Callback& lightRadiusChanged);
~Light();
const AABB& localAABB() const;
AABB lightAABB() const override;
// Note: move this upwards
mutable Matrix4 m_projectionOrientation;
// Renderable submission functions
void renderWireframe(IRenderableCollector& collector,
const VolumeTest& volume,
const Matrix4& localToWorld,
bool selected) const;
void setRenderSystem(const RenderSystemPtr& renderSystem);
// Adds the light centre renderable to the given collector
void renderLightCentre(IRenderableCollector& collector, const VolumeTest& volume, const Matrix4& localToWorld) const;
void renderProjectionPoints(IRenderableCollector& collector, const VolumeTest& volume, const Matrix4& localToWorld) const;
// Returns a reference to the member class Doom3LightRadius (used to set colours)
Doom3LightRadius& getDoom3Radius();
void translate(const Vector3& translation);
/**
* greebo: This sets the light start to the given value, including bounds checks.
*/
void setLightStart(const Vector3& newLightStart);
/**
* greebo: Checks if the light_start is positioned "above" the light origin and constrains
* the movement accordingly to prevent the light volume to become an "hourglass".
* Only affects the _lightStartTransformed member.
*/
void ensureLightStartConstraints();
void rotate(const Quaternion& rotation);
// This snaps the light as a whole to the grid (basically the light origin)
void snapto(float snap);
void setLightRadius(const AABB& aabb);
void transformLightRadius(const Matrix4& transform);
void revertTransform();
void freezeTransform();
// Is this light projected or omni?
bool isProjected() const;
// Set the projection-changed flag
void projectionChanged();
// Update the projected light frustum
void updateProjection() const;
// RendererLight implementation
const IRenderEntity& getLightEntity() const override;
Matrix4 getLightTextureTransformation() const override;
Vector3 getLightOrigin() const override;
const ShaderPtr& getShader() const override;
const Matrix4& rotation() const;
Vector3& target();
Vector3& targetTransformed();
Vector3& up();
Vector3& upTransformed();
Vector3& right();
Vector3& rightTransformed();
Vector3& start();
Vector3& startTransformed();
Vector3& end();
Vector3& endTransformed();
Vector3& colourLightTarget();
Vector3& colourLightRight();
Vector3& colourLightUp();
Vector3& colourLightStart();
Vector3& colourLightEnd();
bool useStartEnd() const;
}; // class Light
} // namespace entity