Closed kvark closed 9 years ago
I will need to investigate how we are using the Entities right now. But it makes sense that this extends what the World
does. An entity should only really have meaning when referenced to a World
object.
trait Entity {
type Bounding;
type Position;
fn get_position(&self, world: &World) -> Position;
fn get_bounding(&self, world: &World) -> Bounding;
}
With a design like this, the user could have a Resolved
Object or a Referenced
one. A Resolved
object being like the current Entity
where everything is inside of the object. A Referenced
could be a pointer, or just an NodeID that is to be looked up from the world.
First off, I believe entities and other things should operate on transforms, not positions. Changing to transforms, however, introduces an ambiguity - is the bounding in world space or the entity space?
The approach you propose would effectively hide NodePtr
/SkeletonPtr
types as well as the World
trait, which is very nice. One possible downside of this may be a difficulty in connecting cameras with entities and types. While the old approach would have a World
trait dictating all the associated types related to the space, without it they'll need to match each other with a set of where
clauses, probably.
Edit: also, do you see how a list of fragments per entity fits into (your/general) ECS?
Iterating on what I posted before.
trait Entity {
type Bounding;
type WorldTransform;
/// An iterator for the fragments
type Fragments;
fn is_visiable(&self, world &World) -> bool;
fn get_transform(&self, world: &World) -> WorldTransform;
fn get_bounding(&self, world: &World) -> Bounding;
fn get_fragments(&self, world: &World) -> Fragments;
}
trait Camera {
type View;
type Projection;
fn view(&self, world: &World) -> View;
fn projection(&self, world: &World) -> Projection;
fn get_view_projection(&self, world: &W) -> cgmath::Matrix4<S> {
use cgmath::{Matrix, Transform};
let node_inverse = self.view(world).invert().unwrap();
self.projection(world).into().mul_m(&node_inverse.into())
}
}
get_fragments
could be difficult to implement, since the iterator is lifetime bound, while the interface is notget_view
/get_projection
instead?View
is incorrectly named. The view transform in GL is typically World -> Camera space, while your view is the opposite. I'd rather have this:trait Node {
type Transform;
fn get_transform(&self, world: &World) -> Transform;
}
trait Entity: Node {
...
}
trait Camera: Node {
...
}
Looks good to me.
On the topic of Fragments. The easiest way is just to return a Vec
, it's not optimal of course but it gives us an easy way forward.
My biggest concern about fragments is how to map them to an ECS. If they are components (would be highly desirable), then the ECS has to support multiple components per entity.
If we put ECS aside, I can see the fragments interface as follows:
fn get_fragments<'a>(&'a self, &'a Storage) -> &'a [Fragment];
where Storage
is the rendering equivalent of World
. It may contain an array of fragments, where each entity points to (nice memory layout, less allocations on entity loading, but less flexibility of changing the fragments after they are loaded).
Slightly off-topicky - a ECS supporting multiple components could look like that:
type SliceStart = u32;
type SliceEnd = u32;
struct ComponentSlice<T>(SliceStart, SliceEnd, PhantomData<T>);
// start == end means no components of this type
struct Entity {
component_a: ComponentSlice<ComponentA>,
component_b: ComponentSlice<ComponentB>,
...
}
I know, it's much closer to simplecs
than to your ECS, and we have no chance to use it. Just though I'd leave the idea here for future reference.
I'm in process of implementing this (Node
, Entity
, Camera
traits). This interface is so good it will also provide #16 for free!
Entity being a struct is not compatible. We should turn it to a trait (as proposed by @csherratt), which fits nicely into the design. We can think of an entity as something abstract with a number of mandatory components (space node, fragments) and some optional ones (skeleton). The fact that there are multiple fragments may introduce some difficulties though.
Following this route, a camera should also be treated as something abstract with a space node and projection. Abstracting the scene though seems difficult in terms of ECS. Perhaps, I'll just move the current one into
claymore_scene
and leave the spot open ingfx_scene
.