extern crate mat4; extern crate vec3; extern crate vec4; use crate::object::Object; use crate::ray::Ray; use crate::sphere::Sphere; use sdl2::pixels::Color; fn put_pixel(data: &mut [u8], x: usize, y: usize, color: Color) { data[y * 3 * 800 + x * 3] = color.r; data[y * 3 * 800 + x * 3 + 1] = color.g; data[y * 3 * 800 + x * 3 + 2] = color.b; } pub fn render(data: &mut [u8], i: i32) { let sphere = Sphere {}; let forward = *vec3::transform_mat4( &mut vec3::new_zero(), &vec3::new(0. as f64, 0. as f64, -1. as f64), mat4::rotate( &mut mat4::new_zero(), &mat4::new_identity(), &0., &(3.141592 / 4.), &0., ), ); let view_matrix = *mat4::inv( &mut mat4::new_zero(), mat4::look_at( &mut mat4::new_zero(), &[100., 0., 100.], &[100. + forward[0], 0. + forward[1], 100. + forward[2]], &[0., 1., 0.], ), ); // let view_matrix = *mat4::look_at( // &mut mat4::new_zero(), // &[0., 0., 10.], // &[0., 0., 9.], // &[0., 1., 0.], // ); let scale = *mat4::scale( &mut mat4::new_zero(), &mat4::new_identity(), &vec3::new(1. / 3., 1. / 3., 1. / 3.), ); let translate = *mat4::translate( &mut mat4::new_zero(), &mat4::new_identity(), &vec3::new(-i as f64, -i as f64, 0.), ); let rotate = *mat4::transpose( &mut mat4::new_zero(), mat4::rotate(&mut mat4::new_zero(), &mat4::new_identity(), &0., &0., &0.), ); let model_matrix_tmp = *mat4::mul(&mut mat4::new_zero(), &scale, &rotate); let model_matrix1 = *mat4::mul(&mut mat4::new_zero(), &model_matrix_tmp, &translate); let mut origin = [0., 0., 0.]; let test = origin; vec3::transform_mat4(&mut origin, &test, &view_matrix); let test = origin; vec3::transform_mat4(&mut origin, &test, &model_matrix1); let mut prelight = [-10., 10., 0.]; let test = prelight; vec3::transform_mat4(&mut prelight, &test, &model_matrix1); for x in 0..800 { for y in 0..800 { let pi_4: f64 = 3.141592 / 8.; let dirx = (2. * ((x as f64 + 0.5) / 800.) - 1.) * pi_4.tan(); let diry = (1. - 2. * ((y as f64 + 0.5) / 800.)) * pi_4.tan(); let scalar = (dirx.powi(2) + diry.powi(2) + 1.).sqrt(); let mut ray = Ray { origin: origin, direction: [dirx / scalar, diry / scalar, -1. / scalar], }; let test = ray.direction; vec3::transform_mat4(&mut ray.direction, &test, &view_matrix); let test = ray.direction; vec3::transform_mat4(&mut ray.direction, &test, &model_matrix1); ray.direction[0] = ray.direction[0] - ray.origin[0]; ray.direction[1] = ray.direction[1] - ray.origin[1]; ray.direction[2] = ray.direction[2] - ray.origin[2]; let scalar = (ray.direction[0].powi(2) + ray.direction[1].powi(2) + ray.direction[2].powi(2)) .sqrt(); ray.direction = [ ray.direction[0] / scalar, ray.direction[1] / scalar, ray.direction[2] / scalar, ]; if x == 0 && y == 0 { println!("{:?}", ray); } let ray2 = ray; let mut distances = Vec::new(); distances.push(sphere.get_intersection(ray)); distances.push(None); let a = (distances[0], distances[1]); match a { (Some(dist), None) => { let n = [ ray.origin[0] + ray.direction[0] * dist, ray.origin[1] + ray.direction[1] * dist, ray.origin[2] + ray.direction[2] * dist, ]; let normal = sphere.get_normal(n); let light = [prelight[0] - n[0], prelight[1] - n[1], prelight[2] - n[2]]; let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt(); let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar]; let mut diffuse = normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2]; if diffuse < 0. { diffuse = 0.; } put_pixel( &mut *data, x, y, Color { r: (diffuse * 128. * 0.9 + 0.1 * 255.) as u8, g: 0, b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8, a: 0, }, ); } (None, Some(dist)) => { let n = [ ray2.origin[0] + ray2.direction[0] * dist, ray2.origin[1] + ray2.direction[1] * dist, ray2.origin[2] + ray2.direction[2] * dist, ]; let normal = sphere.get_normal(n); let light = [n[0] - 10., n[1] - 10., n[2] + 10.]; let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt(); let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar]; let mut diffuse = normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2]; if diffuse < 0. { diffuse = 0.; } put_pixel( &mut *data, x, y, Color { r: 0, g: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8, b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8, a: 0, }, ); } (Some(dist1), Some(dist2)) => { let n; if dist1 < dist2 { n = [ ray.origin[0] + ray.direction[0] * dist1, ray.origin[1] + ray.direction[1] * dist1, ray.origin[2] + ray.direction[2] * dist1, ]; } else { n = [ ray2.origin[0] + ray2.direction[0] * dist2, ray2.origin[1] + ray2.direction[1] * dist2, ray2.origin[2] + ray2.direction[2] * dist2, ]; } let normal = sphere.get_normal(n); let light = [n[0] - 10., n[1] - 10., n[2] + 10.]; let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt(); let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar]; let mut diffuse = normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2]; if diffuse < 0. { diffuse = 0.; } put_pixel( &mut *data, x, y, Color { r: 0, g: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8, b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8, a: 0, }, ); } (None, None) => { put_pixel( &mut *data, x, y, Color { r: 0, g: 0, b: 0, a: 0, }, ); } } } } }