-
Notifications
You must be signed in to change notification settings - Fork 44
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
Node tree rewrite #155
Node tree rewrite #155
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's soo cool. Can't wait we will finish it and merge.
src/hub.rs
Outdated
for (child_ptr, sibling) in deferred_sibling_updates { | ||
let child = &mut self.nodes[&child_ptr]; | ||
if child.next_sibling.is_some() { | ||
error!("Attaching a child that still has an old parent, discarding siblings"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can we change parent now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, I forgot about this :) Now added to TODO list for this PR.
Basically, we can either merge the old siblings with the new ones (like Scene::add
does), or require the user to call Group::remove(&item)
before adding to another group. Either way, the remove
needs to be added.
src/hub.rs
Outdated
Operation::AddChild(child_ptr) => match node.sub_node { | ||
SubNode::Group { ref mut first_child } => { | ||
let sibling = mem::replace(first_child, Some(child_ptr.clone())); | ||
deferred_sibling_updates.push((child_ptr, sibling)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
borrow checker...
src/hub.rs
Outdated
SubNode::Visual(_, ref mut gpu_data) => gpu_data.pending = Some(mesh.dynamic.clone()), | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
pub(crate) fn walk(&self, base: &Option<NodePointer>) -> TreeWalker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/node.rs
Outdated
/// The same as `visible`, used internally. | ||
pub world_visible: bool, | ||
/// Relative to parent transform. | ||
pub transform: Transform, | ||
/// Material in case this `Node` has it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this ever useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait, why is Material
here? O_O
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this is user-exposed node, not the internal one.
Yeah, let it be. The whole reflection thing (with sync
) I'd consider non-idiomatic, so we shouldn't be too eager to optimize it.
src/render/mod.rs
Outdated
}; | ||
let mx_view = Matrix4::from(w.inverse_transform().unwrap()); | ||
let node = &hub[&camera]; | ||
let world_transform = node.transform; //TODO!!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: compute the world transform for the camera, which is expected here
src/scene.rs
Outdated
use std::sync::MutexGuard; | ||
|
||
/// Unique identifier for a scene. | ||
pub type Uid = usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like we're going in the right direction here. The reduced verbosity from all the mut
s and set_parent
calls is a breath of fresh air.
Alright, I rebased the code and implemented the missing bits. |
Here are the profiling results (note: I only used
Looks like I addressed all the action items from my side. Waiting for more reviews now (@alteous , @vitvakatu ). |
I believe in the long term our architecture should work like this:
TL;DR: there is no strong reason for |
examples/group.rs
Outdated
const SPEEDS: [f32; 6] = [0.7, -1.0, 1.3, -1.6, 1.9, -2.2]; | ||
struct LevelDesc { | ||
color: three::Color, | ||
speed: f32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the unit of this? I assume radians/second?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct
walker | ||
} | ||
|
||
pub(crate) fn walk(&self, base: &Option<NodePointer>) -> TreeWalker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Perhaps walk_visible
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in froggy, it's better to use shorter names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's for internal use only anyhow. Most of the time we are only concerned about visible nodes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're close
@@ -28,7 +31,7 @@ cgmath = { version = "0.15", features = ["mint"] } | |||
derivative = "1.0" | |||
froggy = "0.4.4" | |||
genmesh = "0.5" | |||
gfx = "0.16" | |||
gfx = "0.16.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because your instancing changes require it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of strict version rules in Cargo. It will use the latest available version anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your position is in the minority within the community then. Latest will be used on fresh checkout, if we don't check in Cargo.lock
. But people who already have Cargo.lock
will get breakage if you don't write the exact version in the Cargo.toml
. Another case is - some crate that depends on you may say gfx = "=0.16.2"
and it will try to build but will fail even after cargo update
.
TL;DR: Cargo versioning rules are here to stay and be respected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, there is a proposal (which I supported) about making cargo publish
checking out all the minimal compatible versions (as opposed to latest). Think about it ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, you convicted me
|
||
let mut mline = { | ||
// test removal from scene | ||
win.scene.remove(&mcyl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it supposed to be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - it's a small test for object removal. May not be the best place, but better than nothing
walker | ||
} | ||
|
||
pub(crate) fn walk(&self, base: &Option<NodePointer>) -> TreeWalker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in froggy, it's better to use shorter names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ready to go
bors r+ |
155: Node tree rewrite r=vitvakatu a=kvark Fixes #44 Core of the change is switching relationships from "child->parent" to "parent->first_child->sibling", which gives us the following benefits: - clean children lifetimes, as expected by users - no need to store all the meshes returned by gltf/obj loaders: perhaps, we can follow-up with a PR that allows querying meshes by name from their parents, so that we don't even return all the meshes directly in the loader API - nice `Group::add(&something)`, like Three-js does - make `Scene` truly unique and node-less - no need for unique scene IDs ~~- technically, objects can now be present in multiple scenes at once~~ - immutable node data upon traversal (!): - we just compute the world visibility/transform on the fly - thus, no need for a separate `update_transforms` step - uses pretty iterators ;) - as a downside, not as straightforward to reflect the world info to the user (see TODO) Has other changes making things nicer: - refactored frame render code - no `&mut self` on objects - idiomatic hub indexing - safer group/camera/text/audio spawning (internal) - more robust message handling (panic on unprocessed/unexpected messages) - can debug print the `Operation` TODO: - [x] check/fix docs - [x] compute world transform/visibility for the user if needed (is it needed?) - [x] provide API to detach from parent - [x] reviews! - [x] profile the cost of recomputing the world transforms
bors r- |
Canceled |
bors r=vitvakatu |
155: Node tree rewrite r=vitvakatu a=kvark Fixes #44 Core of the change is switching relationships from "child->parent" to "parent->first_child->sibling", which gives us the following benefits: - clean children lifetimes, as expected by users - no need to store all the meshes returned by gltf/obj loaders: perhaps, we can follow-up with a PR that allows querying meshes by name from their parents, so that we don't even return all the meshes directly in the loader API - nice `Group::add(&something)`, like Three-js does - make `Scene` truly unique and node-less - no need for unique scene IDs ~~- technically, objects can now be present in multiple scenes at once~~ - immutable node data upon traversal (!): - we just compute the world visibility/transform on the fly - thus, no need for a separate `update_transforms` step - uses pretty iterators ;) - as a downside, not as straightforward to reflect the world info to the user (see TODO) Has other changes making things nicer: - refactored frame render code - no `&mut self` on objects - idiomatic hub indexing - safer group/camera/text/audio spawning (internal) - more robust message handling (panic on unprocessed/unexpected messages) - can debug print the `Operation` TODO: - [x] check/fix docs - [x] compute world transform/visibility for the user if needed (is it needed?) - [x] provide API to detach from parent - [x] reviews! - [x] profile the cost of recomputing the world transforms
Build succeeded |
Fixes #44
Core of the change is switching relationships from "child->parent" to "parent->first_child->sibling", which gives us the following benefits:
Group::add(&something)
, like Three-js doesScene
truly unique and node-less- technically, objects can now be present in multiple scenes at onceupdate_transforms
stepHas other changes making things nicer:
&mut self
on objectsOperation
TODO: