Skip to content

Commit 432138f

Browse files
committed
add all the things
1 parent a9b5072 commit 432138f

File tree

3 files changed

+170
-14
lines changed

3 files changed

+170
-14
lines changed

crates/bevy_geometry/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ edition = "2018"
1010
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1111

1212
[dependencies]
13+
bevy_transform = { path = "../bevy_transform", version = "0.4.0" }
1314
bevy_math = { path = "../bevy_math", version = "0.4.0" }
14-
bevy_reflect = { path = "../bevy_reflect", version = "0.4.0" }
15+
bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"] }

crates/bevy_geometry/src/lib.rs

Lines changed: 167 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,183 @@
1-
use bevy_math::{Quat, Vec3};
1+
use bevy_math::*;
2+
use bevy_reflect::Reflect;
3+
//use bevy_transform::components::GlobalTransform;
4+
use std::error::Error;
5+
use std::fmt;
26

3-
pub trait Primitive3d {}
7+
pub trait Primitive3d {
8+
/*
9+
/// Returns true if this primitive is on the outside (normal direction) of the supplied
10+
fn outside_plane(
11+
&self,
12+
primitive_transform: GlobalTransform,
13+
plane: Plane,
14+
plane_transform: GlobalTransform,
15+
) -> bool;*/
16+
}
417

5-
#[derive(Copy, Clone, PartialEq, Debug)]
18+
#[derive(Debug, Clone)]
19+
pub enum PrimitiveError {
20+
MinGreaterThanMax,
21+
NonPositiveExtents,
22+
}
23+
impl Error for PrimitiveError {}
24+
impl fmt::Display for PrimitiveError {
25+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26+
match self {
27+
PrimitiveError::MinGreaterThanMax => {
28+
write!(f, "AxisAlignedBox minimums must be smaller than maximums")
29+
}
30+
PrimitiveError::NonPositiveExtents => {
31+
write!(f, "AxisAlignedBox extents must be greater than zero")
32+
}
33+
}
34+
}
35+
}
36+
37+
#[derive(Copy, Clone, PartialEq, Debug, Reflect)]
638
pub struct Sphere {
739
pub origin: Vec3,
840
pub radius: f32,
941
}
42+
impl Primitive3d for Sphere {}
1043

11-
#[derive(Copy, Clone, PartialEq, Debug)]
12-
pub struct Box {
13-
pub maximums: Vec3,
14-
pub minimums: Vec3,
44+
/// An oriented box, unlike an axis aligned box, can be rotated and is not constrained to match the
45+
/// orientation of the coordinate system it is defined in. Internally, this is represented as an
46+
/// axis aligned box with some rotation ([Quat]) applied.
47+
#[derive(Copy, Clone, PartialEq, Debug, Reflect)]
48+
pub struct OrientedBox {
49+
pub aab: AxisAlignedBox,
1550
pub orientation: Quat,
1651
}
52+
impl Primitive3d for OrientedBox {}
1753

18-
#[derive(Copy, Clone, PartialEq, Debug)]
54+
/// An axis aligned box is a box whose axes lie in the x/y/z directions of the coordinate system
55+
/// the box is defined in.
56+
#[derive(Copy, Clone, PartialEq, Debug, Reflect)]
1957
pub struct AxisAlignedBox {
20-
pub maximums: Vec3,
21-
pub minimums: Vec3,
58+
minimums: Vec3,
59+
maximums: Vec3,
2260
}
61+
impl Primitive3d for AxisAlignedBox {}
62+
impl AxisAlignedBox {
63+
pub fn from_min_max(minimums: Vec3, maximums: Vec3) -> Result<AxisAlignedBox, PrimitiveError> {
64+
if (maximums - minimums).min_element() > 0.0 {
65+
Ok(AxisAlignedBox { minimums, maximums })
66+
} else {
67+
Err(PrimitiveError::MinGreaterThanMax)
68+
}
69+
}
70+
pub fn from_extents_origin(
71+
extents: Vec3,
72+
origin: Vec3,
73+
) -> Result<AxisAlignedBox, PrimitiveError> {
74+
if extents.min_element() > 0.0 {
75+
Ok(AxisAlignedBox {
76+
minimums: origin,
77+
maximums: extents + origin,
78+
})
79+
} else {
80+
Err(PrimitiveError::NonPositiveExtents)
81+
}
82+
}
83+
}
84+
85+
/// A frustum is a truncated pyramid that is used to represent the "volume" of world space that is
86+
/// visible to the camera.
87+
#[derive(Copy, Clone, PartialEq, Debug, Reflect)]
88+
#[reflect_value(PartialEq)]
89+
pub struct Frustum {
90+
planes: [Plane; 6],
91+
}
92+
impl Primitive3d for Frustum {}
93+
impl Frustum {
94+
pub fn from_camera_properties(
95+
&self,
96+
camera_position: Mat4,
97+
projection_matrix: Mat4,
98+
) -> Frustum {
99+
let ndc_to_world: Mat4 = camera_position * projection_matrix.inverse();
100+
// Near/Far, Top/Bottom, Left/Right
101+
let nbl_world = ndc_to_world.project_point3(Vec3::new(-1.0, -1.0, -1.0));
102+
let nbr_world = ndc_to_world.project_point3(Vec3::new(1.0, -1.0, -1.0));
103+
let ntl_world = ndc_to_world.project_point3(Vec3::new(-1.0, 1.0, -1.0));
104+
let fbl_world = ndc_to_world.project_point3(Vec3::new(-1.0, -1.0, 1.0));
105+
let ftr_world = ndc_to_world.project_point3(Vec3::new(1.0, 1.0, 1.0));
106+
let ftl_world = ndc_to_world.project_point3(Vec3::new(-1.0, 1.0, 1.0));
107+
let fbr_world = ndc_to_world.project_point3(Vec3::new(1.0, -1.0, 1.0));
108+
let ntr_world = ndc_to_world.project_point3(Vec3::new(1.0, 1.0, -1.0));
109+
110+
let near_normal = (nbr_world - nbl_world)
111+
.cross(ntl_world - nbl_world)
112+
.normalize();
113+
let far_normal = (fbr_world - ftr_world)
114+
.cross(ftl_world - ftr_world)
115+
.normalize();
116+
let top_normal = (ftl_world - ftr_world)
117+
.cross(ntr_world - ftr_world)
118+
.normalize();
119+
let bottom_normal = (fbl_world - nbl_world)
120+
.cross(nbr_world - nbl_world)
121+
.normalize();
122+
let right_normal = (ntr_world - ftr_world)
123+
.cross(fbr_world - ftr_world)
124+
.normalize();
125+
let left_normal = (ntl_world - nbl_world)
126+
.cross(fbl_world - nbl_world)
127+
.normalize();
23128

129+
let left = Plane {
130+
point: nbl_world,
131+
normal: left_normal,
132+
};
133+
let right = Plane {
134+
point: ftr_world,
135+
normal: right_normal,
136+
};
137+
let bottom = Plane {
138+
point: nbl_world,
139+
normal: bottom_normal,
140+
};
141+
let top = Plane {
142+
point: ftr_world,
143+
normal: top_normal,
144+
};
145+
let near = Plane {
146+
point: nbl_world,
147+
normal: near_normal,
148+
};
149+
let far = Plane {
150+
point: ftr_world,
151+
normal: far_normal,
152+
};
153+
Frustum {
154+
planes: [left, right, top, bottom, near, far],
155+
}
156+
}
157+
}
158+
159+
/// A plane is defined by a point in space and a normal vector at that point.
24160
#[derive(Copy, Clone, PartialEq, Debug)]
25161
pub struct Plane {
26-
pub point: Vec3,
27-
pub normal: Vec3,
162+
point: Vec3,
163+
normal: Vec3,
164+
}
165+
impl Primitive3d for Plane {}
166+
impl Plane {
167+
/// Generate a plane from three points that lie on the plane.
168+
pub fn from_points(points: [Vec3; 3]) -> Plane {
169+
let point = points[1];
170+
let arm_1 = points[0] - point;
171+
let arm_2 = points[2] - point;
172+
let normal = arm_1.cross(arm_2).normalize();
173+
Plane { point, normal }
174+
}
175+
/// Generate a plane from a point on that plane and the normal direction of the plane. The
176+
/// normal vector does not need to be normalized (length can be != 1).
177+
pub fn from_point_normal(point: Vec3, normal: Vec3) -> Plane {
178+
Plane {
179+
point,
180+
normal: normal.normalize(),
181+
}
182+
}
28183
}

tools/publish.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ crates=(
33
bevy_utils
44
bevy_derive
55
bevy_math
6-
bevy_geometry
76
bevy_tasks
87
bevy_ecs/macros
98
bevy_ecs
@@ -17,6 +16,7 @@ crates=(
1716
bevy_core
1817
bevy_diagnostic
1918
bevy_transform
19+
bevy_geometry
2020
bevy_window
2121
bevy_render
2222
bevy_input

0 commit comments

Comments
 (0)