Semester 1, Week 08 Development - 62firelight/manimRT-490 GitHub Wiki
What's New
Finished Features
- As a user, I want to...
- Apply a linear transformation to the ray (inverse of an object's transformation)
- NOTE: Translations were supported before, but rotation and scaling transformations are now supported. This required me to create a new RTSphere class which is similar to the Sphere mobject in Manim, but will now keep track of the transformations that were applied to it. Note that the RTSphere is currently considered immutable in the sense that you can't (or shouldn't) apply any more transformations after it has been created without breaking its functionality.
- Apply a linear transformation to the ray (inverse of an object's transformation)
Literature Review Update
I have updated the summaries for the papers in the literature review. They can be found just after the reference for each paper. Ideally, they would be bullet points but I'm not sure how to format them that way yet.
The link to the literature review on Overleaf can be found here.
Feature Showcase
Ray Intersection with a Transformed Sphere
from manim import *
from manim_rt.RTSphere import RTSphere
from manim_rt.Ray3D import Ray3D
class RTSphereTest(ThreeDScene):
def construct(self):
axes = ThreeDAxes(z_range=(-4, 8, 1))
labels = axes.get_axis_labels()
translation = [0.25, 1.5, 1]
x_scale = 3
y_scale = 0.5
z_scale = 2
x_rotation = 75 * DEGREES
y_rotation = 45 * DEGREES
z_rotation = 90 * DEGREES
sphere = RTSphere(translation, x_scale, y_scale, z_scale, x_rotation, y_rotation, z_rotation)
red_ray = Ray3D(ORIGIN, OUT, 4, color=RED)
hit_points = red_ray.get_intersection(sphere)
for hit_point in hit_points:
hit_point_obj = Dot3D(hit_point)
self.add(hit_point_obj)
y_label = MathTex("y").next_to(axes.get_y_axis().get_end(), buff=0.5)
z_label = MathTex("z").next_to(axes.get_z_axis().get_end(), buff=0.75)
ray_text = MathTex("\\text{Red Ray: }" + red_ray.get_equation())
sphere_text = Tex("Sphere Transformations:")
scale_text = MathTex(f"\\text{{Scaled by [{x_scale}, {y_scale}, {z_scale}]}}", font_size=39)
rotation_text = MathTex(f"\\text{{Rotated by [{x_rotation / DEGREES}, {y_rotation / DEGREES}, {z_rotation / DEGREES}] (deg)}}", font_size=39)
translation_text = MathTex(f"\\text{{Translated to }} {str(translation)}", font_size=39)
self.set_camera_orientation(phi=60 * DEGREES, theta=-20 * DEGREES, frame_center=[0, 0, 2])
top_left_group_text = VGroup(ray_text, sphere_text, scale_text, rotation_text, translation_text).arrange(DOWN, center=False, aligned_edge=LEFT).to_corner(UL)
self.add(axes, sphere, red_ray)
self.add_fixed_in_frame_mobjects(top_left_group_text)
self.add_fixed_orientation_mobjects(y_label, z_label)
Issues
Strange Layering Issue With Animations
As in the prototype, there is still an annoying bug where Manim mobjects appear in front of the sphere during their animation, but then correct themselves once the next animation starts. See the video below for what I mean:
https://github.com/62firelight/manimRT-490/assets/54054879/7d700193-5fee-41d4-a124-bfb57ce53310
There might be some ways to get around this. One way may be to animate part of the ray as a line as it shoots out to its first intersection point with the sphere, and then to animate the rest of the ray as it shoots out of the second intersection point. Unfortunately, this still doesn't stop the Dot3D mobjects from forcing themselves in front of the sphere.
Questions
- When inserting parameters to make an RTSphere, should the scale and rotation parameters (x_scale, y_scale, z_scale, etc) remain individual parameters per axis or should they be grouped together (having [x_scale, y_scale, z_scale] as a list parameter for example)? It seems annoying to have to type out parameters you might not want to change, but it's probably not an issue because Python allows you to ignore the parameter order and simply type the name of the parameter you want to set out. Not to mention, the parameters can be set to default values (x_scale to 1 or x_rotation to 0 for example).
- What's the best way to represent vectors? 3blue1brown uses an arrow shooting right above a letter to represent a vector (at least in his linear algebra series), but this might not work if we also want "hats" to represent normalized vectors.
- Is it more intuitive to call a get_intersection() method on the ray or the object it may or may not intersect? Currently, it is called on the ray e.g.
hit_points = ray.get_intersection(sphere)
. I don't think it would be a hard task to re-implement this so that it is called on the object instead. - Should RT objects like RTSphere remain immutable in the sense you can't apply any further transformations to them?
To-Do List
More user stories have been added for Sprint 2 - Lighting Computations and Shadows. The user stories spreadsheet can be found here.
I am no longer using italics to indicate objectives carried over from past posts as it's rather painful to add multiple of these using GitHub's markdown editor.
From highest to lowest priority:
- As a user I want to...
- print a LaTeX equation for the Phong Illumination Model so I can illustrate the main equation required for lighting in a ray tracer
- get a normal vector with a unit length (n hat) to any surface that a ray hits so I can calculate diffuse lighting
- create a Manim mobject representing a point light source so I can easily illustrate lighting concepts in a scene
- get a normalized vector that points towards a light source (l hat) in a scene so I can calculate diffuse lighting and shadows
- get a normalized vector that is the reflection of the vector that points towards a light source in a scene (r hat) so I can calculate specular lighting
- get a normalized vector that points towards the viewer of a scene (v hat) so I can calculate specular lighting
- print a LaTeX equation for the Phong Illumination Model with multiple light sources so I can illustrate what happens when multiple light sources are used in a ray tracer
- print a LaTeX equation for the Phong Illumination Model with multiple light sources and different light intensities so I can illustrate what happens with different colour intensities in a ray tracer
- shoot a ray from a known hit point towards a light source to check for intersections so I can illustrate shadows
- create a Manim mobject representing a human eye so I can introduce ray-tracing by comparing it with how humans perceive light
- calculate the intensity of light from a light source for any point in the scene so I can calculate diffuse lighting
- Develop full animation video for illustrating ray-object intersections
- As a developer I want to add a new object (other than spheres) that rays can intersect so that I can teach ray-tracing for different objects in my scene
- Add docstrings to created classes and their methods
- Add option to initialize camera grid with x value and aspect ratio
- Generate spheres that intersect the ray at different points (2 intersection points + 1 intersection + no intersection)