mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 18:21:12 +00:00
114 lines
3.2 KiB
Rust
114 lines
3.2 KiB
Rust
use anyhow::Result as AnyhowResult;
|
|
use std::path::Path;
|
|
use std::time::{Duration, Instant};
|
|
use glium::{self, Display};
|
|
use glium::vertex::VertexBufferAny;
|
|
use std::f32;
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct ExtractedVertex {
|
|
pub position: [f32; 3],
|
|
pub normal: [f32; 3],
|
|
pub color_diffuse: [f32; 3],
|
|
pub color_specular: [f32; 4],
|
|
pub tex_coords: [f32; 2], // [u, v]
|
|
}
|
|
|
|
/// Returns a vertex buffer that should be rendered as `TrianglesList`.
|
|
/// Adapted from https://github.com/Twinklebear/tobj_viewer/blob/master/src/support/mod.rs
|
|
pub fn load_wavefront(path: &Path) -> AnyhowResult<Vec<ExtractedVertex>>
|
|
//pub fn load_wavefront(display: &Display, path: &Path)
|
|
//-> (VertexBufferAny, f32)
|
|
{
|
|
// TODO: This appears to be one of two hooks for the data to be uploaded to OpenGL
|
|
implement_vertex!(ExtractedVertex, position, normal, color_diffuse, color_specular, tex_coords);
|
|
|
|
let mut min_pos = [f32::INFINITY; 3];
|
|
let mut max_pos = [f32::NEG_INFINITY; 3];
|
|
let mut vertex_data = Vec::new();
|
|
|
|
println!("loading {:?}...", path);
|
|
let (models, mats) = tobj::load_obj(path)?;
|
|
println!("loaded {:?}...", path);
|
|
|
|
// Just upload the first object in the group
|
|
for model in &models {
|
|
let mesh = &model.mesh;
|
|
//println!("Uploading model: {}", model.name);
|
|
|
|
for idx in &mesh.indices {
|
|
let i = *idx as usize;
|
|
|
|
let pos = [
|
|
mesh.positions[3 * i],
|
|
mesh.positions[3 * i + 1],
|
|
mesh.positions[3 * i + 2],
|
|
];
|
|
|
|
let normal = if !mesh.normals.is_empty() {
|
|
[
|
|
mesh.normals[3 * i],
|
|
mesh.normals[3 * i + 1],
|
|
mesh.normals[3 * i + 2],
|
|
]
|
|
} else {
|
|
[0.0, 0.0, 0.0]
|
|
};
|
|
|
|
let tex_coords = if !mesh.texcoords.is_empty() {
|
|
// texcoord = [u, v];
|
|
[
|
|
mesh.texcoords[i * 2],
|
|
mesh.texcoords[i * 2 + 1]
|
|
]
|
|
} else {
|
|
[0.0, 0.0]
|
|
};
|
|
|
|
let (color_diffuse, color_specular) = match mesh.material_id {
|
|
Some(i) => (
|
|
mats[i].diffuse,
|
|
[
|
|
mats[i].specular[0],
|
|
mats[i].specular[1],
|
|
mats[i].specular[2],
|
|
mats[i].shininess,
|
|
],
|
|
),
|
|
None => ([0.8, 0.8, 0.8], [0.15, 0.15, 0.15, 15.0]),
|
|
};
|
|
|
|
vertex_data.push(ExtractedVertex {
|
|
position: pos,
|
|
normal: normal,
|
|
color_diffuse: color_diffuse,
|
|
color_specular: color_specular,
|
|
tex_coords: tex_coords,
|
|
});
|
|
|
|
// Update our min/max pos so we can figure out the bounding box of the object
|
|
// to view it
|
|
for i in 0..3 {
|
|
min_pos[i] = f32::min(min_pos[i], pos[i]);
|
|
max_pos[i] = f32::max(max_pos[i], pos[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(vertex_data)
|
|
|
|
// TODO: This appears to be the second hook:
|
|
// Compute scale factor to fit the model with a [-1, 1] bounding box
|
|
/*let diagonal_len = 6.0;
|
|
let current_len = f32::powf(max_pos[0] - min_pos[0], 2.0)
|
|
+ f32::powf(max_pos[1] - min_pos[1], 2.0)
|
|
+ f32::powf(max_pos[2] - min_pos[2], 2.0);
|
|
let scale = f32::sqrt(diagonal_len / current_len);
|
|
println!("Model scaled by {} to fit", scale);
|
|
(
|
|
glium::vertex::VertexBuffer::new(display, &vertex_data)
|
|
.unwrap()
|
|
.into_vertex_buffer_any(),
|
|
scale,
|
|
)*/
|
|
} |