Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template System and Reworked glTF Handling #203

Merged
merged 11 commits into from
May 16, 2018
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Cargo.lock

# Configuration file for editors using the RLS.
rls.toml
25 changes: 17 additions & 8 deletions examples/gltf-morph-targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,31 @@ fn main() {

let default = concat!(env!("CARGO_MANIFEST_DIR"), "/test_data/AnimatedMorphCube/AnimatedMorphCube.gltf");
let path = std::env::args().nth(1).unwrap_or(default.into());
let gltf = window.factory.load_gltf(&path);
window.scene.add(&gltf);

// Load the contents of the glTF files. Scenes loaded from the file are returned as
// `Template` objects, which can be used to instantiate the actual objects for rendering.
let templates = window.factory.load_gltf(&path);

// Instantiate the contents of the template, and then add it to the scene.
let (instance, animations) = window.factory.instantiate_template(&templates[0]);
window.scene.add(&instance);

// Begin playing all the animations instantiated from the template.
let mut mixer = three::animation::Mixer::new();
for clip in gltf.clips {
mixer.action(clip);
for animation in animations {
mixer.action(animation);
}

// Create a camera with which to render the scene, and control it with the built-in
// orbit controller, set to orbit the model.
let camera = window.factory.perspective_camera(60.0, 0.1 .. 20.0);
camera.set_position([0.0, 1.0, 5.0]);

let mut controls = three::controls::Orbit::builder(&camera)
.position([-0.08, -0.05, 0.075])
.target([0.0, 0.0, 0.01])
.position([-3.0, 3.0, -3.0])
.up([0.0, 1.0, 0.0])
.build();

// Run the main loop, updating the camera controller, animations, and rendering the scene
// every frame.
while window.update() && !window.input.hit(three::KEY_ESCAPE) {
mixer.update(window.input.delta_time());
controls.update(&window.input);
Expand Down
21 changes: 15 additions & 6 deletions examples/gltf-node-animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,31 @@ fn main() {

let default = concat!(env!("CARGO_MANIFEST_DIR"), "/test_data/BoxAnimated/BoxAnimated.gltf");
let path = std::env::args().nth(1).unwrap_or(default.into());
let gltf = window.factory.load_gltf(&path);
window.scene.add(&gltf);

// Load the contents of the glTF files. Scenes loaded from the file are returned as
// `Template` objects, which can be used to instantiate the actual objects for rendering.
let templates = window.factory.load_gltf(&path);

// Instantiate the contents of the template, and then add it to the scene.
let (instance, animations) = window.factory.instantiate_template(&templates[0]);
window.scene.add(&instance);

// Start playing all the animations from the template.
let mut mixer = three::animation::Mixer::new();
for clip in gltf.clips {
mixer.action(clip);
for animation in animations {
mixer.action(animation);
}

// Create a camera with which to render the scene, and control it with the built-in
// orbit controller, set to orbit the model.
let camera = window.factory.perspective_camera(60.0, 0.1 .. 100.0);
window.scene.add(&camera);

let mut controls = three::controls::Orbit::builder(&camera)
.position([3.0, 3.0, 3.0])
.target([0.0, 1.0, 0.0])
.build();

// Run the main loop, updating the camera controller, animations, and rendering the scene
// every frame.
while window.update() && !window.input.hit(three::KEY_ESCAPE) {
mixer.update(window.input.delta_time());
controls.update(&window.input);
Expand Down
34 changes: 28 additions & 6 deletions examples/gltf-pbr-shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,33 @@ fn main() {
let default = concat!(env!("CARGO_MANIFEST_DIR"), "/test_data/Lantern/Lantern.gltf");
let path = std::env::args().nth(1).unwrap_or(default.into());
println!("Loading {:?} (this may take a while)", path);
let mut gltf = win.factory.load_gltf(&path);
win.scene.add(&gltf);

let cam = if gltf.cameras.len() > 0 {
gltf.cameras.swap_remove(0)
} else {
// Load the contents of the glTF files. Scenes loaded from the file are returned as
// `Template` objects, which can be used to instantiate the actual objects for rendering.
let templates = win.factory.load_gltf(&path);

// Instantiate the contents of the template, and then add it to the scene.
let (instance, _) = win.factory.instantiate_template(&templates[0]);
win.scene.add(&instance);

// TODO: Look for an existing camera within the glTF scene. We'll need the ability to walk
// the scene hierarchy before we can do this.
let cam = None;
// for node in instance.nodes.values() {
// if let Some(ref camera) = node.camera {
// cam = Some(camera.clone());
// break;
// }
// }

// If we didn't find a camera in the glTF scene, create a default one to use.
let cam = cam.unwrap_or_else(|| {
let default = win.factory.perspective_camera(60.0, 0.001 .. 100.0);
win.scene.add(&default);
default
};
});

// Create a skybox for the scene.
let skybox_path = three::CubeMapPath {
front: "test_data/skybox/posz.jpg",
back: "test_data/skybox/negz.jpg",
Expand All @@ -34,14 +50,20 @@ fn main() {
let skybox = win.factory.load_cubemap(&skybox_path);
win.scene.background = three::Background::Skybox(skybox);

// Determine the current position of the camera so that we can use it to initialize the
// camera controller.
let init = win.scene
.sync_guard()
.resolve_world(&cam)
.transform;

// Create a first person camera controller, starting at the camera's current position.
let mut controls = three::controls::FirstPerson::builder(&cam)
.position(init.position)
.move_speed(4.0)
.build();

// Run the main loop, updating the camera controller and rendering the scene every frame.
while win.update() && !win.input.hit(three::KEY_ESCAPE) {
controls.update(&win.input);
win.render(&cam);
Expand Down
26 changes: 18 additions & 8 deletions examples/gltf-vertex-skinning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,32 @@ fn main() {

let default = concat!(env!("CARGO_MANIFEST_DIR"), "/test_data/BrainStem/BrainStem.gltf");
let path = std::env::args().nth(1).unwrap_or(default.into());
let gltf = window.factory.load_gltf(&path);
window.scene.add(&gltf);

// Load the contents of the glTF files. Scenes loaded from the file are returned as
// `Template` objects, which can be used to instantiate the actual objects for rendering.
let templates = window.factory.load_gltf(&path);

// Instantiate the contents of the template, and then add it to the scene.
let (instance, animations) = window.factory.instantiate_template(&templates[0]);
window.scene.add(&instance);

// Begin playing all the animations instantiated from the template.
let mut mixer = three::animation::Mixer::new();
for clip in gltf.clips {
mixer.action(clip);
for animation in animations {
mixer.action(animation);
}

// Create a camera with which to render the scene, and control it with the built-in
// orbit controller, set to orbit the model.
let camera = window.factory.perspective_camera(45.0, 0.1 .. 100.0);
window.scene.add(&camera);

let mut controls = three::controls::Orbit::builder(&camera)
.position([0.0, -3.0, 3.0])
.target([0.0, 0.0, 1.0])
.position([0.0, 3.0, -1.0])
.target([0.0, 0.0, -1.0])
.up([0.0, 0.0, -1.0])
.build();

// Run the main loop, updating the camera controller, animations, and rendering the scene
// every frame.
while window.update() && !window.input.hit(three::KEY_ESCAPE) {
mixer.update(window.input.delta_time());
controls.update(&window.input);
Expand Down
20 changes: 18 additions & 2 deletions src/controls/orbit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct Orbit {
pub struct Builder {
object: object::Base,
position: mint::Point3<f32>,
up: mint::Vector3<f32>,
target: mint::Point3<f32>,
button: Button,
speed: f32,
Expand All @@ -38,6 +39,7 @@ impl Builder {
Builder {
object: object.upcast(),
position: [0.0, 0.0, 0.0].into(),
up: [0.0, 0.0, 1.0].into(),
target: [0.0, 0.0, 0.0].into(),
button: MOUSE_LEFT,
speed: 1.0,
Expand All @@ -58,6 +60,20 @@ impl Builder {
self
}

/// Sets the initial up direction.
///
/// Defaults to the unit z axis.
pub fn up<P>(
&mut self,
up: P,
) -> &mut Self
where
P: Into<mint::Vector3<f32>>
{
self.up = up.into();
self
}

/// Set the target position.
///
/// Defaults to the world origin.
Expand Down Expand Up @@ -93,8 +109,8 @@ impl Builder {
/// Finalize builder and create new `OrbitControls`.
pub fn build(&mut self) -> Orbit {
let dir = (Point3::from(self.position) - Point3::from(self.target)).normalize();
let up = Vector3::unit_z();
let q = Quaternion::look_at(dir, up).invert();
let up = self.up;
let q = Quaternion::look_at(dir, up.into()).invert();
let object = self.object.clone();
object.set_transform(self.position, q, 1.0);
let transform = Decomposed {
Expand Down
Loading