Skip to main content

fyrox_graphics/
geometry_buffer.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Geometry buffer is a mesh buffer, that could contain multiple vertex buffers and only one
22//! element buffer.
23
24#![warn(missing_docs)]
25
26use crate::{
27    buffer::BufferUsage,
28    core::{array_as_u8_slice, math::TriangleDefinition},
29    define_shared_wrapper, ElementKind,
30};
31use bytemuck::Pod;
32use fyrox_core::define_as_any_trait;
33use std::mem::size_of;
34
35/// Attribute kind of a vertex.
36#[derive(Copy, Clone)]
37#[allow(dead_code)]
38pub enum AttributeKind {
39    /// Floating point 32-bit number.
40    Float,
41    /// Integer unsigned 8-bit number.
42    UnsignedByte,
43    /// Integer unsigned 16-bit number.
44    UnsignedShort,
45    /// Integer unsigned 32-bit number.
46    UnsignedInt,
47}
48
49/// Vertex attribute definition.
50pub struct AttributeDefinition {
51    /// Binding point of the vertex attribute.
52    pub location: u32,
53    /// Vertex attribute kind. See [`AttributeKind`] docs for more info.
54    pub kind: AttributeKind,
55    /// Component count in the vertex. This could be 1,2,3 or 4.
56    pub component_count: usize,
57    /// A flag, that defines whether the attribute is normalized or not. Normalized attributes
58    /// are always real numbers in `[-1.0; 1.0]` range (or `[0.0; 1.0]` for unsigned attributes).
59    pub normalized: bool,
60    /// Defines feed rate of the vertex attribute. 0 - means that the attribute will be unique per
61    /// vertex, 1 - per each drawn instance, 2 - per two instances and so on.
62    pub divisor: u32,
63}
64
65impl AttributeKind {
66    /// Returns attribute size in bytes.
67    pub fn size(self) -> usize {
68        match self {
69            AttributeKind::Float => size_of::<f32>(),
70            AttributeKind::UnsignedByte => size_of::<u8>(),
71            AttributeKind::UnsignedShort => size_of::<u16>(),
72            AttributeKind::UnsignedInt => size_of::<u32>(),
73        }
74    }
75}
76
77/// Untyped vertex buffer data.
78pub struct VertexBufferData<'a> {
79    /// Vertex size.
80    pub element_size: usize,
81    /// Vertex buffer data.
82    pub bytes: Option<&'a [u8]>,
83}
84
85impl<'a> VertexBufferData<'a> {
86    /// Creates a new untyped vertex buffer data from a typed slice. Underlying type must implement
87    /// [`Pod`] trait!
88    pub fn new<T: Pod>(vertices: Option<&'a [T]>) -> Self {
89        Self {
90            element_size: size_of::<T>(),
91            bytes: vertices.map(|v| array_as_u8_slice(v)),
92        }
93    }
94}
95
96/// Vertex buffer descriptor contains information about vertex buffer layout and content usage as
97/// well as the data that will be uploaded to GPU.
98pub struct VertexBufferDescriptor<'a> {
99    /// Vertex buffer usage. See [`BufferUsage`] docs for more info.
100    pub usage: BufferUsage,
101    /// Attributes of the vertex buffer.
102    pub attributes: &'a [AttributeDefinition],
103    /// Data of the vertex buffer. See [`VertexBufferData`] docs for more info.
104    pub data: VertexBufferData<'a>,
105}
106
107/// Describes elements for the geometry buffer.
108pub enum ElementsDescriptor<'a> {
109    /// Triangles are formed by a triple of vertex indices.
110    Triangles(&'a [TriangleDefinition]),
111    /// Lines are formed by a pair of vertex indices.
112    Lines(&'a [[u32; 2]]),
113    /// Points are just straight vertex indices.
114    Points(&'a [u32]),
115}
116
117impl ElementsDescriptor<'_> {
118    /// Returns element kind of the elements' descriptor.
119    pub fn element_kind(&self) -> ElementKind {
120        match self {
121            ElementsDescriptor::Triangles(_) => ElementKind::Triangle,
122            ElementsDescriptor::Lines(_) => ElementKind::Line,
123            ElementsDescriptor::Points(_) => ElementKind::Point,
124        }
125    }
126}
127
128/// Descriptor of the geometry buffer. It essentially binds multiple vertex buffers and one element
129/// buffer.
130pub struct GpuGeometryBufferDescriptor<'a> {
131    /// Name of the geometry buffer. Used only for debugging purposes.
132    pub name: &'a str,
133    /// Vertex buffers of the buffer. There must be at least one vertex buffer.
134    pub buffers: &'a [VertexBufferDescriptor<'a>],
135    /// Usage of the geometry buffer. See [`BufferUsage`] docs for more info.
136    pub usage: BufferUsage,
137    /// Elements of the geometry buffer.
138    pub elements: ElementsDescriptor<'a>,
139}
140
141define_as_any_trait!(GpuGeometryBufferAsAny => GpuGeometryBufferTrait);
142
143/// Geometry buffer is a mesh buffer, that could contain multiple vertex buffers and only one
144/// element buffer. Element could be either a line or triangle (the most commonly used one).
145///
146/// ## Examples
147///
148/// The simplest possible example shows how to create a geometry buffer that has a single triangle:
149///
150/// ```rust
151/// use fyrox_graphics::{
152///     buffer::BufferUsage,
153///     core::{algebra::Vector3, math::TriangleDefinition},
154///     error::FrameworkError,
155///     geometry_buffer::{
156///         AttributeDefinition, AttributeKind, ElementsDescriptor, GpuGeometryBuffer,
157///         GpuGeometryBufferDescriptor, VertexBufferData, VertexBufferDescriptor,
158///     },
159///     server::GraphicsServer,
160/// };
161/// use bytemuck::{Pod, Zeroable};
162///
163/// // Vertex type must implement a bunch of traits, that guarantees that the data will be tightly
164/// // packed with expected order of elements.
165/// #[derive(Pod, Copy, Clone, Zeroable)]
166/// #[repr(C)]
167/// struct Vertex {
168///     position: Vector3<f32>,
169/// }
170///
171/// fn create_geometry_buffer(
172///     server: &dyn GraphicsServer,
173/// ) -> Result<GpuGeometryBuffer, FrameworkError> {
174///     let vertices = [
175///         Vertex {
176///             position: Vector3::new(0.0, 0.0, 0.0),
177///         },
178///         Vertex {
179///             position: Vector3::new(0.0, 1.0, 0.0),
180///         },
181///         Vertex {
182///             position: Vector3::new(1.0, 0.0, 0.0),
183///         },
184///     ];
185///
186///     let triangles = [TriangleDefinition([0, 1, 2])];
187///
188///     server.create_geometry_buffer(GpuGeometryBufferDescriptor {
189///         name: "MyBuffer",
190///         buffers: &[VertexBufferDescriptor {
191///             usage: BufferUsage::StaticDraw,
192///             attributes: &[AttributeDefinition {
193///                 location: 0,
194///                 kind: AttributeKind::Float,
195///                 component_count: 3,
196///                 normalized: false,
197///                 divisor: 0,
198///             }],
199///             data: VertexBufferData::new(Some(&vertices)),
200///         }],
201///         usage: BufferUsage::StaticDraw,
202///         elements: ElementsDescriptor::Triangles(&triangles),
203///     })
204/// }
205/// ```
206pub trait GpuGeometryBufferTrait: GpuGeometryBufferAsAny {
207    /// Write untyped data to a vertex buffer with the given index.
208    fn set_buffer_data(&self, buffer: usize, data: &[u8]);
209
210    /// Returns total number of elements in the geometry buffer.
211    fn element_count(&self) -> usize;
212
213    /// Writes triangles to the buffer. Each triangle definition contains triangle indices, that
214    /// forms the triangle.
215    fn set_triangles(&self, triangles: &[TriangleDefinition]);
216
217    /// Writes lines to the buffer. Each pair defines starting and ending vertex index of the line.
218    fn set_lines(&self, lines: &[[u32; 2]]);
219
220    /// Writes points to the buffer. Each index in the slice defines vertex index.
221    fn set_points(&self, points: &[u32]);
222}
223
224impl dyn GpuGeometryBufferTrait {
225    /// Writes a typed data to a vertex buffer with the given index. Underlying type must implement
226    /// [`Pod`] trait!
227    pub fn set_buffer_data_of_type<T: Pod>(&self, buffer: usize, data: &[T]) {
228        self.set_buffer_data(buffer, array_as_u8_slice(data))
229    }
230}
231
232define_shared_wrapper!(GpuGeometryBuffer<dyn GpuGeometryBufferTrait>);