Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commitbdea637d395c14a30c9961947b027ffe66394bfc (patch)
Author
 Syndamia <kamen@syndamia.com>
2024-07-02 11:08:22 +0300
Committer
 Syndamia <kamen@syndamia.com>
2024-07-02 11:08:22 +0300
Files08639bd9f506cca5aa83a46e4fb2556c77a45a36
uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.tar
uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.tar.gz
uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.zip
Parentd942e135e502ee409222b9389a5a03b3f2861582 (diff)
[Ray/project-medium] Added solution
1 files changed, 487 insertions, 0 deletions
-rw-r--r--Year 3/Raytracing/9002-project-medium-Impelemented-PointClouds.patch487
diff --git a/Year 3/Raytracing/9002-project-medium-Impelemented-PointClouds.patch b/Year 3/Raytracing/9002-project-medium-Impelemented-PointClouds.patch
new file mode 100644
index 0000000..be7b131
--- /dev/null
+++ b/Year 3/Raytracing/9002-project-medium-Impelemented-PointClouds.patch
@@ -0,0 +1,487 @@
+From 7eee648883aeda494734e59c41c97c21691a200d Mon Sep 17 00:00:00 2001
+From: Syndamia <kamen@syndamia.com>
+Date: Mon, 1 Jul 2024 16:17:36 +0300
+Subject: [PATCH] [project-medium] Impelemented PointClouds
+
+---
+ data/pointcloud.hexray | 175 +++++++++++++++++++++++++++++++++++++++++
+ flake.lock | 27 +++++++
+ flake.nix | 26 ++++++
+ src/main.cpp | 2 +-
+ src/mesh.cpp | 163 ++++++++++++++++++++++++++++++++++++++
+ src/mesh.h | 9 ++-
+ src/scene.cpp | 1 +
+ 7 files changed, 401 insertions(+), 2 deletions(-)
+ create mode 100644 data/pointcloud.hexray
+ create mode 100644 flake.lock
+ create mode 100644 flake.nix
+
+diff --git a/data/pointcloud.hexray b/data/pointcloud.hexray
+new file mode 100644
+index 0000000..2c60cb5
+--- /dev/null
++++ b/data/pointcloud.hexray
+@@ -0,0 +1,175 @@
++//
++
++// 1. First, some global settings
++GlobalSettings {
++ frameWidth 960
++ frameHeight 540
++ ambientLight (0.28, 0.30, 0.35)
++ maxTraceDepth 5
++ wantAA off
++ prepassSamples 0
++ interactive on
++ //foveatedRadius 75
++}
++
++PointLight {
++ pos (160, 80, 40)
++ color (1, 1, 1)
++ power 10000
++}
++
++// 2. A camera
++// (to enable the spherical lens camera (which introduces heavy spherical abberation)), replace "Camera" with "SphericalLensCamera"
++
++Camera camera {
++ pos (120, 22, 60)
++ yaw 11.46
++ pitch -15
++ roll 0.0
++ fov 100
++ aspectRatio 1.777
++ //stereoSeparation 0.25 // comment this out to disable the stereoscopic effect
++ dof off
++ numSamples 100
++ fNumber 5.6
++ autoFocus off
++ focalPlaneDist 21.48
++}
++
++/*
++// top view
++Camera camera {
++ pos (130, 85, 75)
++ yaw 11.46
++ pitch -90
++ roll 0.0
++ fov 90
++ aspect 1.333
++}
++*/
++
++/// Floor ///
++
++Plane floor {
++ y 0
++ limit 64
++}
++
++CheckerTexture checker {
++ color1 (0.5, 0.5, 0.25)
++ color2 (0.25, 0.25, 0.25)
++ scaling 8
++}
++
++Lambert floorShader {
++ color (1, 1, 1)
++ texture checker
++}
++
++// 3. A floor node, using a plane as a geometry, and a flat shader with a checker texture
++Node floorNode {
++ geometry floor
++ shader floorShader
++ translate (100, 0, 96)
++}
++
++/// Dice ///
++
++Mesh dice {
++ file "geom/truncated_cube.obj"
++ faceted true
++}
++
++BumpTexture diceBump {
++ file "texture/zar-bump.bmp"
++ strength 5
++}
++
++BitmapTexture dice_texture {
++ file "texture/zar-texture.bmp"
++ scaling 1
++}
++
++Lambert flat {
++ color (1,1,1)
++ texture dice_texture
++}
++
++/// Wineglass ///
++
++PointCloud wineglass {
++ file "geom/newwine.obj"
++ backfaceCulling false
++}
++
++Phong white_flat {
++ color (0.7, 0.7, 0.7)
++ exponent 200
++}
++
++Reflection reflection {
++ multiplier 0.96
++}
++
++Refraction refraction {
++ ior 1.5
++ multiplier 0.96
++}
++
++Fresnel fresnel {
++ ior 1.5
++}
++
++Layered glass {
++ layer refraction (1, 1, 1)
++ layer reflection (1, 1, 1) fresnel
++}
++
++Node wineglass {
++ geometry wineglass
++ shader white_flat
++ //shader glass
++ translate (126, 0, 80)
++ scale (17, 17, 17)
++}
++
++/// Teapot ///
++
++
++PointCloud teapot {
++ file "geom/teapot_hires.obj"
++}
++
++CheckerTexture teapot_checker {
++ color1 (0.9, 0.1, 0.1)
++ color2 (0.05, 0.05, 0.07)
++ scaling 0.1
++}
++
++Phong teapot_lambert {
++ color (1, 1, 1)
++ texture teapot_checker
++ exponent 30
++}
++
++Layered teapot_layered {
++ layer teapot_lambert (1, 1, 1)
++ layer white_flat (0.16, 0.16, 0.16)
++ layer reflection (0.05, 0.07, 0.09)
++}
++
++Node teapotNode {
++ geometry teapot
++ //shader teapot_layered
++ shader teapot_lambert
++ translate (110, 19, 90)
++ rotate (-27, 0, 30)
++ scale (7.5, 7.5, 7.5)
++}
++
++
++
++// 5. The cubemap environment:
++CubemapEnvironment environment {
++ folder "env/forest"
++}
+diff --git a/flake.lock b/flake.lock
+new file mode 100644
+index 0000000..25db693
+--- /dev/null
++++ b/flake.lock
+@@ -0,0 +1,27 @@
++{
++ "nodes": {
++ "nixpkgs": {
++ "locked": {
++ "lastModified": 1716061101,
++ "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=",
++ "owner": "nixos",
++ "repo": "nixpkgs",
++ "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2",
++ "type": "github"
++ },
++ "original": {
++ "owner": "nixos",
++ "ref": "nixos-23.11",
++ "repo": "nixpkgs",
++ "type": "github"
++ }
++ },
++ "root": {
++ "inputs": {
++ "nixpkgs": "nixpkgs"
++ }
++ }
++ },
++ "root": "root",
++ "version": 7
++}
+diff --git a/flake.nix b/flake.nix
+new file mode 100644
+index 0000000..d0a99fd
+--- /dev/null
++++ b/flake.nix
+@@ -0,0 +1,26 @@
++# Този файл, заедно с flake.lock са си за моета система, да имам копие ако случайно изтрия нещо
++{
++ description = "hexray raytracer in FMI elective";
++
++ inputs = {
++ nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
++ };
++
++ outputs = inputs:
++ let
++ pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux";
++ in {
++ devShells."x86_64-linux".default = pkgs.mkShell {
++ nativeBuildInputs = with pkgs; [
++ cmake
++ pkg-config
++ ];
++
++ buildInputs = with pkgs; [
++ SDL2
++ openexr_3
++ zlib
++ ];
++ };
++ };
++}
+diff --git a/src/main.cpp b/src/main.cpp
+index fdca0f5..61386f3 100644
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -525,7 +525,7 @@ void renderThreadEntry() {
+ }
+ }
+
+-const char* DEFAULT_SCENE = "data/simple.hexray";
++const char* DEFAULT_SCENE = "data/pointcloud.hexray";
+
+ int main(int argc, char** argv)
+ {
+diff --git a/src/mesh.cpp b/src/mesh.cpp
+index 36ea203..9bf3ea2 100644
+--- a/src/mesh.cpp
++++ b/src/mesh.cpp
+@@ -394,3 +394,166 @@ void Mesh::prepareTriangles()
+ t.dNdy.normalize();
+ }
+ }
++
++/* Triangle operations */
++
++Vector triangleNormal(const Triangle& t, const std::vector<Vector>& points) {
++ return normalize((points[t.v[1]] - points[t.v[0]]) ^ (points[t.v[2]] - points[t.v[0]]));
++}
++
++bool operator==(const Triangle& lhs, const Triangle& rhs) {
++ return
++ (lhs.v[0] == rhs.v[0] || lhs.v[0] == rhs.v[1] || lhs.v[0] == rhs.v[2]) &&
++ (lhs.v[1] == rhs.v[0] || lhs.v[1] == rhs.v[1] || lhs.v[1] == rhs.v[2]) &&
++ (lhs.v[2] == rhs.v[0] || lhs.v[2] == rhs.v[1] || lhs.v[2] == rhs.v[2]);
++}
++
++/* Closest two points */
++
++struct ClosePoint {
++ int index = -1;
++ double distance = INFINITY;
++
++ ClosePoint& operator=(const ClosePoint& rhs) {
++ this->index = rhs.index;
++ this->distance = rhs.distance;
++ return *this;
++ }
++
++ friend bool operator<(const ClosePoint& lhs, const ClosePoint& rhs) {
++ return lhs.distance < rhs.distance;
++ }
++};
++
++std::pair<int, int> closestTwoPoints(const Vector& p, const std::vector<Vector>& points, const std::vector<bool>& unavailable) {
++ ClosePoint first, second;
++ for (ClosePoint curr = { 0 }; curr.index < points.size(); curr.index++) {
++ if (unavailable[curr.index]) continue;
++
++ curr.distance = (p - points[curr.index]).length();
++ // curr == p
++ if (curr.distance < 0.00001) continue;
++
++ // would first, second and p form a (left-direction) triangle
++ bool perpenToFirst = first.index != -1;
++ if (perpenToFirst) {
++ double dotp = dot(normalize(p - points[first.index]), normalize(p - points[curr.index]));
++ perpenToFirst = 0.0 < dotp && dotp < 0.2;
++ }
++
++ if (curr < first) {
++ if (perpenToFirst)
++ second = first;
++ first = curr;
++ }
++ else if (curr < second && perpenToFirst) {
++ second = curr;
++ }
++ }
++ return { first.index, second.index };
++}
++
++/* Generate triangles */
++
++struct MarkedVertices {
++private:
++ int size;
++public:
++ std::vector<bool> markings;
++ int total;
++
++ MarkedVertices(int size) {
++ this->size = size;
++ markings = std::vector<bool>(size, false);
++ total = 0;
++ }
++
++ bool all() {
++ return total >= size;
++ }
++
++ void add(int index) {
++ markings[index] = true;
++ total++;
++ }
++
++ void clear() {
++ markings.assign(size, false);
++ total = 0;
++ }
++};
++
++void PointCloud::generateTriangles() {
++ MarkedVertices unavailable(vertices.size());
++ std::pair<int, int> triangleForming;
++ bool validTriangle;
++ Triangle t;
++ t.t[0] = 0; t.t[1] = 0; t.t[2] = 0;
++
++ for (int i = 0; i < vertices.size(); i++) {
++ t.v[0] = i;
++
++ unavailable.clear();
++ do {
++ validTriangle = false;
++
++ triangleForming = closestTwoPoints(vertices[i], vertices, unavailable.markings);
++ if (triangleForming.first < 0 || triangleForming.second < 0) break;
++
++ t.v[1] = triangleForming.first;
++ t.v[2] = triangleForming.second;
++ unavailable.add(triangleForming.first);
++ unavailable.add(triangleForming.second);
++
++ validTriangle = true;
++
++ for (const Triangle& ct : triangles) {
++ if (ct == t) {
++ validTriangle = false;
++ break;
++ }
++ }
++ } while (!validTriangle && !unavailable.all());
++
++ if (validTriangle) {
++ triangles.push_back(t);
++ }
++ }
++}
++
++bool PointCloud::loadFromOBJ(const char* filename)
++{
++ FILE* f = fopen(filename, "rt");
++
++ if (!f) return false;
++
++ Vector sentinel(0, 0, 0);
++ vertices = {sentinel};
++ normals = {sentinel};
++ uvs = {sentinel};
++
++ char line[10000];
++ while (fgets(line, sizeof(line), f)) {
++ if (line[0] == '#') continue;
++ //
++ std::vector<std::string> tokens = tokenize(line);
++ if (tokens.empty()) continue;
++ //
++ if (tokens[0] == "v") {
++ vertices.push_back(Vector(
++ toDouble(tokens[1]),
++ toDouble(tokens[2]),
++ toDouble(tokens[3])
++ ));
++ continue;
++ }
++ }
++
++ fclose(f);
++
++ printf("Calculating triangle mesh for %s...\n", filename);
++ generateTriangles();
++
++ prepareTriangles();
++ return true;
++}
+diff --git a/src/mesh.h b/src/mesh.h
+index e300d6a..f8f0e5c 100644
+--- a/src/mesh.h
++++ b/src/mesh.h
+@@ -94,7 +94,7 @@ public:
+
+ ~Mesh();
+
+- bool loadFromOBJ(const char* filename);
++ virtual bool loadFromOBJ(const char* filename);
+
+ void baseProperties(ParsedBlock& pb)
+ {
+@@ -122,3 +122,10 @@ public:
+
+ virtual bool intersect(const Ray& ray, IntersectionInfo& info) override;
+ };
++
++class PointCloud : public Mesh {
++ void generateTriangles();
++
++public:
++ virtual bool loadFromOBJ(const char* filename) override;
++};
+diff --git a/src/scene.cpp b/src/scene.cpp
+index e319eeb..410129d 100644
+--- a/src/scene.cpp
++++ b/src/scene.cpp
+@@ -798,6 +798,7 @@ SceneElement* DefaultSceneParser::newSceneElement(const char* className)
+ if (!strcmp(className, "CubemapEnvironment")) return new CubemapEnvironment;
+ if (!strcmp(className, "Camera")) return new Camera;
+ if (!strcmp(className, "Mesh")) return new Mesh;
++ if (!strcmp(className, "PointCloud")) return new PointCloud;
+ if (!strcmp(className, "Heightfield")) return new Heightfield;
+ if (!strcmp(className, "BumpTexture")) return new BumpTexture;
+ if (!strcmp(className, "Bumps")) return new Bumps;
+--
+2.42.0
+