From 9dbcb2b811d2adc8c58e039723f88869ad9a5c4a Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Mon, 18 Sep 2023 11:23:49 +0100 Subject: [PATCH] Basic brush plane intersection calculation --- Cargo.lock | 12 +++++++++ csg/Cargo.toml | 1 + csg/src/brush.rs | 63 +++++++++++++++++++++++++++++++++++++++++++ csg/src/lib.rs | 6 +++++ csg/src/math.rs | 1 + csg/src/plane.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ editor/Cargo.toml | 3 ++- editor/src/main.rs | 33 ++++++++++++++++++++++- 8 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 csg/src/brush.rs create mode 100644 csg/src/math.rs create mode 100644 csg/src/plane.rs diff --git a/Cargo.lock b/Cargo.lock index 83c8aa9..a14a22e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,19 @@ version = 3 [[package]] name = "csg" version = "0.1.0" +dependencies = [ + "glam", +] [[package]] name = "editor" version = "0.1.0" +dependencies = [ + "csg", +] + +[[package]] +name = "glam" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42218cb640844e3872cc3c153dc975229e080a6c4733b34709ef445610550226" diff --git a/csg/Cargo.toml b/csg/Cargo.toml index 30d1a4a..f969eb9 100644 --- a/csg/Cargo.toml +++ b/csg/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +glam = "0.24.1" diff --git a/csg/src/brush.rs b/csg/src/brush.rs new file mode 100644 index 0000000..1af0949 --- /dev/null +++ b/csg/src/brush.rs @@ -0,0 +1,63 @@ +use glam::Vec3; + +use crate::plane::{Plane, PlaneIntersection}; + +pub struct MaterialId(pub String); + +pub struct TextureProjection { + pub u: Plane, + pub v: Plane, +} + +impl Default for TextureProjection { + fn default() -> Self { + Self { + u: Plane { + normal: glam::vec3(1.0, 0.0, 0.0), + offset: 0.0, + }, + v: Plane { + normal: glam::vec3(0.0, 1.0, 0.0), + offset: 0.0, + }, + } + } +} + +pub struct BrushPlane { + pub plane: Plane, + pub material: MaterialId, + pub tex_projection: TextureProjection, +} + +pub struct Brush { + pub planes: Vec, +} + +impl Brush { + pub fn get_vertices(&self) -> Vec { + if self.planes.len() < 3 { + println!("fug"); + return vec![]; + } + + let mut vs = vec![]; + let len = self.planes.len(); + for i in 0..(len - 2) { + for j in (i + 1)..(len - 1) { + for k in (j + 1)..len { + if let Some(intersection) = PlaneIntersection::from_planes( + self.planes[i].plane, + self.planes[j].plane, + self.planes[k].plane, + ) { + // TODO: Validate that the found intersection is within all brush planes + vs.push(intersection.get_intersection_point()) + } + } + } + } + + vs + } +} diff --git a/csg/src/lib.rs b/csg/src/lib.rs index 7d12d9a..3eb0ddf 100644 --- a/csg/src/lib.rs +++ b/csg/src/lib.rs @@ -1,3 +1,9 @@ +pub mod brush; +pub mod math; +pub mod plane; + +pub use glam; + pub fn add(left: usize, right: usize) -> usize { left + right } diff --git a/csg/src/math.rs b/csg/src/math.rs new file mode 100644 index 0000000..410b9cc --- /dev/null +++ b/csg/src/math.rs @@ -0,0 +1 @@ +pub const EPSILON: f32 = 0.0001; diff --git a/csg/src/plane.rs b/csg/src/plane.rs new file mode 100644 index 0000000..ac8d678 --- /dev/null +++ b/csg/src/plane.rs @@ -0,0 +1,66 @@ +use glam::{Mat3, Vec3}; + +use crate::math; + +#[derive(Clone, Copy, Debug)] +pub struct Plane { + pub normal: Vec3, + pub offset: f32, +} + +impl Plane { + pub fn from_point_normal(point: Vec3, normal: Vec3) -> Self { + Self { + normal, + offset: -point.dot(normal), + } + } +} + +pub struct PlaneIntersection { + pub planes: [Plane; 3], +} + +impl PlaneIntersection { + pub fn from_planes(p1: Plane, p2: Plane, p3: Plane) -> Option { + let plane = Self { + planes: [p1, p2, p3], + }; + + let determinant = plane.get_matrix().determinant(); + // println!("Determinant: {determinant}"); + if determinant.abs() > math::EPSILON { + Some(plane) + } else { + None + } + } + + pub fn get_intersection_point(&self) -> Vec3 { + let base_matrix = self.get_matrix(); + let base_det = base_matrix.determinant(); + let offsets = glam::vec3( + self.planes[0].offset, + self.planes[1].offset, + self.planes[2].offset, + ); + + let mut vs = vec![]; + for idx in 0..3 { + let mut matrix = base_matrix; + *(matrix.col_mut(idx)) = -offsets; + vs.push(matrix.determinant() / base_det); + } + + Vec3::from_slice(&vs) + } + + fn get_matrix(&self) -> Mat3 { + glam::mat3( + self.planes[0].normal, + self.planes[1].normal, + self.planes[2].normal, + ) + .transpose() + } +} diff --git a/editor/Cargo.toml b/editor/Cargo.toml index f430d3f..c2968e2 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -1,8 +1,9 @@ [package] -name = "editor" +name = "editor" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +csg = { path = "../csg" } diff --git a/editor/src/main.rs b/editor/src/main.rs index e7a11a9..29287b8 100644 --- a/editor/src/main.rs +++ b/editor/src/main.rs @@ -1,3 +1,34 @@ +use csg::{ + brush::{self, Brush, BrushPlane, MaterialId, TextureProjection}, + glam::{self}, + plane::Plane, +}; + fn main() { - println!("Hello, world!"); + let points = vec![ + glam::vec3(1.0, 0.0, 0.0), + glam::vec3(-1.0, 0.0, 0.0), + glam::vec3(0.0, 1.0, 0.0), + glam::vec3(0.0, -1.0, 0.0), + glam::vec3(0.0, 0.0, 1.0), + glam::vec3(0.0, 0.0, -1.0), + ]; + + let mut brush_planes = vec![]; + for point in &points { + brush_planes.push(BrushPlane { + plane: Plane::from_point_normal(*point, *point), + material: MaterialId("Epic".to_string()), + tex_projection: TextureProjection::default(), + }); + + println!("Plane: {:?}", brush_planes.last().unwrap().plane); + } + + let brush = Brush { + planes: brush_planes, + }; + let vs = brush.get_vertices(); + + println!("Vertices: {vs:?}"); }