1use crate::{ops, Vec3, Vec3A, Vec4, Vec4Swizzles};
2
3#[cfg(feature = "bevy_reflect")]
4use bevy_reflect::{std_traits::ReflectDefault, Reflect};
5#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
6use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
7
8#[derive(#[automatically_derived]
impl ::core::clone::Clone for HalfSpace {
#[inline]
fn clone(&self) -> HalfSpace {
let _: ::core::clone::AssertParamIsClone<Vec4>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for HalfSpace { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for HalfSpace {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "HalfSpace",
"normal_d", &&self.normal_d)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for HalfSpace {
#[inline]
fn default() -> HalfSpace {
HalfSpace { normal_d: ::core::default::Default::default() }
}
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for HalfSpace {
#[inline]
fn eq(&self, other: &HalfSpace) -> bool {
self.normal_d == other.normal_d
}
}PartialEq)]
33#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for HalfSpace {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"HalfSpace", false as usize + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"normal_d", &self.normal_d)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for HalfSpace {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"normal_d" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"normal_d" => _serde::__private228::Ok(__Field::__field0),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<HalfSpace>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = HalfSpace;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct HalfSpace")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<Vec4>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct HalfSpace with 1 element")),
};
_serde::__private228::Ok(HalfSpace { normal_d: __field0 })
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<Vec4> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("normal_d"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec4>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("normal_d")?,
};
_serde::__private228::Ok(HalfSpace { normal_d: __field0 })
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &["normal_d"];
_serde::Deserializer::deserialize_struct(__deserializer,
"HalfSpace", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<HalfSpace>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};serde::Deserialize))]
34#[cfg_attr(
35 feature = "bevy_reflect",
36 derive(const _: () =
{
impl bevy_reflect::GetTypeRegistration for HalfSpace where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
registration.register_type_data::<ReflectDefault, Self>();
registration.register_type_data::<ReflectSerialize, Self>();
registration.register_type_data::<ReflectDeserialize, Self>();
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<Vec4 as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for HalfSpace where {
#[inline]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec4>("normal_d")]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for HalfSpace where {
fn type_path() -> &'static str {
"bevy_math::primitives::half_space::HalfSpace"
}
fn short_type_path() -> &'static str { "HalfSpace" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("HalfSpace")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_math::primitives::half_space".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_math::primitives::half_space")
}
}
impl bevy_reflect::Reflect for HalfSpace where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
impl bevy_reflect::structs::Struct for HalfSpace where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name {
"normal_d" => ::core::option::Option::Some(&self.normal_d),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name {
"normal_d" =>
::core::option::Option::Some(&mut self.normal_d),
_ => ::core::option::Option::None,
}
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.normal_d),
_ => ::core::option::Option::None,
}
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.normal_d),
_ => ::core::option::Option::None,
}
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index {
0usize => ::core::option::Option::Some("normal_d"),
_ => ::core::option::Option::None,
}
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name {
"normal_d" => ::core::option::Option::Some(0usize),
_ => ::core::option::Option::None,
}
}
fn field_len(&self) -> usize { 1usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
-> bevy_reflect::structs::DynamicStruct {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed("normal_d",
bevy_reflect::PartialReflect::to_dynamic(&self.normal_d));
dynamic
}
}
impl bevy_reflect::PartialReflect for HalfSpace where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for HalfSpace where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<Vec4 as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"normal_d")?))() {
__this.normal_d = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect),
37 reflect(Clone, Debug, Default, PartialEq)
38)]
39#[cfg_attr(
40 all(feature = "serialize", feature = "bevy_reflect"),
41 reflect(Serialize, Deserialize)
42)]
43pub struct HalfSpace {
44 normal_d: Vec4,
45}
46
47impl HalfSpace {
48 #[inline]
53 pub fn new(normal_d: Vec4) -> Self {
54 Self {
55 normal_d: normal_d * normal_d.xyz().length_recip(),
56 }
57 }
58
59 #[inline]
61 pub fn normal(&self) -> Vec3A {
62 Vec3A::from_vec4(self.normal_d)
63 }
64
65 #[inline]
68 pub fn d(&self) -> f32 {
69 self.normal_d.w
70 }
71
72 #[inline]
75 pub fn normal_d(&self) -> Vec4 {
76 self.normal_d
77 }
78
79 #[inline]
81 pub fn intersection_point(a: HalfSpace, b: HalfSpace, c: HalfSpace) -> Option<Vec3> {
82 let an = a.normal();
83 let bn = b.normal();
84 let cn = c.normal();
85
86 let x = Vec3A::new(an.x, bn.x, cn.x);
87 let y = Vec3A::new(an.y, bn.y, cn.y);
88 let z = Vec3A::new(an.z, bn.z, cn.z);
89
90 let d = -Vec3A::new(a.d(), b.d(), c.d());
91
92 let u = y.cross(z);
93 let v = x.cross(d);
94
95 let denom = x.dot(u);
96
97 if ops::abs(denom) < f32::EPSILON {
98 return None;
99 }
100
101 Some(Vec3::new(d.dot(u), z.dot(v), -y.dot(v)) / denom)
102 }
103}
104
105#[cfg(test)]
106mod half_space_tests {
107 use core::f32;
108
109 use approx::assert_relative_eq;
110
111 use super::HalfSpace;
112 use crate::{Vec3, Vec4};
113
114 #[test]
115 fn intersection_point() {
116 let xy_at_z_3 = HalfSpace {
118 normal_d: Vec4::new(0., 0., -1., 3.),
119 };
120 let xz_at_y_2 = HalfSpace {
121 normal_d: Vec4::new(0., 1., 0., -2.),
122 };
123 let yz_at_x_1 = HalfSpace {
124 normal_d: Vec4::new(1., 0., 0., -1.),
125 };
126 assert_relative_eq!(
127 HalfSpace::intersection_point(xy_at_z_3, xz_at_y_2, yz_at_x_1).unwrap(),
128 Vec3::new(1., 2., 3.),
129 epsilon = 2e-7
130 );
131
132 let xz_at_y_3 = HalfSpace {
134 normal_d: Vec4::new(0., 1., 0., -3.),
135 };
136 assert!(HalfSpace::intersection_point(xy_at_z_3, xz_at_y_2, xz_at_y_3).is_none());
137
138 let other_xz_at_y_2 = HalfSpace {
140 normal_d: Vec4::new(0., -1., 0., 3.),
141 };
142 assert!(HalfSpace::intersection_point(xy_at_z_3, xz_at_y_2, other_xz_at_y_2).is_none());
143
144 assert!(HalfSpace::intersection_point(xz_at_y_2, xz_at_y_2, other_xz_at_y_2).is_none());
146
147 let ill_defined = HalfSpace {
149 normal_d: Vec4::new(0., 0., 0., f32::INFINITY),
150 };
151 assert!(HalfSpace::intersection_point(xy_at_z_3, xz_at_y_2, ill_defined).is_none());
152 }
153}