Skip to content

Commit

Permalink
#5584: Prepare for light volume rendering.
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Dec 5, 2021
1 parent 6da7470 commit 2e32d59
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 51 deletions.
31 changes: 27 additions & 4 deletions radiantcore/entity/light/LightNode.cpp
Expand Up @@ -26,6 +26,7 @@ LightNode::LightNode(const IEntityClassPtr& eclass) :
_lightEndInstance(_light.endTransformed(), std::bind(&LightNode::selectedChangedComponent, this, std::placeholders::_1)),
_dragPlanes(std::bind(&LightNode::selectedChangedComponent, this, std::placeholders::_1)),
_renderableOctagon(*this),
_renderableLightVolume(*this),
_renderableRadius(_light._lightBox.origin),
_renderableFrustum(_light._lightBox.origin, _light._lightStartTransformed, _light._frustum),
_overrideColKey(colours::RKEY_OVERRIDE_LIGHTCOL)
Expand All @@ -48,6 +49,7 @@ LightNode::LightNode(const LightNode& other) :
_lightEndInstance(_light.endTransformed(), std::bind(&LightNode::selectedChangedComponent, this,std::placeholders:: _1)),
_dragPlanes(std::bind(&LightNode::selectedChangedComponent, this, std::placeholders::_1)),
_renderableOctagon(*this),
_renderableLightVolume(*this),
_renderableRadius(_light._lightBox.origin),
_renderableFrustum(_light._lightBox.origin, _light._lightStartTransformed, _light._frustum),
_overrideColKey(colours::RKEY_OVERRIDE_LIGHTCOL)
Expand Down Expand Up @@ -107,6 +109,7 @@ void LightNode::onRemoveFromScene(scene::IMapRootNode& root)
setSelectedComponents(false, selection::ComponentSelectionMode::Face);

_renderableOctagon.clear();
_renderableLightVolume.clear();
}

void LightNode::testSelect(Selector& selector, SelectionTest& test)
Expand Down Expand Up @@ -280,7 +283,19 @@ void LightNode::selectedChangedComponent(const ISelectable& selectable) {
void LightNode::onPreRender(const VolumeTest& volume)
{
// Pick the colour shader according to our settings
_renderableOctagon.update(_overrideColKey.get() ? getColourShader() : _colourKey.getColourShader());
const auto& colourShader = _overrideColKey.get() ? getColourShader() : _colourKey.getColourShader();
_renderableOctagon.update(colourShader);

// Depending on the selected status or the entity settings, we need to update the wireframe volume
if (_showLightVolumeWhenUnselected || isSelected())
{
_renderableLightVolume.update(colourShader);
}
else
{
// Light volume is not visible, hide it
_renderableLightVolume.clear();
}
}

void LightNode::renderSolid(IRenderableCollector& collector, const VolumeTest& volume) const
Expand Down Expand Up @@ -308,22 +323,24 @@ void LightNode::renderWireframe(IRenderableCollector& collector, const VolumeTes
void LightNode::renderHighlights(IRenderableCollector& collector, const VolumeTest& volume)
{
collector.addHighlightRenderable(_renderableOctagon, Matrix4::getIdentity());
collector.addHighlightRenderable(_renderableLightVolume, Matrix4::getIdentity());
}

void LightNode::renderLightVolume(IRenderableCollector& collector,
const Matrix4& localToWorld,
bool selected) const
{
#if 0
// Obtain the appropriate Shader for the light volume colour
const auto& colourShader = _overrideColKey.get() ? getWireShader() : _colourKey.getColourShader();

if (!colourShader) return;

#endif
#if 0
// Main render, submit the diamond that represents the light entity
collector.addRenderable(*colourShader, *this, localToWorld);
#endif

#if 0
// Render bounding box if selected or the showAllLighRadii flag is set
if (selected || EntitySettings::InstancePtr()->getShowAllLightRadii())
{
Expand All @@ -340,6 +357,7 @@ void LightNode::renderLightVolume(IRenderableCollector& collector,
collector.addRenderable(*colourShader, _renderableRadius, localToWorld);
}
}
#endif
}

/* greebo: Calculates the corners of the light radii box and rotates them according the rotation matrix.
Expand Down Expand Up @@ -592,7 +610,9 @@ void LightNode::_onTransformationChanged()
_light.revertTransform();
evaluateTransform();
_light.updateOrigin();

_renderableOctagon.queueUpdate();
_renderableLightVolume.queueUpdate();
}

void LightNode::_applyTransformation()
Expand All @@ -614,16 +634,19 @@ void LightNode::onVisibilityChanged(bool isVisibleNow)
if (isVisibleNow)
{
_renderableOctagon.queueUpdate();
_renderableLightVolume.queueUpdate();
}
else
{
_renderableLightVolume.clear();
_renderableOctagon.clear();
}
}

void LightNode::onEntitySettingsChanged()
{
// TODO
_showLightVolumeWhenUnselected = EntitySettings::InstancePtr()->getShowAllLightRadii();
_renderableLightVolume.queueUpdate();
}

} // namespace entity
4 changes: 4 additions & 0 deletions radiantcore/entity/light/LightNode.h
Expand Up @@ -7,6 +7,7 @@
#include "dragplanes.h"
#include "../VertexInstance.h"
#include "../EntityNode.h"
#include "Renderables.h"

namespace entity
{
Expand Down Expand Up @@ -41,9 +42,12 @@ class LightNode :

// Renderable components of this light
RenderableLightOctagon _renderableOctagon;
RenderableLightVolume _renderableLightVolume;
RenderLightRadiiBox _renderableRadius;
RenderLightProjection _renderableFrustum;

bool _showLightVolumeWhenUnselected;

// a temporary variable for calculating the AABB of all (selected) components
mutable AABB m_aabb_component;

Expand Down
58 changes: 58 additions & 0 deletions radiantcore/entity/light/Renderables.cpp
Expand Up @@ -174,4 +174,62 @@ void RenderLightProjection::render(const RenderInfo& info) const
}
}

void RenderableLightOctagon::updateGeometry()
{
if (!_needsUpdate) return;

_needsUpdate = false;

// Generate the indexed vertex data
static Vector3 Origin(0, 0, 0);
static Vector3 Extents(8, 8, 8);

// Calculate the light vertices of this bounding box and store them into <points>
Vector3 max(Origin + Extents);
Vector3 min(Origin - Extents);
Vector3 mid(Origin);

// top, bottom, tleft, tright, bright, bleft
std::vector<ArbitraryMeshVertex> vertices
{
ArbitraryMeshVertex({ mid[0], mid[1], max[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ mid[0], mid[1], min[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ min[0], max[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ max[0], max[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ max[0], min[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ min[0], min[1], mid[2] }, {1,0,0}, {0,0}),
};

// Orient the points using the transform
const auto& orientation = _owner.localToWorld();
for (auto& vertex : vertices)
{
vertex.vertex = orientation * vertex.vertex;
}

// Indices are always the same, therefore constant
static const std::vector<unsigned int> Indices
{
0, 2, 3,
0, 3, 4,
0, 4, 5,
0, 5, 2,
1, 2, 5,
1, 5, 4,
1, 4, 3,
1, 3, 2
};

RenderableGeometry::updateGeometry(render::GeometryType::Triangles, vertices, Indices);
}

void RenderableLightVolume::updateGeometry()
{
if (!_needsUpdate) return;

_needsUpdate = false;

// TODO
}

} // namespace entity
76 changes: 29 additions & 47 deletions radiantcore/entity/light/Renderables.h
Expand Up @@ -11,7 +11,10 @@

void light_draw_box_lines(const Vector3& origin, const Vector3 points[8]);

namespace entity {
namespace entity
{

class LightNode;

class RenderLightRadiiBox : public OpenGLRenderable {
const Vector3& m_origin;
Expand All @@ -36,6 +39,8 @@ class RenderLightProjection : public OpenGLRenderable {
}; // class RenderLightProjection

// The small diamond representing at the light's origin
// This is using the Triangle geometry type such that we can see
// the half-transparent (red) overlay when the light is selected
class RenderableLightOctagon :
public render::RenderableGeometry
{
Expand All @@ -55,54 +60,31 @@ class RenderableLightOctagon :
}

protected:
void updateGeometry() override
void updateGeometry() override;
};

// The wireframe showing the light volume of the light
// which is either a box (point light) or a frustum/cone (projected)
class RenderableLightVolume :
public render::RenderableGeometry
{
private:
const LightNode& _light;
bool _needsUpdate;

public:
RenderableLightVolume(const LightNode& light) :
_light(light),
_needsUpdate(true)
{}

void queueUpdate()
{
if (!_needsUpdate) return;

_needsUpdate = false;

// Generate the indexed vertex data
static Vector3 Origin(0, 0, 0);
static Vector3 Extents(8, 8, 8);

// Calculate the light vertices of this bounding box and store them into <points>
Vector3 max(Origin + Extents);
Vector3 min(Origin - Extents);
Vector3 mid(Origin);

// top, bottom, tleft, tright, bright, bleft
std::vector<ArbitraryMeshVertex> vertices
{
ArbitraryMeshVertex({ mid[0], mid[1], max[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ mid[0], mid[1], min[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ min[0], max[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ max[0], max[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ max[0], min[1], mid[2] }, {1,0,0}, {0,0}),
ArbitraryMeshVertex({ min[0], min[1], mid[2] }, {1,0,0}, {0,0}),
};

// Orient the points using the transform
const auto& orientation = _owner.localToWorld();
for (auto& vertex : vertices)
{
vertex.vertex = orientation * vertex.vertex;
}

// Indices are always the same, therefore constant
static const std::vector<unsigned int> Indices
{
0, 2, 3,
0, 3, 4,
0, 4, 5,
0, 5, 2,
1, 2, 5,
1, 5, 4,
1, 4, 3,
1, 3, 2
};

RenderableGeometry::updateGeometry(render::GeometryType::Triangles, vertices, Indices);
_needsUpdate = true;
}

protected:
void updateGeometry() override;
};

} // namespace entity

0 comments on commit 2e32d59

Please sign in to comment.