Reimplement dot + cross

This commit is contained in:
Michael Zhang 2023-02-15 19:22:17 -06:00
parent 000004404e
commit 0000045030
4 changed files with 62 additions and 12 deletions

View file

@ -5,6 +5,7 @@ use nalgebra::Vector3;
use crate::image::Color;
use crate::ray::Ray;
use crate::utils::cross;
use super::cylinder::Cylinder;
use super::illumination::IntersectionContext;
@ -134,8 +135,8 @@ impl Scene {
/// Determine the boundaries of the viewing window in world coordinates
pub fn compute_viewing_window(&self, distance: f64) -> Rect {
// Compute viewing directions
let u = self.view_dir.cross(&self.up_dir).normalize();
let v = u.cross(&self.view_dir).normalize();
let u = cross(self.view_dir, self.up_dir).normalize();
let v = cross(u, self.view_dir).normalize();
// Compute dimensions of viewing window based on field of view
let viewing_width = {

View file

@ -8,7 +8,7 @@ use rayon::prelude::{
ParallelIterator,
};
use crate::{image::Color, ray::Ray};
use crate::{image::Color, ray::Ray, utils::dot};
use super::{
data::{DepthCueing, Light, LightKind, Object},
@ -53,12 +53,11 @@ impl Scene {
let diffuse_component = material.k_d
* material.diffuse_color
* normal.dot(&light_direction).max(0.0);
* dot(normal, light_direction).max(0.0);
let specular_component = material.k_s
* material.specular_color
* normal
.dot(&halfway_direction)
* dot(normal, halfway_direction)
.max(0.0)
.powf(material.exponent);

View file

@ -24,6 +24,21 @@ where
.map(|i| i.into_inner())
}
/// Dot-product between two 3D vectors.
#[inline]
pub fn dot(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
a.x * b.x + a.y * b.y + a.z * b.z
}
/// Cross-product between two 3D vectors.
#[inline]
pub fn cross(a: Vector3<f64>, b: Vector3<f64>) -> Vector3<f64> {
let x = a.y * b.z - a.z * b.y;
let y = a.z * b.x - a.x * b.z;
let z = a.x * b.y - a.y * b.x;
Vector3::new(x, y, z)
}
/// Calculate the rotation matrix between the 2 given vectors
///
/// Based on the method given [here][1].
@ -39,15 +54,15 @@ pub fn compute_rotation_matrix(
return Ok(Matrix3::identity());
}
let cos_t = a.dot(&b);
let sin_t = a.cross(&b).norm();
let cos_t = dot(a, b);
let sin_t = cross(a, b).norm();
let g = Matrix3::new(cos_t, -sin_t, 0.0, sin_t, cos_t, 0.0, 0.0, 0.0, 1.0);
// New basis vectors
let u = a;
let v = (b - a.dot(&b) * a).normalize();
let w = b.cross(&a);
let v = (b - cos_t * a).normalize();
let w = cross(b, a);
// Not sure if this is required to be invertible?
let f_inverse = Matrix3::from_columns(&[u, v, w]);
@ -56,8 +71,9 @@ pub fn compute_rotation_matrix(
None => {
// So I ran into this case trying to compute the rotation matrix where one
// of the vector endpoints was (0, 0, 0). I'm pretty sure this case makes
// no sense in reality, so going to just error out here and screw
// recovering.
// no sense in reality, which means if I ever encounter this case, I
// probably made a mistake somewhere before. So going to just error
// out here and screw recovering.
//
// println!("Failed to compute inverse matrix.");
// println!("- Initial: a = {a}, b = {b}");

View file

@ -0,0 +1,34 @@
class Point:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __sub__(self, o):
return Point(self.x - o.x, self.y - o.y, self.z - o.z)
def __str__(self):
return f"({self.x}, {self.y}, {self.z})"
def cross(self, o):
x = self.y * o.z - self.z * o.y
y = self.z * o.x - self.x * o.z
z = self.x * o.y - self.y * o.x
return Point(x, y, z)
p0 = Point(1, 1, 0)
p1 = Point(0, 1, 1)
p2 = Point(1, 0, 1)
e1 = p1 - p0
print(e1)
e2 = p2 - p0
print(e2)
n = e1.cross(e2)
print(n)
# Find A, B, C and D
D = -(n.x * p0.x + n.y * p0.y + n.z * p0.z)
print(n.x, n.y, n.z, D)