/
LightNode.h
275 lines (207 loc) · 8.73 KB
/
LightNode.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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#pragma once
#include "Doom3LightRadius.h"
#include "Renderables.h"
#include "LightShader.h"
#include "ilightnode.h"
#include "registry/CachedKey.h"
#include "scene/TransformedCopy.h"
#include "math/Frustum.h"
#include "editable.h"
#include "dragplanes.h"
#include "../VertexInstance.h"
#include "../EntityNode.h"
#include "../OriginKey.h"
#include "../RotationKey.h"
#include "Renderables.h"
#include "LightVertexInstanceSet.h"
namespace entity
{
class LightNode;
typedef std::shared_ptr<LightNode> LightNodePtr;
/// Scenegraph node representing a light
class LightNode :
public EntityNode,
public ILightNode,
public Snappable,
public ComponentSelectionTestable,
public ComponentEditable,
public ComponentSnappable,
public PlaneSelectable,
public RendererLight
{
OriginKey m_originKey;
// The "working" version of the origin
Vector3 _originTransformed;
RotationKey m_rotationKey;
RotationMatrix m_rotation;
Doom3LightRadius m_doom3Radius;
RotationMatrix m_lightRotation;
bool m_useLightRotation = false;
// Projected light vectors, both base and transformed
scene::TransformedCopy<Projected<Vector3>> _projVectors;
// 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;
ShaderPtr _vertexShader;
ShaderPtr _crystalFillShader;
ShaderPtr _crystalOutlineShader;
// The 8x8 box representing the light object itself
AABB _lightBox;
Callback m_transformChanged;
Callback m_boundsChanged;
Callback m_evaluateTransform;
LightVertexInstanceSet _instances;
// dragplanes for lightresizing using mousedrag
selection::DragPlanes _dragPlanes;
// Renderable components of this light
RenderableLightOctagon _renderableOctagon;
RenderableLightOctagon _renderableOctagonOutline;
RenderableLightVolume _renderableLightVolume;
RenderableLightVertices _renderableVertices;
bool _showLightVolumeWhenUnselected;
// a temporary variable for calculating the AABB of all (selected) components
mutable AABB m_aabb_component;
// Cached rkey to override light volume colour
registry::CachedKey<bool> _overrideColKey;
mutable Matrix4 m_projectionOrientation;
public:
LightNode(const IEntityClassPtr& eclass);
private:
LightNode(const LightNode& other);
public:
static LightNodePtr Create(const IEntityClassPtr& eclass);
// ILightNode implementation
const RendererLight& getRendererLight() const override { return *this; }
void transformChanged() override;
// RenderEntity implementation
virtual float getShaderParm(int parmNum) const override;
// Bounded implementation
const AABB& localAABB() const override;
// override scene::Node methods to deselect the child components
virtual void onRemoveFromScene(scene::IMapRootNode& root) override;
// Snappable implementation
void snapto(float snap) override;
/** greebo: Returns the AABB of the small diamond representation.
* (use this to select the light against an AABB selectiontest like CompleteTall or similar).
*/
AABB getSelectAABB() const override;
/* greebo: This snaps the components to the grid.
*
* Note: if none are selected, ALL the components are snapped to the grid (I hope this is intentional)
* This function can only be called in Selection::eVertex mode, so I assume that the user wants all components
* to be snapped.
*
* If one or more components is/are selected, ONLY those are snapped to the grid.
*/
void snapComponents(float snap) override;
// PlaneSelectable implementation
void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback) override;
void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes) override;
// Test the light volume for selection, this just passes the call on to the contained Light class
void testSelect(Selector& selector, SelectionTest& test) override;
// greebo: Returns true if drag planes or the light center is selected (both are components)
bool isSelectedComponents() const override;
// greebo: Selects/deselects all components, depending on the chosen componentmode
void setSelectedComponents(bool select, selection::ComponentSelectionMode mode) override;
void invertSelectedComponents(selection::ComponentSelectionMode mode) override;
void testSelectComponents(Selector& selector, SelectionTest& test, selection::ComponentSelectionMode mode) override;
/**
* greebo: This returns the AABB of all the selectable vertices. This method
* distinguishes between projected and point lights and stretches the AABB accordingly.
*/
// ComponentEditable implementation
const AABB& getSelectedComponentsBounds() const override;
scene::INodePtr clone() const override;
void selectedChangedComponent(const ISelectable& selectable);
// Renderable implementation
void onPreRender(const VolumeTest& volume) override;
void renderHighlights(IRenderableCollector& collector, const VolumeTest& volume) override;
void setRenderSystem(const RenderSystemPtr& renderSystem) override;
const Matrix4& rotation() const;
// Returns the original "origin" value
const Vector3& getUntransformedOrigin() override;
const Vector3& getWorldPosition() const override;
void onEntitySettingsChanged() override;
// Is this light projected or omni?
bool isProjected() const;
// Returns the frustum structure (calling this on point lights will throw)
const Frustum& getLightFrustum() const;
// Returns the relative start point used by projected lights to cut off
// the upper part of the projection cone to form the frustum
// Calling this on point lights will throw.
const Vector3& getLightStart() const;
// Returns the light radius for point lights
// Calling this on projected lights will throw
const Vector3& getLightRadius() const;
virtual Vector4 getEntityColour() const override;
protected:
// Gets called by the Transformable implementation whenever
// scale, rotation or translation is changed.
void _onTransformationChanged() override;
// Called by the Transformable implementation before freezing
// or when reverting transformations.
void _applyTransformation() override;
// Override EntityNode::construct()
void construct() override;
void onVisibilityChanged(bool isVisibleNow) override;
void onSelectionStatusChange(bool changeGroupStatus) override;
void onColourKeyChanged(const std::string& value) override;
private:
void evaluateTransform();
// Ensure the start and end points are set to sensible values
void checkStartEnd();
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 rotationChanged();
void lightRotationChanged(const std::string& value);
void onLightRadiusChanged();
// Returns a reference to the member class Doom3LightRadius (used to set colours)
Doom3LightRadius& getDoom3Radius();
/**
* 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 translate(const Vector3& translation);
void rotate(const Quaternion& rotation);
void setLightRadius(const AABB& aabb);
void transformLightRadius(const Matrix4& transform);
void revertLightTransform();
void freezeLightTransform();
// Set the projection-changed flag
void projectionChanged();
// Update the projected light frustum
void updateProjection() const;
bool useStartEnd() const;
void updateRenderables();
void clearRenderables();
public:
// RendererLight implementation
const IRenderEntity& getLightEntity() const override;
Matrix4 getLightTextureTransformation() const override;
Vector3 getLightOrigin() const override;
bool isShadowCasting() const override;
bool isBlendLight() const override;
const ShaderPtr& getShader() const override;
AABB lightAABB() const override;
};
} // namespace entity