Skip to content

Commit

Permalink
feat: add light shape generators
Browse files Browse the repository at this point in the history
  • Loading branch information
Latios96 committed Dec 8, 2024
1 parent c1e6704 commit d4f8177
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/crayg/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ set(crayg_SRCS
scene/lights/Light.h
scene/lights/RectLight.cpp
scene/lights/RectLight.h
scene/lights/shapegenerators/AbstractLightShapeGenerator.cpp
scene/lights/shapegenerators/AbstractLightShapeGenerator.h
scene/lights/shapegenerators/DiskLightShapeGenerator.cpp
scene/lights/shapegenerators/DiskLightShapeGenerator.h
scene/lights/shapegenerators/RectLightShapeGenerator.cpp
scene/lights/shapegenerators/RectLightShapeGenerator.h
scene/primitives/GroundPlane.cpp
scene/primitives/GroundPlane.h
scene/primitives/PointInstancer.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "AbstractLightShapeGenerator.h"

namespace crayg {} // crayg
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "basics/Vector3f.h"
#include "scene/primitives/trianglemesh/TriangleMesh.h"

namespace crayg {

template <typename T> class AbstractLightShapeGenerator {
public:
AbstractLightShapeGenerator(const T &light);

virtual int getPointCount() = 0;
virtual int getIndicesCount() = 0;
virtual void generateShape(Vector3f *points, TriangleMesh::FaceVertexIndices *indices) = 0;

virtual ~AbstractLightShapeGenerator() = default;

protected:
T light;
};

template <typename T> AbstractLightShapeGenerator<T>::AbstractLightShapeGenerator(const T &light) : light(light) {
}

} // crayg
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "DiskLightShapeGenerator.h"

namespace crayg {

DiskLightShapeGenerator::DiskLightShapeGenerator(const DiskLight &light) : AbstractLightShapeGenerator(light) {
}

DiskLightShapeGenerator::DiskLightShapeGenerator(const DiskLight &light, int subdivisions)
: AbstractLightShapeGenerator(light), subdivisions(subdivisions) {
}

int DiskLightShapeGenerator::getPointCount() {
return subdivisions + 1;
}

int DiskLightShapeGenerator::getIndicesCount() {
return subdivisions;
}

void DiskLightShapeGenerator::generateShape(Vector3f *vertices, TriangleMesh::FaceVertexIndices *indices) {
generatePoints(vertices);
generateIndices(indices);
}

void DiskLightShapeGenerator::generatePoints(Vector3f *vertices) const {
const float epsilon = -0.001f;

const float radius = light.getRadius();

vertices[0] = Vector3f(0, 0, 0);

Vector3f pointOnBorder(-radius, 0, epsilon);
const float stepSize = 360.f / static_cast<float>(subdivisions);

for (int i = 1; i <= subdivisions; i++) {
vertices[i] = Transform::withRotation(0, 0, (i - 1) * stepSize).applyForPoint(pointOnBorder);
}

for (int i = 0; i < subdivisions - 1; i++) {
vertices[i] = light.getTransform().applyForPoint(vertices[i]);
}
}

void DiskLightShapeGenerator::generateIndices(TriangleMesh::FaceVertexIndices *indices) const {
for (int i = 0; i < subdivisions; i++) {
const int middlePointIndex = 0;
const int previousPointIndex = i + 1;
const int currentPointIndex = i + 2;
indices[i] = TriangleMesh::FaceVertexIndices(middlePointIndex, previousPointIndex, currentPointIndex);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "AbstractLightShapeGenerator.h"
#include "scene/lights/DiskLight.h"

namespace crayg {

class DiskLightShapeGenerator : public AbstractLightShapeGenerator<DiskLight> {
public:
explicit DiskLightShapeGenerator(const DiskLight &light);
DiskLightShapeGenerator(const DiskLight &light, int subdivisions);
int getPointCount() override;
int getIndicesCount() override;
void generateShape(Vector3f *points, TriangleMesh::FaceVertexIndices *indices) override;

private:
void generatePoints(Vector3f *vertices) const;
void generateIndices(TriangleMesh::FaceVertexIndices *indices) const;
int subdivisions = 64;
};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "RectLightShapeGenerator.h"

namespace crayg {

RectLightShapeGenerator::RectLightShapeGenerator(const RectLight &light) : AbstractLightShapeGenerator(light) {
}

int RectLightShapeGenerator::getPointCount() {
return POINT_COUNT;
}

int RectLightShapeGenerator::getIndicesCount() {
return FACE_COUNT;
}

void RectLightShapeGenerator::generateShape(Vector3f *vertices, TriangleMesh::FaceVertexIndices *indices) {
generatePoints(vertices);
generateIndices(indices);
}

void RectLightShapeGenerator::generatePoints(Vector3f *vertices) const {
const float epsilon = -0.001f;

const float halfWidth = light.getWidth() / 2.f;
const float halfHeight = light.getHeight() / 2.f;

vertices[0].x = -halfWidth;
vertices[0].y = -halfHeight;
vertices[0].z = epsilon;
vertices[1].x = -halfWidth;
vertices[1].y = halfHeight;
vertices[1].z = epsilon;
vertices[2].x = halfWidth;
vertices[2].y = halfHeight;
vertices[2].z = epsilon;
vertices[3].x = +halfWidth;
vertices[3].y = -halfHeight;
vertices[3].z = epsilon;

for (int i = 0; i < POINT_COUNT; i++) {
vertices[i] = light.getTransform().applyForPoint(vertices[i]);
}
}

void RectLightShapeGenerator::generateIndices(TriangleMesh::FaceVertexIndices *indices) const {
indices[0].v0 = 2;
indices[0].v1 = 1;
indices[0].v2 = 0;
indices[1].v0 = 3;
indices[1].v1 = 2;
indices[1].v2 = 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "AbstractLightShapeGenerator.h"
#include "scene/lights/RectLight.h"

namespace crayg {

class RectLightShapeGenerator : public AbstractLightShapeGenerator<RectLight> {
public:
explicit RectLightShapeGenerator(const RectLight &light);
int getPointCount() override;
int getIndicesCount() override;
void generateShape(Vector3f *points, TriangleMesh::FaceVertexIndices *indices) override;

private:
void generatePoints(Vector3f *vertices) const;
void generateIndices(TriangleMesh::FaceVertexIndices *indices) const;
static const int POINT_COUNT = 4;
static const int FACE_COUNT = 2;
};

}
2 changes: 2 additions & 0 deletions src/crayg/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ set(UNIT_TEST_SOURCE_LIST
TestConversionNodes.cpp
TestDebugIntegrator.cpp
TestDiskLight.cpp
TestDiskLightShapeGenerator.cpp
TestDtoUtils.cpp
TestEmbreeBvhBuilder.cpp
TestEmbreeSceneIntersector.cpp
Expand Down Expand Up @@ -93,6 +94,7 @@ set(UNIT_TEST_SOURCE_LIST
TestRaytracingIntegrator.cpp
TestReadableFormatter.cpp
TestRectLight.cpp
TestRectLightShapeGenerator.cpp
TestRegionToRender.cpp
TestRemainingTimeCalculator.cpp
TestRenderSettings.cpp
Expand Down
48 changes: 48 additions & 0 deletions src/crayg/tests/TestDiskLightShapeGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "scene/lights/shapegenerators/DiskLightShapeGenerator.h"
#include <catch2/catch.hpp>

namespace crayg {

TEST_CASE("DiskLightShapeGenerator::getPointCount") {

SECTION("should return correct point count") {
DiskLight diskLight;
DiskLightShapeGenerator diskLightShapeGenerator(diskLight, 8);

REQUIRE(diskLightShapeGenerator.getPointCount() == 9);
}
}

TEST_CASE("DiskLightShapeGenerator::getIndicesCount") {

SECTION("should return correct indices count") {
DiskLight diskLight;
DiskLightShapeGenerator diskLightShapeGenerator(diskLight, 8);

REQUIRE(diskLightShapeGenerator.getIndicesCount() == 8);
}
}

TEST_CASE("DiskLightShapeGenerator::generateShape") {

SECTION("should generate correct shape") {
DiskLight diskLight;
diskLight.setTransform(Transform::withPosition({0, 0, 0}));
diskLight.setRadius(2);

DiskLightShapeGenerator diskLightShapeGenerator(diskLight, 4);
std::vector<Vector3f> points(diskLightShapeGenerator.getPointCount());
std::vector<TriangleMesh::FaceVertexIndices> indices(diskLightShapeGenerator.getIndicesCount());

diskLightShapeGenerator.generateShape(points.data(), indices.data());

REQUIRE(points[0] == Vector3f(0, 0, 0));
for (int i = 1; i < points.size(); i++) {
REQUIRE(points[i].length() == Catch::Detail::Approx(2.0f));
}

REQUIRE(indices == std::vector<TriangleMesh::FaceVertexIndices>({{0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 4, 5}}));
}
}

}
46 changes: 46 additions & 0 deletions src/crayg/tests/TestRectLightShapeGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "scene/lights/shapegenerators/RectLightShapeGenerator.h"
#include <catch2/catch.hpp>

namespace crayg {

TEST_CASE("RectLightShapeGenerator::getPointCount") {

SECTION("should return correct point count") {
RectLight rectLight;
RectLightShapeGenerator rectLightShapeGenerator(rectLight);

REQUIRE(rectLightShapeGenerator.getPointCount() == 4);
}
}

TEST_CASE("RectLightShapeGenerator::getIndicesCount") {

SECTION("should return correct indices count") {
RectLight rectLight;
RectLightShapeGenerator rectLightShapeGenerator(rectLight);

REQUIRE(rectLightShapeGenerator.getIndicesCount() == 2);
}
}

TEST_CASE("RectLightShapeGenerator::generateShape") {

SECTION("should generate correct shape") {
RectLight rectLight;
rectLight.setTransform(Transform::withPosition({0, 1, 0}));
rectLight.setWidth(2);
rectLight.setHeight(3);

RectLightShapeGenerator rectLightShapeGenerator(rectLight);
std::vector<Vector3f> points(rectLightShapeGenerator.getPointCount());
std::vector<TriangleMesh::FaceVertexIndices> indices(rectLightShapeGenerator.getIndicesCount());

rectLightShapeGenerator.generateShape(points.data(), indices.data());

REQUIRE(points == std::vector<Vector3f>(
{{-1, -0.5f, -0.001f}, {-1, 2.5f, -0.001f}, {1, 2.5f, -0.001f}, {1, -0.5f, -0.001f}}));
REQUIRE(indices == std::vector<TriangleMesh::FaceVertexIndices>({{2, 1, 0}, {3, 2, 0}}));
}
}

}

0 comments on commit d4f8177

Please sign in to comment.