library: render: mesh: scale, rotate, & translate
The scaling factor is the same on all axis, to avoid having angles changed which would mess with the normals too much.
This commit is contained in:
parent
2d624c517f
commit
15381d4bbd
|
@ -1,7 +1,7 @@
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nalgebra::Unit;
|
use nalgebra::{Similarity3, Unit};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
@ -27,6 +27,12 @@ pub struct Mesh {
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
pub(crate) struct Wavefront {
|
pub(crate) struct Wavefront {
|
||||||
pub obj_file: PathBuf,
|
pub obj_file: PathBuf,
|
||||||
|
#[serde(default = "crate::serialize::vector::zeros")]
|
||||||
|
translation: Vector,
|
||||||
|
#[serde(default = "crate::serialize::vector::zeros")]
|
||||||
|
rotation: Vector,
|
||||||
|
#[serde(default = "crate::serialize::coefficient::default_identity")]
|
||||||
|
scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Wavefront> for Mesh {
|
impl TryFrom<Wavefront> for Mesh {
|
||||||
|
@ -37,6 +43,10 @@ impl TryFrom<Wavefront> for Mesh {
|
||||||
|
|
||||||
let (models, materials) = load_obj(&wavefront.obj_file)?;
|
let (models, materials) = load_obj(&wavefront.obj_file)?;
|
||||||
|
|
||||||
|
// The object to world transformation matrix
|
||||||
|
let transform =
|
||||||
|
Similarity3::new(wavefront.translation, wavefront.rotation, wavefront.scale);
|
||||||
|
|
||||||
for model in models {
|
for model in models {
|
||||||
let mesh = &model.mesh;
|
let mesh = &model.mesh;
|
||||||
|
|
||||||
|
@ -49,29 +59,39 @@ impl TryFrom<Wavefront> for Mesh {
|
||||||
mesh.indices[i * 3 + 2] as usize,
|
mesh.indices[i * 3 + 2] as usize,
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME: world-to-object transformations needed
|
let pos_a = transform * Point::from_slice(&mesh.positions[(a * 3)..(a * 3 + 2)]);
|
||||||
let pos_a = Point::from_slice(&mesh.positions[(a * 3)..(a * 3 + 2)]);
|
let pos_b = transform * Point::from_slice(&mesh.positions[(b * 3)..(b * 3 + 2)]);
|
||||||
let pos_b = Point::from_slice(&mesh.positions[(b * 3)..(b * 3 + 2)]);
|
let pos_c = transform * Point::from_slice(&mesh.positions[(c * 3)..(c * 3 + 2)]);
|
||||||
let pos_c = Point::from_slice(&mesh.positions[(c * 3)..(c * 3 + 2)]);
|
|
||||||
|
|
||||||
let triangle: ShapeEnum = if mesh.normals.is_empty() {
|
let triangle: ShapeEnum = if mesh.normals.is_empty() {
|
||||||
Triangle::new(pos_a, pos_b, pos_c).into()
|
Triangle::new(pos_a, pos_b, pos_c).into()
|
||||||
} else {
|
} else {
|
||||||
let norm_a = Unit::new_normalize(Vector::new(
|
// We apply the (arguably useless) scaling to the vectors in case it is
|
||||||
mesh.normals[a * 3],
|
// negative, which would invert their direction
|
||||||
mesh.normals[a * 3 + 1],
|
let norm_a = {
|
||||||
mesh.normals[a * 3 + 2],
|
let vec = Vector::new(
|
||||||
));
|
mesh.normals[a * 3],
|
||||||
let norm_b = Unit::new_normalize(Vector::new(
|
mesh.normals[a * 3 + 1],
|
||||||
mesh.normals[b * 3],
|
mesh.normals[a * 3 + 2],
|
||||||
mesh.normals[b * 3 + 1],
|
);
|
||||||
mesh.normals[b * 3 + 2],
|
Unit::new_normalize(transform * vec)
|
||||||
));
|
};
|
||||||
let norm_c = Unit::new_normalize(Vector::new(
|
let norm_b = {
|
||||||
mesh.normals[c * 3],
|
let vec = Vector::new(
|
||||||
mesh.normals[c * 3 + 1],
|
mesh.normals[b * 3],
|
||||||
mesh.normals[c * 3 + 2],
|
mesh.normals[b * 3 + 1],
|
||||||
));
|
mesh.normals[b * 3 + 2],
|
||||||
|
);
|
||||||
|
Unit::new_normalize(transform * vec)
|
||||||
|
};
|
||||||
|
let norm_c = {
|
||||||
|
let vec = Vector::new(
|
||||||
|
mesh.normals[c * 3],
|
||||||
|
mesh.normals[c * 3 + 1],
|
||||||
|
mesh.normals[c * 3 + 2],
|
||||||
|
);
|
||||||
|
Unit::new_normalize(transform * vec)
|
||||||
|
};
|
||||||
|
|
||||||
InterpolatedTriangle::new(pos_a, pos_b, pos_c, norm_a, norm_b, norm_c).into()
|
InterpolatedTriangle::new(pos_a, pos_b, pos_c, norm_a, norm_b, norm_c).into()
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,3 +14,8 @@ where
|
||||||
let v: Vector = Deserialize::deserialize(deserializer)?;
|
let v: Vector = Deserialize::deserialize(deserializer)?;
|
||||||
Ok(Unit::new_normalize(v))
|
Ok(Unit::new_normalize(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a vector containing all zeros.
|
||||||
|
pub fn zeros() -> Vector {
|
||||||
|
Vector::new(0., 0., 0.)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue