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
156
157
158
159
160
161
162
163
164
165
mod context;
#[doc(inline)]
pub use context::*;
pub mod buffer;
pub use buffer::*;
pub mod math;
pub use math::*;
pub mod texture;
pub use texture::*;
mod cpu_mesh;
#[doc(inline)]
pub use cpu_mesh::*;
pub mod render_states;
pub use render_states::*;
pub mod render_target;
pub use render_target::*;
mod uniform;
#[doc(inline)]
pub use uniform::*;
mod cpu_material;
#[doc(inline)]
pub use cpu_material::*;
mod cpu_volume;
#[doc(inline)]
pub use cpu_volume::*;
mod camera;
#[doc(inline)]
pub use camera::*;
mod image_effect;
#[doc(inline)]
pub use image_effect::*;
mod image_cube_effect;
#[doc(inline)]
pub use image_cube_effect::*;
mod program;
#[doc(inline)]
pub use program::*;
mod aabb;
#[doc(inline)]
pub use aabb::*;
mod color;
#[doc(inline)]
pub use color::*;
mod viewport;
#[doc(inline)]
pub use viewport::*;
pub use crate::ThreeDResult;
use thiserror::Error;
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum CoreError {
#[error("failed creating context with error: {0}")]
ContextCreation(String),
#[error("failed rendering with error: {0}")]
ContextError(String),
#[error("failed creating shader: {0}")]
ShaderCreation(String),
#[error("failed creating program: {0}")]
ProgramCreation(String),
#[error("failed creating buffer: {0}")]
BufferCreation(String),
#[error("failed compiling {0} shader: {1}")]
ShaderCompilation(String, String),
#[error("failed to link shader program: {0}")]
ShaderLink(String),
#[error("the uniform {0} is sent to the shader but not defined or never used")]
UnusedUniform(String),
#[error("the attribute {0} is sent to the shader but not defined or never used")]
UnusedAttribute(String),
#[error("failed creating a new render target: {0}")]
RenderTargetCreation(String),
#[error("cannot read {0} from a render target without {0}")]
RenderTargetRead(String),
#[error("cannot read color from anything else but an RGBA texture")]
ReadWrongFormat,
#[error("failed creating a new texture: {0}")]
TextureCreation(String),
#[error("invalid size of texture data (got {0} bytes but expected {1} bytes)")]
InvalidTextureLength(usize, usize),
#[error("the render call requires the {0} vertex buffer which is missing on the given mesh")]
MissingMeshBuffer(String),
#[error(
"if the fragment shader defined 'in vec3 tang' it also needs to define 'in vec3 bitang'"
)]
MissingBitangent,
#[error("{0} buffer length must be {1}, actual length is {2}")]
InvalidBufferLength(String, usize, usize),
#[error("mesh must have both normals and uv coordinates to be able to compute tangents")]
FailedComputingTangents,
#[error("the number of vertices must be divisable by 3, actual count is {0}")]
InvalidNumberOfVertices(usize),
#[error("data for element at index {0} has length {1} but a length of {2} was expected")]
InvalidUniformBufferElementLength(u32, usize, usize),
#[error("the index {0} is outside the expected range [0, {1}]")]
IndexOutOfRange(usize, usize),
#[error("cannot take as input a negative minimum distance")]
NegativeDistance,
#[error("a minimum must be smaller than a maximum")]
MinimumLargerThanMaximum,
#[error("the transformation matrix cannot be inverted and is therefore invalid")]
FailedInvertingTransformationMatrix,
}
mod data_type;
use data_type::DataType;
fn to_byte_slice<'a, T: DataType>(data: &'a [T]) -> &'a [u8] {
unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const _,
data.len() * std::mem::size_of::<T>(),
)
}
}
fn from_byte_slice<'a, T: DataType>(data: &'a [u8]) -> &'a [T] {
unsafe {
let (_prefix, values, _suffix) = data.align_to::<T>();
values
}
}
fn format_from_data_type<T: DataType>() -> u32 {
match T::size() {
1 => crate::context::RED,
2 => crate::context::RG,
3 => crate::context::RGB,
4 => crate::context::RGBA,
_ => unreachable!(),
}
}
fn flip_y<T: TextureDataType>(pixels: &mut [T], width: usize, height: usize) {
for row in 0..height / 2 {
for col in 0..width {
let index0 = width * row + col;
let index1 = width * (height - row - 1) + col;
pixels.swap(index0, index1);
}
}
}