1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#![deny(missing_docs)]

//! Scene infrastructure to be used with Gfx phases.

extern crate gfx_phase;
extern crate gfx;
extern crate cgmath;
extern crate collision;
extern crate hprof;

mod cull;

pub use gfx_phase::AbstractPhase;
pub use self::cull::{Culler, Frustum, Context};

/// Scene drawing error.
#[derive(Debug)]
pub enum Error {
    /// Error in creating a batch.
    Batch(gfx::batch::Error),
    /// Error in sending a batch for drawing.
    Flush(gfx_phase::FlushError),
}

/// Type of the call counter.
pub type Count = u32;

/// Rendering success report.
#[derive(Clone, Debug)]
pub struct Report {
    /// Number of calls in invisible entities.
    pub calls_invisible: Count,
    /// Number of calls that got culled out.
    pub calls_culled: Count,
    /// Number of calls that the phase doesn't apply to.
    pub calls_rejected: Count,
    /// Number of calls that failed to link batches.
    pub calls_failed: Count,
    /// Number of calls issued to the GPU.
    pub calls_passed: Count,
    /// Number of primitives rendered.
    pub primitives_rendered: Count,
}

impl Report {
    /// Create an empty `Report`.
    pub fn new() -> Report {
        Report {
            calls_rejected: 0,
            calls_failed: 0,
            calls_culled: 0,
            calls_invisible: 0,
            calls_passed: 0,
            primitives_rendered: 0,
        }
    }

    /// Get total number of draw calls.
    pub fn get_calls_total(&self) -> Count {
        self.calls_invisible + self.calls_culled +
        self.calls_rejected  + self.calls_failed +
        self.calls_passed
    }

    /// Get the rendered/submitted calls ratio.
    pub fn get_calls_ratio(&self) -> f32 {
        self.calls_passed as f32 / self.get_calls_total() as f32
    }
}

/// Abstract scene that can be drawn into something.
pub trait AbstractScene<R: gfx::Resources> {
    /// A type of the view information.
    type ViewInfo: gfx_phase::ToDepth;
    /// A type of the material.
    type Material;
    /// A type of the camera.
    type Camera;
    /// the status information from the render results
    /// this can be used to communicate meta from the render
    type Status;

    /// Draw the contents of the scene with a specific phase into a stream.
    fn draw<H, S>(&self, &mut H, &Self::Camera, &mut S)
            -> Result<Self::Status, Error> where
        H: gfx_phase::AbstractPhase<R, Self::Material, Self::ViewInfo>,
        S: gfx::Stream<R>;
}

/// A fragment of an entity, contains a single draw call.
#[derive(Clone, Debug)]
pub struct Fragment<R: gfx::Resources, M> {
    /// Fragment material.
    pub material: M,
    /// Mesh slice.
    pub slice: gfx::Slice<R>,
}

impl<R: gfx::Resources, M> Fragment<R, M> {
    /// Create a new fragment.
    pub fn new(mat: M, slice: gfx::Slice<R>) -> Fragment<R, M> {
        Fragment {
            material: mat,
            slice: slice,
        }
    }
}

/// An abstract node in space.
pub trait Node {
    /// Associated abstract transformation (affine matrix, decomposed, etc).
    type Transform;
    /// Get local -> world transform.
    fn get_transform(&self) -> Self::Transform;
}

/// An abstract entity.
pub trait Entity<R: gfx::Resources, M>: Node {
    /// Type of the spatial bound (box, sphere, etc).
    type Bound;
    /// Check if it's visible.
    fn is_visible(&self) -> bool { true }
    /// Get the local bound.
    fn get_bound(&self) -> Self::Bound;
    /// Get the mesh.
    fn get_mesh(&self) -> &gfx::Mesh<R>;
    /// Get the drawable fragments of this entity.
    fn get_fragments(&self) -> &[Fragment<R, M>];
}

/// An abstract camera.
pub trait Camera<S>: Node {
    /// Associated projection type (perspective, ortho, etc)
    type Projection: std::convert::Into<cgmath::Matrix4<S>>;
    /// Get the projection.
    fn get_projection(&self) -> Self::Projection;
    /// Compute the view-projection matrix.
    fn get_view_projection(&self) -> cgmath::Matrix4<S> where
        S: cgmath::BaseFloat,
        Self::Transform : cgmath::Transform3<S>
    {
        use cgmath::{Matrix, Transform};
        let view = self.get_transform().invert().unwrap();
        self.get_projection().into().mul_m(&view.into())
    }
}

/// Abstract information about the view. Supposed to containt at least
/// Model-View-Projection transform for the shader.
pub trait ViewInfo<S, T>: gfx_phase::ToDepth<Depth = S>
    where S: Copy+PartialOrd+std::fmt::Debug
{
    /// Construct a new information block.
    fn new(mvp: cgmath::Matrix4<S>, view: T, model: T) -> Self;
}