-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
67 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Julia's Parametric Heart Surface Renderer | ||
|
||
C++ stdlib-only renderer that generates a sequence of images to create an | ||
animation of a rotating heart-shaped surface. B-day gift for @ainnnia :))) | ||
|
||
https://github.com/havaker/heart/assets/41525193/2af59099-dcb3-4ca0-b20c-47ac4a83a267 | ||
|
||
## How it Works | ||
|
||
[Julia's parametric heart surface](https://math.stackexchange.com/a/3935220) is defined by the following equations: | ||
```math | ||
\begin{align*} | ||
x &= \left(15 \sin{\left(u \right)} - 4 \sin{\left(3 u \right)}\right) \sin{\left(v \right)} \\ | ||
y &= 8 \cos{\left(v \right)} \\ | ||
z &= \left(15 \cos{\left(u \right)} - 5 \cos{\left(2 u \right)} - 2 \cos{\left(3 u \right)} - \cos{\left(4 u \right)}\right) \sin{\left(v \right)} | ||
\end{align*} | ||
``` | ||
|
||
Given a function $`f(u, v) = (x, y, z)`$ we can sample a point belonging to the heart surface by sampling $`(u, v) \in [0, 2 \pi] \times [0, \pi]`$. | ||
Drawing such point is done by a (somewhat) standard series of projections, that map a 3D point to 2D pixel coordinates. | ||
By sampling enough points, a high quality picture can be produced. | ||
|
||
### Code structure | ||
|
||
The heart surface is defined in a symbolic way in `src/codegen/generate.py`. | ||
|
||
Surface defning functions are generated via `sympy`'s C code generation and written | ||
to `src/codegen/surface.[c,h]`. The C++ renderer defined in `src/main.cc` uses | ||
these functions to render the heart surface. | ||
|
||
The renderer: | ||
- samples the heart surface in the parameter domain | ||
- applies a simplified Phong lighting model | ||
- projects the points onto a 2D plane, using z-buffer to determine visibility | ||
- outputs the rendered frames in PPM format | ||
|
||
For more details, see the comments in the source code. They should be quite | ||
verbose. | ||
|
||
## Running | ||
|
||
The simplest way to run the renderer is to use [Nix](https://nixos.org/): | ||
``` | ||
nix run github:havaker/heart#video heart.mp4 | ||
``` | ||
|
||
That command will fetch the source code, build the renderer, and render the | ||
animation video to `heart.mp4`. | ||
|
||
If you don't have Nix, you can still build the renderer manually using the | ||
provided `CmakeLists.txt` file. To render the animation, install `ffmpeg` and | ||
follow the steps described in the `flake.nix` file. | ||
|
||
## Development | ||
|
||
To develop the renderer, you can use the provided `flake.nix` file to create a | ||
development environment with all the necessary dependencies (Nix required). To | ||
enter the development environment, run `nix develop` in the cloned repository. | ||
|
||
In that environment, you can use the `./run.sh` script to build and run the | ||
preview animation. | ||
|
||
## Compatibility | ||
|
||
*x86-64 Linux* only. It should be possible to run the renderer on other platforms | ||
by simply modyfing the `system = "..."` line in `flake.nix`, but I haven't | ||
tested it. |