diff options
| Commit | bdea637d395c14a30c9961947b027ffe66394bfc (patch) | |
|---|---|---|
| Author | 2024-07-02 11:08:22 +0300 | |
| Committer | 2024-07-02 11:08:22 +0300 | |
| Files | 08639bd9f506cca5aa83a46e4fb2556c77a45a36 | |
| uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.tar uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.tar.gz uni-projects-bdea637d395c14a30c9961947b027ffe66394bfc.zip | ||
| Parent | d942e135e502ee409222b9389a5a03b3f2861582 (diff) | |
[Ray/project-medium] Added solution
1 files changed, 487 insertions, 0 deletions
| -rw-r--r-- | Year 3/Raytracing/9002-project-medium-Impelemented-PointClouds.patch | 487 |
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 + |
