First quick pass at loading OBJ files.
This commit is contained in:
parent
199b33f944
commit
3618636c42
|
|
@ -7,9 +7,12 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sdl2 = "0.32"
|
alga = "0.9"
|
||||||
|
itertools = "0.8"
|
||||||
|
obj = "0.9"
|
||||||
quickcheck = "0.9"
|
quickcheck = "0.9"
|
||||||
quickcheck_macros = "0.8"
|
quickcheck_macros = "0.8"
|
||||||
|
sdl2 = "0.32"
|
||||||
|
|
||||||
[dependencies.nalgebra]
|
[dependencies.nalgebra]
|
||||||
version = "0.19"
|
version = "0.19"
|
||||||
|
|
|
||||||
50
src/main.rs
50
src/main.rs
|
|
@ -7,15 +7,17 @@ use std::time::Duration;
|
||||||
|
|
||||||
use nalgebra::{Point3, Vector3};
|
use nalgebra::{Point3, Vector3};
|
||||||
|
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use vanrijn::camera::partial_render_scene;
|
use vanrijn::camera::partial_render_scene;
|
||||||
use vanrijn::colour::{ColourRgbF, NamedColour};
|
use vanrijn::colour::{ColourRgbF, NamedColour};
|
||||||
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper};
|
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper};
|
||||||
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
||||||
use vanrijn::mesh::Triangle;
|
use vanrijn::mesh::{load_obj, Triangle};
|
||||||
use vanrijn::raycasting::{Plane, Sphere};
|
use vanrijn::raycasting::{Intersect, Plane, Sphere};
|
||||||
use vanrijn::scene::Scene;
|
use vanrijn::scene::Scene;
|
||||||
|
|
||||||
fn update_texture(image: &ImageRgbU8, texture: &mut Texture) {
|
fn update_texture(image: &ImageRgbU8, texture: &mut Texture) {
|
||||||
|
|
@ -59,9 +61,20 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
)?;
|
)?;
|
||||||
let mut output_image = ImageRgbF::<f64>::new(image_width, image_height);
|
let mut output_image = ImageRgbF::<f64>::new(image_width, image_height);
|
||||||
|
|
||||||
let scene = Scene {
|
let scene = Arc::new(Scene {
|
||||||
camera_location: Point3::new(0.0, 0.0, 0.0),
|
camera_location: Point3::new(-2.0, 1.0, -5.0),
|
||||||
objects: vec![
|
objects: load_obj(
|
||||||
|
Path::new("/home/matthew/Downloads/bunny.obj"),
|
||||||
|
Arc::new(ReflectiveMaterial {
|
||||||
|
colour: ColourRgbF::from_named(NamedColour::Yellow),
|
||||||
|
diffuse_strength: 0.05,
|
||||||
|
reflection_strength: 0.9,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|triangle| Box::new(triangle) as Box<dyn Intersect<f64>>)
|
||||||
|
.chain(vec![
|
||||||
Box::new(Plane::new(
|
Box::new(Plane::new(
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
-2.0,
|
-2.0,
|
||||||
|
|
@ -69,17 +82,17 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
colour: ColourRgbF::new(0.55, 0.27, 0.04),
|
colour: ColourRgbF::new(0.55, 0.27, 0.04),
|
||||||
diffuse_strength: 0.1,
|
diffuse_strength: 0.1,
|
||||||
}),
|
}),
|
||||||
)),
|
)) as Box<dyn Intersect<f64>>,
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Point3::new(1.25, -0.5, 6.0),
|
Point3::new(-6.25, -0.5, 1.0),
|
||||||
1.0,
|
1.0,
|
||||||
Rc::new(LambertianMaterial {
|
Arc::new(LambertianMaterial {
|
||||||
colour: ColourRgbF::from_named(NamedColour::Green),
|
colour: ColourRgbF::from_named(NamedColour::Green),
|
||||||
diffuse_strength: 0.1,
|
diffuse_strength: 0.1,
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Point3::new(-1.25, -0.5, 6.0),
|
Point3::new(-4.25, -0.5, 2.0),
|
||||||
1.0,
|
1.0,
|
||||||
Rc::new(ReflectiveMaterial {
|
Rc::new(ReflectiveMaterial {
|
||||||
colour: ColourRgbF::from_named(NamedColour::Blue),
|
colour: ColourRgbF::from_named(NamedColour::Blue),
|
||||||
|
|
@ -88,7 +101,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Point3::new(0.0, 1.5, 6.0),
|
Point3::new(-5.0, 1.5, 1.0),
|
||||||
1.0,
|
1.0,
|
||||||
Rc::new(PhongMaterial {
|
Rc::new(PhongMaterial {
|
||||||
colour: ColourRgbF::from_named(NamedColour::Red),
|
colour: ColourRgbF::from_named(NamedColour::Red),
|
||||||
|
|
@ -97,20 +110,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
specular_strength: 1.0,
|
specular_strength: 1.0,
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
Box::new(Triangle {
|
])
|
||||||
vertices: [
|
.collect(),
|
||||||
Point3::new(1.25, -0.5, 6.0),
|
});
|
||||||
Point3::new(-1.25, -0.5, 6.0),
|
|
||||||
Point3::new(0.0, 1.5, 6.0),
|
|
||||||
],
|
|
||||||
normals: [Vector3::new(0.0, 0.0, 1.0); 3],
|
|
||||||
material: Rc::new(LambertianMaterial {
|
|
||||||
colour: ColourRgbF::from_named(NamedColour::Green),
|
|
||||||
diffuse_strength: 0.1,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut event_pump = sdl_context.event_pump()?;
|
let mut event_pump = sdl_context.event_pump()?;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
|
||||||
77
src/mesh.rs
77
src/mesh.rs
|
|
@ -1,10 +1,15 @@
|
||||||
use nalgebra::{Point3, RealField, Vector2, Vector3};
|
use nalgebra::{convert, Point3, RealField, Vector2, Vector3};
|
||||||
|
use obj::{IndexTuple, Obj, SimplePolygon};
|
||||||
|
|
||||||
use super::materials::Material;
|
use super::materials::Material;
|
||||||
use super::raycasting::{Intersect, IntersectionInfo, Ray};
|
use super::raycasting::{Intersect, IntersectionInfo, Ray};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use alga::general::SupersetOf;
|
||||||
|
use std::io::Result;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Triangle<T: RealField> {
|
pub struct Triangle<T: RealField> {
|
||||||
pub vertices: [Point3<T>; 3],
|
pub vertices: [Point3<T>; 3],
|
||||||
pub normals: [Vector3<T>; 3],
|
pub normals: [Vector3<T>; 3],
|
||||||
|
|
@ -76,6 +81,76 @@ impl<T: RealField> Intersect<T> for Triangle<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_vertex_and_normal<T: RealField>(
|
||||||
|
index_tuple: &IndexTuple,
|
||||||
|
vertex_positions: &Vec<[f32; 3]>,
|
||||||
|
normal_positions: &Vec<[f32; 3]>,
|
||||||
|
) -> (Point3<T>, Vector3<T>)
|
||||||
|
where
|
||||||
|
T: SupersetOf<f32>,
|
||||||
|
{
|
||||||
|
let &IndexTuple(vertex_index, _, maybe_normal_index) = index_tuple;
|
||||||
|
let vertex: Point3<T> = convert(Point3::from_slice(&vertex_positions[vertex_index]));
|
||||||
|
let normal = match maybe_normal_index {
|
||||||
|
Some(normal_index) => convert(Vector3::from_row_slice(&normal_positions[normal_index])),
|
||||||
|
None => Vector3::zeros(),
|
||||||
|
};
|
||||||
|
(vertex, normal)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_triangles<T: RealField>(
|
||||||
|
polygon: &SimplePolygon,
|
||||||
|
vertex_positions: &Vec<[f32; 3]>,
|
||||||
|
normal_positions: &Vec<[f32; 3]>,
|
||||||
|
material: Arc<dyn Material<T>>,
|
||||||
|
) -> Vec<Triangle<T>>
|
||||||
|
where
|
||||||
|
T: SupersetOf<f32>,
|
||||||
|
{
|
||||||
|
if let Some(v0_index) = polygon.iter().next() {
|
||||||
|
let (v0_vertex, v0_normal) =
|
||||||
|
get_vertex_and_normal(v0_index, &vertex_positions, &normal_positions);
|
||||||
|
polygon
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.zip(polygon.iter().skip(2))
|
||||||
|
.map(|(v1_index, v2_index)| {
|
||||||
|
let (v1_vertex, v1_normal) =
|
||||||
|
get_vertex_and_normal(v1_index, &vertex_positions, &normal_positions);
|
||||||
|
let (v2_vertex, v2_normal) =
|
||||||
|
get_vertex_and_normal(v2_index, &vertex_positions, &normal_positions);
|
||||||
|
let vertices = [v0_vertex, v1_vertex, v2_vertex];
|
||||||
|
let normals = [v0_normal, v1_normal, v2_normal];
|
||||||
|
Triangle {
|
||||||
|
vertices,
|
||||||
|
normals,
|
||||||
|
material: material.clone(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_obj<T: RealField>(
|
||||||
|
filename: &Path,
|
||||||
|
material: Arc<dyn Material<T>>,
|
||||||
|
) -> Result<Vec<Triangle<T>>>
|
||||||
|
where
|
||||||
|
T: SupersetOf<f32>,
|
||||||
|
{
|
||||||
|
let obj = Obj::<SimplePolygon>::load(filename)?;
|
||||||
|
|
||||||
|
Ok(obj
|
||||||
|
.objects
|
||||||
|
.iter()
|
||||||
|
.flat_map(|object| object.groups.iter())
|
||||||
|
.flat_map(|group| group.polys.iter())
|
||||||
|
.flat_map(|poly| get_triangles(poly, &obj.position, &obj.normal, material.clone()))
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
fn indices_with_index_of_largest_element_last<T: RealField>(v: &Vector3<T>) -> [usize; 3] {
|
fn indices_with_index_of_largest_element_last<T: RealField>(v: &Vector3<T>) -> [usize; 3] {
|
||||||
if v.x > v.y {
|
if v.x > v.y {
|
||||||
if v.z > v.x {
|
if v.z > v.x {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue