model-converter/src/programs/viewer.rs

217 lines
6.4 KiB
Rust
Raw Normal View History

2018-04-17 10:45:44 +02:00
extern crate clap;
2018-02-23 15:22:48 +01:00
extern crate glium;
2018-04-17 10:45:44 +02:00
#[macro_use]
extern crate verbose_log;
2018-02-26 11:45:53 +01:00
extern crate model_converter;
2018-02-23 15:22:48 +01:00
2018-04-11 17:03:32 +02:00
use std::process::exit;
2018-04-17 10:45:44 +02:00
use std::time::{Instant, Duration};
2018-06-15 16:21:04 +02:00
use std::thread::sleep;
2018-04-17 10:45:44 +02:00
use clap::{App, Arg};
2018-04-11 17:03:32 +02:00
2018-02-23 15:22:48 +01:00
use glium::Display;
use glium::glutin;
use glium::glutin::{EventsLoop, WindowBuilder};
2018-02-23 15:22:48 +01:00
2018-07-10 17:43:37 +02:00
use glium::glutin::{
Event,
WindowEvent,
VirtualKeyCode,
ElementState,
};
2018-02-23 15:22:48 +01:00
2018-04-18 10:26:40 +02:00
use model_converter::scene::Scene;
2018-04-17 10:45:44 +02:00
use model_converter::math::bounding_box::BoundingBox3;
2018-04-10 15:13:35 +02:00
use model_converter::math::vector::Vector3;
use model_converter::parser::parse_file;
2018-02-27 11:42:35 +01:00
use model_converter::renderer::Renderer;
use model_converter::controls::{OrbitControls, FirstPersonControls};
2018-04-17 10:45:44 +02:00
use model_converter::camera::Camera;
fn as_millis(duration: Duration) -> u64 {
duration.as_secs() * 1_000 + (duration.subsec_nanos() as u64) / 1_000_000
}
2018-02-26 11:45:53 +01:00
2018-02-23 15:22:48 +01:00
fn main() {
2018-04-17 10:45:44 +02:00
let matches = App::new("3D Viewer")
.version("1.0")
.arg(Arg::with_name("input")
.short("i")
.long("input")
.value_name("FILES")
.takes_value(true)
.multiple(true)
.help("Input model files")
.required(true))
.arg(Arg::with_name("first person")
.short("f")
.long("first-person")
.help("Uses first person controls instead of orbit controls"))
.arg(Arg::with_name("verbose")
.short("v")
.long("verbose")
.help("Shows logs during the parsing of the model"))
.get_matches();
// Set verbose flag
2018-07-02 11:35:12 +02:00
verbose_log::set(matches.occurrences_of("verbose") > 0);
2018-04-17 10:45:44 +02:00
2018-10-11 15:22:59 +02:00
let mut capture_count = 0;
2018-04-17 10:45:44 +02:00
use std::f64::{MIN, MAX};
let mut bbox = BoundingBox3::new(
Vector3::new(MAX, MAX, MAX),
Vector3::new(MIN, MIN, MIN),
);
2018-04-11 17:03:32 +02:00
2018-04-17 10:45:44 +02:00
let mut models = vec![];
2018-04-11 17:03:32 +02:00
2018-04-17 10:45:44 +02:00
for input in matches.values_of("input").unwrap() {
match parse_file(&input) {
2018-04-17 10:45:44 +02:00
Ok(model) => {
if model.vertices.len() > 0 {
bbox = bbox.union(&model.bounding_box());
}
2018-04-17 10:45:44 +02:00
models.push((input.to_owned(), model))
},
Err(e) => {
eprintln!("Error while parsing file: {}", e);
exit(1);
},
2018-04-11 17:03:32 +02:00
}
}
2018-02-26 14:59:32 +01:00
2018-02-23 15:22:48 +01:00
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new().with_visibility(false);
2018-02-26 14:59:32 +01:00
let context = glutin::ContextBuilder::new().with_depth_buffer(24);
2018-02-23 15:22:48 +01:00
let display = Display::new(window, context, &events_loop).unwrap();
let mut renderer = Renderer::new(display);
2018-02-23 15:22:48 +01:00
2018-04-18 10:26:40 +02:00
let mut scene = Scene::new();
2018-04-17 10:45:44 +02:00
let mut before;
let mut duration;
for (name, mut model) in models {
log!("Scaling model {}...", name);
2018-07-23 10:12:37 +02:00
model.center_and_scale_from_box(&bbox);
2018-04-17 10:45:44 +02:00
log!("\nBuilding textures for model {}...", name);
before = Instant::now();
model.build_textures(&renderer);
duration = Instant::now().duration_since(before);
log!(" done in {}ms.\nBuilding vertex buffers for model {}...",
as_millis(duration) ,name);
2018-02-23 15:22:48 +01:00
2018-04-17 10:45:44 +02:00
before = Instant::now();
model.build_vertex_buffers(&renderer);
duration = Instant::now().duration_since(before);
2018-04-18 10:26:40 +02:00
scene.emplace(model);
2018-04-17 10:45:44 +02:00
logln!(" done in {}ms.\nFinished", as_millis(duration));
}
let mut closed = false;
2018-02-26 11:45:53 +01:00
2018-04-10 15:13:35 +02:00
let mut camera = Camera::new(
2018-07-23 10:12:37 +02:00
Vector3::new( 0.0, 0.0, 0.0),
Vector3::new( 0.0, 0.0, 0.0),
Vector3::new( 0.0, 1.0, 0.0),
2018-04-10 15:13:35 +02:00
);
2018-02-26 14:59:32 +01:00
2018-04-17 10:45:44 +02:00
camera.z_near = 0.0001;
2018-04-12 17:23:40 +02:00
2018-04-17 10:59:17 +02:00
let mut controls: Box<Controls> = if matches.is_present("first person") {
2018-04-17 10:45:44 +02:00
Box::new(FirstPersonControls::new())
} else {
Box::new(OrbitControls::new(
Vector3::new(0.0, 0.0, 0.0),
2018-07-23 10:12:37 +02:00
1.0,
2018-04-17 10:45:44 +02:00
&mut camera
))
};
2018-02-23 15:22:48 +01:00
renderer.show();
2018-04-17 10:45:44 +02:00
use model_converter::controls::Controls;
2018-06-15 16:21:04 +02:00
let mut before = Instant::now();
2018-04-10 15:13:35 +02:00
while !closed {
2018-02-27 11:42:35 +01:00
2018-04-10 15:13:35 +02:00
events_loop.poll_events(|ev| {
2018-02-23 15:22:48 +01:00
2018-04-12 17:23:40 +02:00
controls.manage_event(&ev, &mut camera, &renderer);
2018-02-23 15:22:48 +01:00
match ev {
// Close window
Event::WindowEvent {
2018-09-18 15:23:51 +02:00
event: WindowEvent::CloseRequested, ..
2018-02-23 15:22:48 +01:00
} => closed = true,
// Escape key
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
input: glutin::KeyboardInput {
2018-07-10 17:43:37 +02:00
virtual_keycode: Some(VirtualKeyCode::Escape),
state: ElementState::Pressed, ..
2018-02-23 15:22:48 +01:00
}, ..
}, ..
} => closed = true,
2018-07-10 17:43:37 +02:00
// Enter key
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
input: glutin::KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Return),
state: ElementState::Pressed, ..
}, ..
}, ..
} => {
println!("Camera:");
println!("\tPosition: ({}, {}, {})",
2018-07-23 10:12:37 +02:00
camera.position.x(), camera.position.y(), camera.position.z());
2018-07-10 17:43:37 +02:00
println!("\tTarget: ({}, {}, {})",
2018-07-23 10:12:37 +02:00
camera.target.x(), camera.target.y(), camera.target.z());
2018-07-10 17:43:37 +02:00
println!("\tUp: ({}, {}, {})",
2018-07-23 10:12:37 +02:00
camera.up.x(), camera.up.y(), camera.up.z());
2018-10-11 15:22:59 +02:00
},
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
input: glutin::KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::C),
state: ElementState::Pressed, ..
}, ..
}, ..
} => {
// Make a screenshot
let size = renderer.gl_window().get_inner_size().unwrap();
2018-10-12 13:59:56 +02:00
let cap = renderer.capture(size.into());
2018-10-11 15:22:59 +02:00
cap.save(format!("capture-{}.png", capture_count)).unwrap();
capture_count += 1;
},
2018-07-10 17:43:37 +02:00
2018-02-23 15:22:48 +01:00
_ => (),
}
});
2018-04-10 15:13:35 +02:00
2018-04-12 17:23:40 +02:00
controls.update(&mut camera, &renderer);
2018-04-17 10:45:44 +02:00
renderer.render(&scene, &camera);
2018-06-15 16:21:04 +02:00
let elapsed = as_millis(Instant::now().duration_since(before));
2018-04-10 15:13:35 +02:00
2018-06-15 16:21:04 +02:00
if elapsed < 20 {
sleep(Duration::from_millis(20 - elapsed));
}
before = Instant::now();
2018-02-23 15:22:48 +01:00
}
}