From 54c0fd70f82eb1a6814872c78bc22380f438c9d1 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 22 Oct 2023 19:29:11 +0200 Subject: feat(engine): add translating & scaling objects --- engine/Cargo.toml | 1 + engine/src/lib.rs | 4 ++- engine/src/matrix.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++ engine/src/object.rs | 26 +++++++++++++++++- engine/src/opengl/shader.rs | 12 +++++++++ engine/src/renderer/mod.rs | 14 +++++++--- engine/src/transform.rs | 45 +++++++++++++++++++++++++++++++ engine/src/vector.rs | 2 +- engine/vertex.glsl | 4 ++- 9 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 engine/src/matrix.rs create mode 100644 engine/src/transform.rs (limited to 'engine') 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 +{ + /// Items must be layed out this way for it to work with OpenGL shaders. + items: [[Value; ROWS]; COLUMNS], +} + +impl Matrix +{ + /// 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 Matrix +{ + /// 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 +{ + pub fn translate(&mut self, translation: &Vec3) + { + 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) + { + 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) + { + self.transform.set_translation(translation); + } + + pub fn scale(&mut self, scaling: Vec3) + { + 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) + { + 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) +pub fn render<'obj>(objects: impl IntoIterator) { 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, + scaling: Vec3, +} + +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) + { + self.translation = translation; + } + + pub fn set_scaling(&mut self, scaling: Vec3) + { + self.scaling = scaling; + } + + pub fn as_matrix(&self) -> Matrix + { + 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 pub const ZERO: Self = Self { x: 0, y: 0 }; } -#[derive(Debug)] +#[derive(Debug, Default, Clone)] #[repr(C)] pub struct Vec3 { 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; } -- cgit v1.2.3-18-g5258