From f7129bdd7cbaed4398e92d0fea708cdd1d1a11a6 Mon Sep 17 00:00:00 2001 From: codereader Date: Sun, 5 Dec 2021 08:58:58 +0100 Subject: [PATCH] #5584: The simpler case (without start/end) of projected light volumes is displayed --- radiantcore/entity/light/LightNode.cpp | 12 +++ radiantcore/entity/light/LightNode.h | 5 ++ radiantcore/entity/light/Renderables.cpp | 99 ++++++++++++++++++++++-- radiantcore/entity/light/Renderables.h | 10 ++- 4 files changed, 116 insertions(+), 10 deletions(-) diff --git a/radiantcore/entity/light/LightNode.cpp b/radiantcore/entity/light/LightNode.cpp index 9f5d4e7c8c..32e3e674cf 100644 --- a/radiantcore/entity/light/LightNode.cpp +++ b/radiantcore/entity/light/LightNode.cpp @@ -70,6 +70,18 @@ void LightNode::construct() _light.construct(); } +bool LightNode::isProjected() const +{ + return _light.isProjected(); +} + +const Frustum& LightNode::getLightFrustum() const +{ + if (!_light.isProjected()) throw std::logic_error("getLightFrustum can be called on projected lights only"); + + return _light._frustum; +} + // Snappable implementation void LightNode::snapto(float snap) { _light.snapto(snap); diff --git a/radiantcore/entity/light/LightNode.h b/radiantcore/entity/light/LightNode.h index 27053f239e..1cb93620f8 100644 --- a/radiantcore/entity/light/LightNode.h +++ b/radiantcore/entity/light/LightNode.h @@ -136,6 +136,11 @@ class LightNode : void onEntitySettingsChanged(); + bool isProjected() const; + + // Returns the frustum structure (calling this on point lights will throw) + const Frustum& getLightFrustum() const; + protected: // Gets called by the Transformable implementation whenever // scale, rotation or translation is changed. diff --git a/radiantcore/entity/light/Renderables.cpp b/radiantcore/entity/light/Renderables.cpp index 53279bee01..c30832258f 100644 --- a/radiantcore/entity/light/Renderables.cpp +++ b/radiantcore/entity/light/Renderables.cpp @@ -1,5 +1,7 @@ #include "Renderables.h" +#include "LightNode.h" + void light_draw_box_lines(const Vector3& origin, const Vector3 points[8]) { //draw lines from the center of the bbox to the corners glBegin(GL_LINES); @@ -174,6 +176,19 @@ void RenderLightProjection::render(const RenderInfo& info) const } } +namespace +{ + +inline void applyTransform(std::vector& vertices, const Matrix4& transform) +{ + for (auto& vertex : vertices) + { + vertex.vertex = transform * vertex.vertex; + } +} + +} + void RenderableLightOctagon::updateGeometry() { if (!_needsUpdate) return; @@ -201,11 +216,7 @@ void RenderableLightOctagon::updateGeometry() }; // Orient the points using the transform - const auto& orientation = _owner.localToWorld(); - for (auto& vertex : vertices) - { - vertex.vertex = orientation * vertex.vertex; - } + applyTransform(vertices, _light.localToWorld()); // Indices are always the same, therefore constant static const std::vector Indices @@ -229,7 +240,81 @@ void RenderableLightVolume::updateGeometry() _needsUpdate = false; - // TODO + if (_light.isProjected()) + { + updateProjectedLightVolume(); + } + else + { + updatePointLightVolume(); + } +} + +void RenderableLightVolume::updatePointLightVolume() +{ + +} + +void RenderableLightVolume::updateProjectedLightVolume() +{ + const auto& frustum = _light.getLightFrustum(); + + // greebo: These four define the base area and are always needed to draw the light + auto backUpperLeft = frustum.getCornerPoint(Frustum::BACK, Frustum::TOP_LEFT); + auto backLowerLeft = frustum.getCornerPoint(Frustum::BACK, Frustum::BOTTOM_LEFT); + auto backUpperRight = frustum.getCornerPoint(Frustum::BACK, Frustum::TOP_RIGHT); + auto backLowerRight = frustum.getCornerPoint(Frustum::BACK, Frustum::BOTTOM_RIGHT); + +#if 0 + if (_start != Vector3(0, 0, 0)) + { + // Calculate the vertices defining the top area + Vector3 frontUpperLeft = _frustum.getCornerPoint(Frustum::FRONT, Frustum::TOP_LEFT); + Vector3 frontLowerLeft = _frustum.getCornerPoint(Frustum::FRONT, Frustum::BOTTOM_LEFT); + Vector3 frontUpperRight = _frustum.getCornerPoint(Frustum::FRONT, Frustum::TOP_RIGHT); + Vector3 frontLowerRight = _frustum.getCornerPoint(Frustum::FRONT, Frustum::BOTTOM_RIGHT); + + frontUpperLeft += _origin; + frontLowerLeft += _origin; + frontUpperRight += _origin; + frontLowerRight += _origin; + + Vector3 frustum[8] = { frontUpperLeft, frontLowerLeft, frontLowerRight, frontUpperRight, + backUpperLeft, backLowerLeft, backLowerRight, backUpperRight }; + drawFrustum(frustum); + } + else +#endif + { + // no light_start, just use the top vertex (doesn't need to be mirrored) + auto top = Plane3::intersect(frustum.left, frustum.right, frustum.top); + + std::vector vertices + { + ArbitraryMeshVertex(top, {1,0,0}, {0,0}), + ArbitraryMeshVertex(backUpperLeft, {1,0,0}, {0,0}), + ArbitraryMeshVertex(backLowerLeft, {1,0,0}, {0,0}), + ArbitraryMeshVertex(backLowerRight, {1,0,0}, {0,0}), + ArbitraryMeshVertex(backUpperRight, {1,0,0}, {0,0}), + }; + + // Orient the points using the transform + applyTransform(vertices, _light.localToWorld()); + + static const std::vector Indices + { + 0, 1, // top to first + 0, 2, // top to second + 0, 3, // top to third + 0, 4, // top to fourth + 1, 2, // first to second + 2, 3, // second to third + 3, 4, // third to fourth + 4, 1, // fourth to first + }; + + RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, Indices); + } } -} // namespace entity +} // namespace diff --git a/radiantcore/entity/light/Renderables.h b/radiantcore/entity/light/Renderables.h index fde8f8e588..41176e6f09 100644 --- a/radiantcore/entity/light/Renderables.h +++ b/radiantcore/entity/light/Renderables.h @@ -45,12 +45,12 @@ class RenderableLightOctagon : public render::RenderableGeometry { private: - const scene::INode& _owner; + const LightNode& _light; bool _needsUpdate; public: - RenderableLightOctagon(const scene::INode& owner) : - _owner(owner), + RenderableLightOctagon(const LightNode& light) : + _light(light), _needsUpdate(true) {} @@ -85,6 +85,10 @@ class RenderableLightVolume : protected: void updateGeometry() override; + +private: + void updatePointLightVolume(); + void updateProjectedLightVolume(); }; } // namespace entity