From 491a80e18262c45ce3f1e07a6fc011a3e4caf3da Mon Sep 17 00:00:00 2001 From: squee72564 Date: Tue, 12 Aug 2025 14:51:47 -0700 Subject: [PATCH 1/2] Update README.md to include more detailed build requirement instructions. In order to follow the build instructions exactly, it is recommended to follow the new build requirement information. This means using Visual Studio with the appropriate C++ workload for Windows, and following the guide for the dependencies on Mac / Linux. --- README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b10b37a..22c75b5 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,34 @@ Thank you everyone for checking out the video, if you haven't it explains code i ## **Building Requirements:** -1. C++ Compiler supporting C++ 17 or newer +### Windows -2. [Cmake](https://cmake.org/) +* It is recommended that Windows users install [Microsoft Visual Studio](https://visualstudio.microsoft.com/downloads/) and choose to install the "Desktop development with C++" as it will give you access to all necessary build requirements and allow you to follow the build instructions directly. + +### macOS / Linux + +1. C++ Compiler supporting C++17 or newer + - **Linux**: `g++` or `clang++` is usually available via your system package manager (`apt`, `dnf`, `pacman`, etc.) + - **macOS**: Install via Xcode Command Line Tools with: `xcode-select --install` + +2. [CMake](https://cmake.org/) + - **Linux**: Available through your system package manager + - **macOS**: Install via [Homebrew](https://brew.sh): `brew install cmake` 3. [Vcpkg](https://vcpkg.io/en/) + - **Linux**: Not typically available via package managers — instead, **clone and bootstrap manually**: + ```bash + git clone https://github.com/microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ``` + - **macOS**: You can install the `vcpkg` executable via [Homebrew](https://formulae.brew.sh/formula/vcpkg): `brew install vcpkg` + > ⚠️ However, this does not clone the full source tree. You **must still clone the repo and run** `./bootstrap-vcpkg.sh` to get full vcpkg functionality. 4. [Git](https://git-scm.com/) + - **Linux**: Available via your package manager + - **macOS**: Pre-installed, or install via Homebrew: `brew install git` + ## **Build Instructions:** From 369c5ccc8475f7e3085437eea4aacaf98773e198 Mon Sep 17 00:00:00 2001 From: squee72564 Date: Tue, 12 Aug 2025 14:53:08 -0700 Subject: [PATCH 2/2] Changed unicode lambda symbol to '_lambda' in identifiers. This is due to a build error when using MSVC. Although this symbol in the identifier is technically allowed, it seems that certain compilers won't build with it. --- 2D_lensing.cpp | 38 +++++++++++++++++++------------------- CPU-geodesic.cpp | 32 ++++++++++++++++---------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/2D_lensing.cpp b/2D_lensing.cpp index f2f4e79..6486928 100644 --- a/2D_lensing.cpp +++ b/2D_lensing.cpp @@ -17,7 +17,7 @@ double c = 299792458.0; double G = 6.67430e-11; struct Ray; -void rk4Step(Ray& ray, double dλ, double rs); +void rk4Step(Ray& ray, double d_lambda, double rs); // --- Structs --- // struct Engine { @@ -109,8 +109,8 @@ struct Ray{ // step 3) store conserved quantities L = r*r * dphi; double f = 1.0 - SagA.r_s/r; - double dt_dλ = sqrt( (dr*dr)/(f*f) + (r*r*dphi*dphi)/f ); - E = f * dt_dλ; + double dt_d_lambda = sqrt( (dr*dr)/(f*f) + (r*r*dphi*dphi)/f ); + E = f * dt_d_lambda; // step 4) start trail : trail.push_back({x, y}); } @@ -146,10 +146,10 @@ struct Ray{ glDisable(GL_BLEND); } - void step(double dλ, double rs) { + void step(double d_lambda, double rs) { // 1) integrate (r,φ,dr,dφ) if(r <= rs) return; // stop if inside the event horizon - rk4Step(*this, dλ, rs); + rk4Step(*this, d_lambda, rs); // 2) convert back to cartesian x,y x = r * cos(phi); @@ -169,46 +169,46 @@ void geodesicRHS(const Ray& ray, double rhs[4], double rs) { double f = 1.0 - rs/r; - // dr/dλ = dr + // dr/d_lambda = dr rhs[0] = dr; - // dφ/dλ = dphi + // dφ/d_lambda = dphi rhs[1] = dphi; - // d²r/dλ² from Schwarzschild null geodesic: - double dt_dλ = E / f; + // d²r/d_lambda² from Schwarzschild null geodesic: + double dt_d_lambda = E / f; rhs[2] = - - (rs/(2*r*r)) * f * (dt_dλ*dt_dλ) + - (rs/(2*r*r)) * f * (dt_d_lambda*dt_d_lambda) + (rs/(2*r*r*f)) * (dr*dr) + (r - rs) * (dphi*dphi); - // d²φ/dλ² = -2*(dr * dphi) / r + // d²φ/d_lambda² = -2*(dr * dphi) / r rhs[3] = -2.0 * dr * dphi / r; } void addState(const double a[4], const double b[4], double factor, double out[4]) { for (int i = 0; i < 4; i++) out[i] = a[i] + b[i] * factor; } -void rk4Step(Ray& ray, double dλ, double rs) { +void rk4Step(Ray& ray, double d_lambda, double rs) { double y0[4] = { ray.r, ray.phi, ray.dr, ray.dphi }; double k1[4], k2[4], k3[4], k4[4], temp[4]; geodesicRHS(ray, k1, rs); - addState(y0, k1, dλ/2.0, temp); + addState(y0, k1, d_lambda/2.0, temp); Ray r2 = ray; r2.r=temp[0]; r2.phi=temp[1]; r2.dr=temp[2]; r2.dphi=temp[3]; geodesicRHS(r2, k2, rs); - addState(y0, k2, dλ/2.0, temp); + addState(y0, k2, d_lambda/2.0, temp); Ray r3 = ray; r3.r=temp[0]; r3.phi=temp[1]; r3.dr=temp[2]; r3.dphi=temp[3]; geodesicRHS(r3, k3, rs); - addState(y0, k3, dλ, temp); + addState(y0, k3, d_lambda, temp); Ray r4 = ray; r4.r=temp[0]; r4.phi=temp[1]; r4.dr=temp[2]; r4.dphi=temp[3]; geodesicRHS(r4, k4, rs); - ray.r += (dλ/6.0)*(k1[0] + 2*k2[0] + 2*k3[0] + k4[0]); - ray.phi += (dλ/6.0)*(k1[1] + 2*k2[1] + 2*k3[1] + k4[1]); - ray.dr += (dλ/6.0)*(k1[2] + 2*k2[2] + 2*k3[2] + k4[2]); - ray.dphi += (dλ/6.0)*(k1[3] + 2*k2[3] + 2*k3[3] + k4[3]); + ray.r += (d_lambda/6.0)*(k1[0] + 2*k2[0] + 2*k3[0] + k4[0]); + ray.phi += (d_lambda/6.0)*(k1[1] + 2*k2[1] + 2*k3[1] + k4[1]); + ray.dr += (d_lambda/6.0)*(k1[2] + 2*k2[2] + 2*k3[2] + k4[2]); + ray.dphi += (d_lambda/6.0)*(k1[3] + 2*k2[3] + 2*k3[3] + k4[3]); } diff --git a/CPU-geodesic.cpp b/CPU-geodesic.cpp index f94e8ae..6c95da2 100644 --- a/CPU-geodesic.cpp +++ b/CPU-geodesic.cpp @@ -102,7 +102,7 @@ struct Camera { Camera camera; struct Ray; -void rk4Step(Ray& ray, double dλ, double rs); +void rk4Step(Ray& ray, double d_lambda, double rs); struct Engine { // -- Quad & Texture render -- // @@ -290,12 +290,12 @@ struct Ray{ // Step 3: store conserved quantities L = r * r * sin(theta) * dphi; double f = 1.0 - SagA.r_s / r; - double dt_dλ = sqrt((dr*dr)/f + r*r*dtheta*dtheta + r*r*sin(theta)*sin(theta)*dphi*dphi); - E = f * dt_dλ; + double dt_d_lambda = sqrt((dr*dr)/f + r*r*dtheta*dtheta + r*r*sin(theta)*sin(theta)*dphi*dphi); + E = f * dt_d_lambda; } - void step(double dλ, double rs) { + void step(double d_lambda, double rs) { if (r <= rs) return; - rk4Step(*this, dλ, rs); + rk4Step(*this, d_lambda, rs); // convert back to cartesian this->x = r * sin(theta) * cos(phi); this->y = r * sin(theta) * sin(phi); @@ -328,7 +328,7 @@ void raytrace(vector& pixels, int W, int H) { const double D_LAMBDA = 1e7; const double ESCAPE_R = 1e14; - // 2) march the ray forward in λ + // 2) march the ray forward in _lambda vec3 color(0.0f); if (!useGeodesics) { double b = 2.0 * dot(camera.pos, dir); @@ -399,35 +399,35 @@ void addState(const double a[6], const double b[6], double factor, double out[6] for (int i = 0; i < 6; i++) out[i] = a[i] + b[i] * factor; } -void rk4Step(Ray& ray, double dλ, double rs) { +void rk4Step(Ray& ray, double d_lambda, double rs) { double y0[6] = { ray.r, ray.theta, ray.phi, ray.dr, ray.dtheta, ray.dphi }; double k1[6], k2[6], k3[6], k4[6], temp[6]; geodesicRHS(ray, k1, rs); - addState(y0, k1, dλ/2.0, temp); + addState(y0, k1, d_lambda/2.0, temp); Ray r2 = ray; r2.r = temp[0]; r2.theta = temp[1]; r2.phi = temp[2]; r2.dr = temp[3]; r2.dtheta = temp[4]; r2.dphi = temp[5]; geodesicRHS(r2, k2, rs); - addState(y0, k2, dλ/2.0, temp); + addState(y0, k2, d_lambda/2.0, temp); Ray r3 = ray; r3.r = temp[0]; r3.theta = temp[1]; r3.phi = temp[2]; r3.dr = temp[3]; r3.dtheta = temp[4]; r3.dphi = temp[5]; geodesicRHS(r3, k3, rs); - addState(y0, k3, dλ, temp); + addState(y0, k3, d_lambda, temp); Ray r4 = ray; r4.r = temp[0]; r4.theta = temp[1]; r4.phi = temp[2]; r4.dr = temp[3]; r4.dtheta = temp[4]; r4.dphi = temp[5]; geodesicRHS(r4, k4, rs); - ray.r += (dλ/6.0)*(k1[0] + 2*k2[0] + 2*k3[0] + k4[0]); - ray.theta += (dλ/6.0)*(k1[1] + 2*k2[1] + 2*k3[1] + k4[1]); - ray.phi += (dλ/6.0)*(k1[2] + 2*k2[2] + 2*k3[2] + k4[2]); - ray.dr += (dλ/6.0)*(k1[3] + 2*k2[3] + 2*k3[3] + k4[3]); - ray.dtheta += (dλ/6.0)*(k1[4] + 2*k2[4] + 2*k3[4] + k4[4]); - ray.dphi += (dλ/6.0)*(k1[5] + 2*k2[5] + 2*k3[5] + k4[5]); + ray.r += (d_lambda/6.0)*(k1[0] + 2*k2[0] + 2*k3[0] + k4[0]); + ray.theta += (d_lambda/6.0)*(k1[1] + 2*k2[1] + 2*k3[1] + k4[1]); + ray.phi += (d_lambda/6.0)*(k1[2] + 2*k2[2] + 2*k3[2] + k4[2]); + ray.dr += (d_lambda/6.0)*(k1[3] + 2*k2[3] + 2*k3[3] + k4[3]); + ray.dtheta += (d_lambda/6.0)*(k1[4] + 2*k2[4] + 2*k3[4] + k4[4]); + ray.dphi += (d_lambda/6.0)*(k1[5] + 2*k2[5] + 2*k3[5] + k4[5]); } void setupCameraCallbacks(GLFWwindow* window) {