summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-10-22 19:29:11 +0200
committerHampusM <hampus@hampusmat.com>2023-10-22 19:29:11 +0200
commit54c0fd70f82eb1a6814872c78bc22380f438c9d1 (patch)
tree7b0b67b52daa7ce18432c7b83caa862234a3255c
parent30394c16ccdcdb145352e245a7a8893cef28e82d (diff)
feat(engine): add translating & scaling objects
-rw-r--r--Cargo.lock11
-rw-r--r--engine/Cargo.toml1
-rw-r--r--engine/src/lib.rs4
-rw-r--r--engine/src/matrix.rs65
-rw-r--r--engine/src/object.rs26
-rw-r--r--engine/src/opengl/shader.rs12
-rw-r--r--engine/src/renderer/mod.rs14
-rw-r--r--engine/src/transform.rs45
-rw-r--r--engine/src/vector.rs2
-rw-r--r--engine/vertex.glsl4
10 files changed, 176 insertions, 8 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ed47841..7010e6c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -76,6 +76,16 @@ dependencies = [
]
[[package]]
+name = "cstr"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8aa998c33a6d3271e3678950a22134cd7dd27cef86dee1b611b5b14207d1d90b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -86,6 +96,7 @@ name = "engine"
version = "0.1.0"
dependencies = [
"bitflags",
+ "cstr",
"gl",
"glfw",
"thiserror",
diff --git a/engine/Cargo.toml b/engine/Cargo.toml
index ff52cce..023c711 100644
--- a/engine/Cargo.toml
+++ b/engine/Cargo.toml
@@ -11,4 +11,5 @@ glfw = { path = "../glfw" }
thiserror = "1.0.49"
gl = "0.14.0"
bitflags = "2.4.0"
+cstr = "0.2.11"
tracing = { version = "0.1.39", optional = true }
diff --git a/engine/src/lib.rs b/engine/src/lib.rs
index db6ab94..dbbd407 100644
--- a/engine/src/lib.rs
+++ b/engine/src/lib.rs
@@ -7,8 +7,10 @@ use glfw::{Window, WindowBuilder};
use crate::object::{Id as ObjectId, Object};
use crate::vector::Vec2;
+mod matrix;
mod opengl;
mod renderer;
+mod transform;
pub mod color;
pub mod object;
@@ -91,7 +93,7 @@ impl Engine
while !self.window.should_close() {
func(self);
- crate::renderer::render(self.objects.values().map(Object::renderable));
+ crate::renderer::render(self.objects.values());
self.window
.swap_buffers()
diff --git a/engine/src/matrix.rs b/engine/src/matrix.rs
new file mode 100644
index 0000000..7e161f2
--- /dev/null
+++ b/engine/src/matrix.rs
@@ -0,0 +1,65 @@
+use crate::vector::Vec3;
+
+#[derive(Debug, Clone)]
+#[repr(C)]
+pub struct Matrix<Value, const ROWS: usize, const COLUMNS: usize>
+{
+ /// Items must be layed out this way for it to work with OpenGL shaders.
+ items: [[Value; ROWS]; COLUMNS],
+}
+
+impl<Value, const ROWS: usize, const COLUMNS: usize> Matrix<Value, ROWS, COLUMNS>
+{
+ /// Sets the value at the specified cell.
+ pub fn set_cell(&mut self, row: usize, column: usize, value: Value)
+ {
+ self.items[column][row] = value;
+ }
+
+ #[must_use]
+ pub fn as_ptr(&self) -> *const Value
+ {
+ self.items[0].as_ptr()
+ }
+}
+
+impl<const ROWS_COLS: usize> Matrix<f32, ROWS_COLS, ROWS_COLS>
+{
+ /// Creates a new identity matrix.
+ #[must_use]
+ pub fn new_identity() -> Self
+ {
+ let mut index = 0;
+
+ let items = [(); ROWS_COLS].map(|()| {
+ let mut columns = [0.0; ROWS_COLS];
+
+ columns[index] = 1.0;
+
+ index += 1;
+
+ columns
+ });
+
+ Self { items }
+ }
+}
+
+impl Matrix<f32, 4, 4>
+{
+ pub fn translate(&mut self, translation: &Vec3<f32>)
+ {
+ self.set_cell(0, 3, translation.x);
+ self.set_cell(1, 3, translation.y);
+ self.set_cell(2, 3, translation.z);
+ self.set_cell(3, 3, 1.0);
+ }
+
+ pub fn scale(&mut self, scaling: &Vec3<f32>)
+ {
+ self.set_cell(0, 0, scaling.x);
+ self.set_cell(1, 1, scaling.y);
+ self.set_cell(2, 2, scaling.z);
+ self.set_cell(3, 3, 1.0);
+ }
+}
diff --git a/engine/src/object.rs b/engine/src/object.rs
index 11ba7e6..c3d82d0 100644
--- a/engine/src/object.rs
+++ b/engine/src/object.rs
@@ -5,6 +5,8 @@ use crate::opengl::shader::{
Shader,
};
use crate::renderer::Renderable;
+use crate::transform::Transform;
+use crate::vector::Vec3;
use crate::vertex::Vertex;
#[derive(Debug)]
@@ -12,6 +14,7 @@ pub struct Object
{
id: Id,
renderable: Renderable,
+ transform: Transform,
}
impl Object
@@ -53,7 +56,13 @@ impl Object
let renderable = Renderable::new(shader_program, vertices);
- Ok(Self { id, renderable })
+ let transform = Transform::new();
+
+ Ok(Self {
+ id,
+ renderable,
+ transform,
+ })
}
/// Returns the object ID.
@@ -63,10 +72,25 @@ impl Object
self.id
}
+ pub fn translate(&mut self, translation: Vec3<f32>)
+ {
+ self.transform.set_translation(translation);
+ }
+
+ pub fn scale(&mut self, scaling: Vec3<f32>)
+ {
+ self.transform.set_scaling(scaling);
+ }
+
pub(crate) fn renderable(&self) -> &Renderable
{
&self.renderable
}
+
+ pub(crate) fn transform(&self) -> &Transform
+ {
+ &self.transform
+ }
}
/// Object error
diff --git a/engine/src/opengl/shader.rs b/engine/src/opengl/shader.rs
index 0bbca77..603c790 100644
--- a/engine/src/opengl/shader.rs
+++ b/engine/src/opengl/shader.rs
@@ -1,6 +1,8 @@
use std::ffi::CStr;
use std::ptr::null_mut;
+use crate::matrix::Matrix;
+
#[derive(Debug)]
pub struct Shader
{
@@ -156,6 +158,16 @@ impl Program
}
}
+ pub fn set_uniform_matrix_4fv(&self, name: &CStr, matrix: &Matrix<f32, 4, 4>)
+ {
+ let uniform_location =
+ unsafe { gl::GetUniformLocation(self.program, name.as_ptr().cast()) };
+
+ unsafe {
+ gl::UniformMatrix4fv(uniform_location, 1, gl::FALSE, matrix.as_ptr());
+ }
+ }
+
fn get_info_log(&self) -> String
{
let mut buf = vec![gl::types::GLchar::default(); 512];
diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs
index 8ca85e2..068b8f0 100644
--- a/engine/src/renderer/mod.rs
+++ b/engine/src/renderer/mod.rs
@@ -1,8 +1,10 @@
use std::ffi::{c_void, CString};
use std::process::abort;
+use cstr::cstr;
use glfw::WindowSize;
+use crate::object::Object;
#[cfg(feature = "debug")]
use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType};
use crate::opengl::shader::Program as ShaderProgram;
@@ -92,14 +94,18 @@ fn opengl_debug_message_cb(
};
}
-pub fn render<'renderable>(renderables: impl IntoIterator<Item = &'renderable Renderable>)
+pub fn render<'obj>(objects: impl IntoIterator<Item = &'obj Object>)
{
clear_buffers(BufferClearMask::COLOR);
- for renderable in renderables {
- renderable.shader_program.activate();
+ for obj in objects {
+ obj.renderable().shader_program.activate();
- renderable.vertex_arr.bind(|vert_arr_curr_bound| {
+ obj.renderable()
+ .shader_program
+ .set_uniform_matrix_4fv(cstr!("transform"), &obj.transform().as_matrix());
+
+ obj.renderable().vertex_arr.bind(|vert_arr_curr_bound| {
VertexArray::draw(&vert_arr_curr_bound, PrimitiveKind::Triangles, 0, 3);
});
}
diff --git a/engine/src/transform.rs b/engine/src/transform.rs
new file mode 100644
index 0000000..9ce52ee
--- /dev/null
+++ b/engine/src/transform.rs
@@ -0,0 +1,45 @@
+use crate::matrix::Matrix;
+use crate::vector::Vec3;
+
+#[derive(Debug, Clone)]
+pub struct Transform
+{
+ translation: Vec3<f32>,
+ scaling: Vec3<f32>,
+}
+
+impl Transform
+{
+ pub fn new() -> Self
+ {
+ Self {
+ translation: Vec3::default(),
+ scaling: Vec3 {
+ x: 1.0,
+ y: 1.0,
+ z: 1.0,
+ },
+ }
+ }
+
+ pub fn set_translation(&mut self, translation: Vec3<f32>)
+ {
+ self.translation = translation;
+ }
+
+ pub fn set_scaling(&mut self, scaling: Vec3<f32>)
+ {
+ self.scaling = scaling;
+ }
+
+ pub fn as_matrix(&self) -> Matrix<f32, 4, 4>
+ {
+ let mut matrix = Matrix::new_identity();
+
+ matrix.translate(&self.translation);
+
+ matrix.scale(&self.scaling);
+
+ matrix
+ }
+}
diff --git a/engine/src/vector.rs b/engine/src/vector.rs
index ada64c4..c25a258 100644
--- a/engine/src/vector.rs
+++ b/engine/src/vector.rs
@@ -10,7 +10,7 @@ impl Vec2<u32>
pub const ZERO: Self = Self { x: 0, y: 0 };
}
-#[derive(Debug)]
+#[derive(Debug, Default, Clone)]
#[repr(C)]
pub struct Vec3<Value>
{
diff --git a/engine/vertex.glsl b/engine/vertex.glsl
index 37d5677..db3d612 100644
--- a/engine/vertex.glsl
+++ b/engine/vertex.glsl
@@ -4,9 +4,11 @@ layout (location = 1) in vec3 color;
out vec3 in_frag_color;
+uniform mat4 transform;
+
void main()
{
- gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
+ gl_Position = transform * vec4(pos, 1.0);
in_frag_color = color;
}