Skip to content

Commit

Permalink
#5584: The simpler case (without start/end) of projected light volume…
Browse files Browse the repository at this point in the history
…s is displayed
  • Loading branch information
codereader committed Dec 5, 2021
1 parent 2e32d59 commit f7129bd
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
12 changes: 12 additions & 0 deletions radiantcore/entity/light/LightNode.cpp
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions radiantcore/entity/light/LightNode.h
Expand Up @@ -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.
Expand Down
99 changes: 92 additions & 7 deletions 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);
Expand Down Expand Up @@ -174,6 +176,19 @@ void RenderLightProjection::render(const RenderInfo& info) const
}
}

namespace
{

inline void applyTransform(std::vector<ArbitraryMeshVertex>& vertices, const Matrix4& transform)
{
for (auto& vertex : vertices)
{
vertex.vertex = transform * vertex.vertex;
}
}

}

void RenderableLightOctagon::updateGeometry()
{
if (!_needsUpdate) return;
Expand Down Expand Up @@ -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<unsigned int> Indices
Expand All @@ -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<ArbitraryMeshVertex> 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<unsigned int> 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
10 changes: 7 additions & 3 deletions radiantcore/entity/light/Renderables.h
Expand Up @@ -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)
{}

Expand Down Expand Up @@ -85,6 +85,10 @@ class RenderableLightVolume :

protected:
void updateGeometry() override;

private:
void updatePointLightVolume();
void updateProjectedLightVolume();
};

} // namespace entity

0 comments on commit f7129bd

Please sign in to comment.