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, Downcast},
29 ElementKind,
30};
31use bytemuck::Pod;
32use std::mem::size_of;
33
34/// Attribute kind of a vertex.
35#[derive(Copy, Clone)]
36#[allow(dead_code)]
37pub enum AttributeKind {
38 /// Floating point 32-bit number.
39 Float,
40 /// Integer unsigned 8-bit number.
41 UnsignedByte,
42 /// Integer unsigned 16-bit number.
43 UnsignedShort,
44 /// Integer unsigned 32-bit number.
45 UnsignedInt,
46}
47
48/// Vertex attribute definition.
49pub struct AttributeDefinition {
50 /// Binding point of the vertex attribute.
51 pub location: u32,
52 /// Vertex attribute kind. See [`AttributeKind`] docs for more info.
53 pub kind: AttributeKind,
54 /// Component count in the vertex. This could be 1,2,3 or 4.
55 pub component_count: usize,
56 /// A flag, that defines whether the attribute is normalized or not. Normalized attributes
57 /// are always real numbers in `[-1.0; 1.0]` range (or `[0.0; 1.0]` for unsigned attributes).
58 pub normalized: bool,
59 /// Defines feed rate of the vertex attribute. 0 - means that the attribute will be unique per
60 /// vertex, 1 - per each drawn instance, 2 - per two instances and so on.
61 pub divisor: u32,
62}
63
64impl AttributeKind {
65 /// Returns attribute size in bytes.
66 pub fn size(self) -> usize {
67 match self {
68 AttributeKind::Float => size_of::<f32>(),
69 AttributeKind::UnsignedByte => size_of::<u8>(),
70 AttributeKind::UnsignedShort => size_of::<u16>(),
71 AttributeKind::UnsignedInt => size_of::<u32>(),
72 }
73 }
74}
75
76/// Untyped vertex buffer data.
77pub struct VertexBufferData<'a> {
78 /// Vertex size.
79 pub element_size: usize,
80 /// Vertex buffer data.
81 pub bytes: Option<&'a [u8]>,
82}
83
84impl<'a> VertexBufferData<'a> {
85 /// Creates a new untyped vertex buffer data from a typed slice. Underlying type must implement
86 /// [`Pod`] trait!
87 pub fn new<T: Pod>(vertices: Option<&'a [T]>) -> Self {
88 Self {
89 element_size: size_of::<T>(),
90 bytes: vertices.map(|v| array_as_u8_slice(v)),
91 }
92 }
93}
94
95/// Vertex buffer descriptor contains information about vertex buffer layout and content usage as
96/// well as the data that will be uploaded to GPU.
97pub struct VertexBufferDescriptor<'a> {
98 /// Vertex buffer usage. See [`BufferUsage`] docs for more info.
99 pub usage: BufferUsage,
100 /// Attributes of the vertex buffer.
101 pub attributes: &'a [AttributeDefinition],
102 /// Data of the vertex buffer. See [`VertexBufferData`] docs for more info.
103 pub data: VertexBufferData<'a>,
104}
105
106/// Describes elements for the geometry buffer.
107pub enum ElementsDescriptor<'a> {
108 /// Triangles are formed by a triple of vertex indices.
109 Triangles(&'a [TriangleDefinition]),
110 /// Lines are formed by a pair of vertex indices.
111 Lines(&'a [[u32; 2]]),
112 /// Points are just straight vertex indices.
113 Points(&'a [u32]),
114}
115
116impl ElementsDescriptor<'_> {
117 /// Returns element kind of the elements' descriptor.
118 pub fn element_kind(&self) -> ElementKind {
119 match self {
120 ElementsDescriptor::Triangles(_) => ElementKind::Triangle,
121 ElementsDescriptor::Lines(_) => ElementKind::Line,
122 ElementsDescriptor::Points(_) => ElementKind::Point,
123 }
124 }
125}
126
127/// Descriptor of the geometry buffer. It essentially binds multiple vertex buffers and one element
128/// buffer.
129pub struct GeometryBufferDescriptor<'a> {
130 /// Vertex buffers of the buffer. There must be at least one vertex buffer.
131 pub buffers: &'a [VertexBufferDescriptor<'a>],
132 /// Usage of the geometry buffer. See [`BufferUsage`] docs for more info.
133 pub usage: BufferUsage,
134 /// Elements of the geometry buffer.
135 pub elements: ElementsDescriptor<'a>,
136}
137
138/// Geometry buffer is a mesh buffer, that could contain multiple vertex buffers and only one
139/// element buffer. Element could be either a line or triangle (the most commonly used one).
140///
141/// ## Examples
142///
143/// The simplest possible example shows how to create a geometry buffer that has a single triangle:
144///
145/// ```rust
146/// use fyrox_graphics::{
147/// buffer::BufferUsage,
148/// core::{algebra::Vector3, math::TriangleDefinition},
149/// error::FrameworkError,
150/// geometry_buffer::{
151/// AttributeDefinition, AttributeKind, ElementsDescriptor, GeometryBuffer,
152/// GeometryBufferDescriptor, VertexBufferData, VertexBufferDescriptor,
153/// },
154/// server::GraphicsServer,
155/// };
156/// use bytemuck::{Pod, Zeroable};
157///
158/// // Vertex type must implement a bunch of traits, that guarantees that the data will be tightly
159/// // packed with expected order of elements.
160/// #[derive(Pod, Copy, Clone, Zeroable)]
161/// #[repr(C)]
162/// struct Vertex {
163/// position: Vector3<f32>,
164/// }
165///
166/// fn create_geometry_buffer(
167/// server: &dyn GraphicsServer,
168/// ) -> Result<Box<dyn GeometryBuffer>, FrameworkError> {
169/// let vertices = [
170/// Vertex {
171/// position: Vector3::new(0.0, 0.0, 0.0),
172/// },
173/// Vertex {
174/// position: Vector3::new(0.0, 1.0, 0.0),
175/// },
176/// Vertex {
177/// position: Vector3::new(1.0, 0.0, 0.0),
178/// },
179/// ];
180///
181/// let triangles = [TriangleDefinition([0, 1, 2])];
182///
183/// server.create_geometry_buffer(GeometryBufferDescriptor {
184/// buffers: &[VertexBufferDescriptor {
185/// usage: BufferUsage::StaticDraw,
186/// attributes: &[AttributeDefinition {
187/// location: 0,
188/// kind: AttributeKind::Float,
189/// component_count: 3,
190/// normalized: false,
191/// divisor: 0,
192/// }],
193/// data: VertexBufferData::new(Some(&vertices)),
194/// }],
195/// usage: BufferUsage::StaticDraw,
196/// elements: ElementsDescriptor::Triangles(&triangles),
197/// })
198/// }
199/// ```
200pub trait GeometryBuffer: Downcast {
201 /// Write untyped data to a vertex buffer with the given index.
202 fn set_buffer_data(&self, buffer: usize, data: &[u8]);
203
204 /// Returns total number of elements in the geometry buffer.
205 fn element_count(&self) -> usize;
206
207 /// Writes triangles to the buffer. Each triangle definition contains triangle indices, that
208 /// forms the triangle.
209 fn set_triangles(&self, triangles: &[TriangleDefinition]);
210
211 /// Writes lines to the buffer. Each pair defines starting and ending vertex index of the line.
212 fn set_lines(&self, lines: &[[u32; 2]]);
213
214 /// Writes points to the buffer. Each index in the slice defines vertex index.
215 fn set_points(&self, points: &[u32]);
216}
217
218impl dyn GeometryBuffer {
219 /// Writes a typed data to a vertex buffer with the given index. Underlying type must implement
220 /// [`Pod`] trait!
221 pub fn set_buffer_data_of_type<T: Pod>(&mut self, buffer: usize, data: &[T]) {
222 self.set_buffer_data(buffer, array_as_u8_slice(data))
223 }
224}