I guess I'll try and do some work (something about trying to force inline the vector operators but failing, and ensuring the internal physics system should work for the dreamcast with its quantized meshes (maybe, it's still quite underperforming compared to RP3D), probably some other things from a week or so ago)
This commit is contained in:
parent
36612f9ce9
commit
8dd83f7f49
@ -7,8 +7,7 @@
|
|||||||
"physics": {
|
"physics": {
|
||||||
"mass": 0,
|
"mass": 0,
|
||||||
"inertia": [0, 0, 0],
|
"inertia": [0, 0, 0],
|
||||||
"type": "bounding box",
|
"type": "mesh" // "bounding box"
|
||||||
"recenter": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@
|
|||||||
"physics": {
|
"physics": {
|
||||||
"mass": 0,
|
"mass": 0,
|
||||||
"type": "bounding box"
|
"type": "bounding box"
|
||||||
|
// "type": "mesh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,10 +8,16 @@ namespace pod {
|
|||||||
template<typename T = NUM, size_t R = 4, size_t C = R>
|
template<typename T = NUM, size_t R = 4, size_t C = R>
|
||||||
struct /*UF_API*/ Matrix {
|
struct /*UF_API*/ Matrix {
|
||||||
// n-dimensional/unspecialized matrix access
|
// n-dimensional/unspecialized matrix access
|
||||||
T components[R*C] = {};
|
union {
|
||||||
|
T components[R*C] = {};
|
||||||
|
pod::Vector<T, C> _rows[R]; // to-do: better name
|
||||||
|
pod::Vector<T, R> _columns[C]; // to-do: better name
|
||||||
|
};
|
||||||
// POD information
|
// POD information
|
||||||
typedef T type_t;
|
typedef T type_t;
|
||||||
typedef T* container_t;
|
typedef T* container_t;
|
||||||
|
typedef pod::Vector<T, R> row_t;
|
||||||
|
typedef pod::Vector<T, C> col_t;
|
||||||
static const size_t rows = R;
|
static const size_t rows = R;
|
||||||
static const size_t columns = C;
|
static const size_t columns = C;
|
||||||
// Overload access
|
// Overload access
|
||||||
@ -23,12 +29,12 @@ namespace pod {
|
|||||||
FORCE_INLINE const T& operator()(size_t r, size_t c) const;
|
FORCE_INLINE const T& operator()(size_t r, size_t c) const;
|
||||||
|
|
||||||
// Arithmetic
|
// Arithmetic
|
||||||
Matrix<T,R,C> operator*( const Matrix<T,R,C>& matrix ) const;
|
FORCE_INLINE Matrix<T,R,C> operator*( const Matrix<T,R,C>& matrix ) const;
|
||||||
Matrix<T,R,C> operator*( T scalar ) const;
|
FORCE_INLINE Matrix<T,R,C> operator*( T scalar ) const;
|
||||||
Matrix<T,R,C> operator+( const Matrix<T,R,C>& matrix ) const;
|
FORCE_INLINE Matrix<T,R,C> operator+( const Matrix<T,R,C>& matrix ) const;
|
||||||
Matrix<T,R,C>& operator *=( const Matrix<T,R,C>& matrix );
|
FORCE_INLINE Matrix<T,R,C>& operator *=( const Matrix<T,R,C>& matrix );
|
||||||
bool operator==( const Matrix<T,R,C>& matrix ) const;
|
FORCE_INLINE bool operator==( const Matrix<T,R,C>& matrix ) const;
|
||||||
bool operator!=( const Matrix<T,R,C>& matrix ) const;
|
FORCE_INLINE bool operator!=( const Matrix<T,R,C>& matrix ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T = NUM> using Matrix2t = Matrix<T,2>;
|
template<typename T = NUM> using Matrix2t = Matrix<T,2>;
|
||||||
@ -48,66 +54,66 @@ namespace uf {
|
|||||||
namespace matrix {
|
namespace matrix {
|
||||||
extern bool UF_API reverseInfiniteProjection;
|
extern bool UF_API reverseInfiniteProjection;
|
||||||
|
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ identity();
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ identity();
|
||||||
|
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ initialize( const T* );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ initialize( const T* );
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ initialize( const uf::stl::vector<T>& );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ initialize( const uf::stl::vector<T>& );
|
||||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> /*UF_API*/ identityi();
|
template<typename T> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> /*UF_API*/ identityi();
|
||||||
|
|
||||||
template<typename T=pod::Matrix4> bool /*UF_API*/ equals( const T& left, const T& right, float eps = 1.0e-6f );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ bool /*UF_API*/ equals( const T& left, const T& right, float eps = 1.0e-6f );
|
||||||
|
|
||||||
template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply( const T& left, const U& right );
|
template<typename T, typename U> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> multiply( const T& left, const U& right );
|
||||||
template<typename T> pod::Matrix4t<T> multiply( const pod::Matrix4t<T>& left, const pod::Matrix4t<T>& right );
|
template<typename T> /*FORCE_INLINE*/ pod::Matrix4t<T> multiply( const pod::Matrix4t<T>& left, const pod::Matrix4t<T>& right );
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ transpose( const T& matrix );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ transpose( const T& matrix );
|
||||||
|
|
||||||
template<typename T=NUM> pod::Matrix2t<T> inverse(const pod::Matrix2t<T>& mat );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix2t<T> inverse(const pod::Matrix2t<T>& mat );
|
||||||
template<typename T=NUM> pod::Matrix3t<T> inverse(const pod::Matrix3t<T>& mat );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix3t<T> inverse(const pod::Matrix3t<T>& mat );
|
||||||
template<typename T=NUM> pod::Matrix4t<T> inverse(const pod::Matrix4t<T>& mat );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> inverse(const pod::Matrix4t<T>& mat );
|
||||||
|
|
||||||
template<typename T=NUM> pod::Vector2t<T> multiply(const pod::Matrix2t<T>& mat, const pod::Vector2t<T>& v );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Vector2t<T> multiply(const pod::Matrix2t<T>& mat, const pod::Vector2t<T>& v );
|
||||||
template<typename T=NUM> pod::Vector3t<T> multiply(const pod::Matrix3t<T>& mat, const pod::Vector3t<T>& v );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Vector3t<T> multiply(const pod::Matrix3t<T>& mat, const pod::Vector3t<T>& v );
|
||||||
template<typename T=NUM> pod::Vector3t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w = 1, bool = false );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Vector3t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w = 1, bool = false );
|
||||||
template<typename T=NUM> pod::Vector4t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector, bool = false );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Vector4t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector, bool = false );
|
||||||
|
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar );
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ add( const T& lhs, const T& rhs );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ add( const T& lhs, const T& rhs );
|
||||||
|
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ inverse_( T& matrix );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ inverse_( T& matrix );
|
||||||
template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const U& right );
|
template<typename T, typename U> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const U& right );
|
||||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const T& right );
|
template<typename T> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const T& right );
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ translate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ translate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ rotate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ rotate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ scale_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ scale_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
|
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> T /*UF_API*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
||||||
|
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T, T, T );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T, T, T );
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T );
|
||||||
template<typename T=NUM> pod::Matrix4t<T> FORCE_INLINE /*UF_API*/ orthographic( const pod::Vector2t<T>& lr, const pod::Vector2t<T>& bt, const pod::Vector2t<T>& nf ) {
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( const pod::Vector2t<T>& lr, const pod::Vector2t<T>& bt, const pod::Vector2t<T>& nf ) {
|
||||||
return orthographic<T>( lr.x, lr.y, bt.x, bt.y, nf.x, nf.y );
|
return orthographic<T>( lr.x, lr.y, bt.x, bt.y, nf.x, nf.y );
|
||||||
}
|
}
|
||||||
template<typename T=NUM> pod::Matrix4t<T> FORCE_INLINE /*UF_API*/ orthographic( const pod::Vector2t<T>& lr, const pod::Vector2t<T>& bt ) {
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( const pod::Vector2t<T>& lr, const pod::Vector2t<T>& bt ) {
|
||||||
return orthographic<T>( lr.x, lr.y, bt.x, bt.y );
|
return orthographic<T>( lr.x, lr.y, bt.x, bt.y );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T=NUM> pod::Matrix4t<T> /*UF_API*/ perspective( T, T, T, T );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ perspective( T, T, T, T );
|
||||||
template<typename T=NUM> pod::Matrix4t<T> FORCE_INLINE /*UF_API*/ perspective( T fov, T raidou, const pod::Vector2f& range ) {
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ perspective( T fov, T raidou, const pod::Vector2f& range ) {
|
||||||
return perspective( fov, raidou, range.x, range.y );
|
return perspective( fov, raidou, range.x, range.y );
|
||||||
}
|
}
|
||||||
template<typename T=NUM> pod::Matrix4t<T> FORCE_INLINE /*UF_API*/ perspective( T fov, const pod::Vector2ui& size, const pod::Vector2f& range ) {
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ perspective( T fov, const pod::Vector2ui& size, const pod::Vector2f& range ) {
|
||||||
return perspective( fov, (T) size.x / (T) size.y, range.x, range.y );
|
return perspective( fov, (T) size.x / (T) size.y, range.x, range.y );
|
||||||
}
|
}
|
||||||
// Setting
|
// Setting
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ copy( T& destination, const T& source );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ copy( T& destination, const T& source );
|
||||||
template<typename T=pod::Matrix4> T& /*UF_API*/ copy( T& destination, typename T::type_t* const source );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ copy( T& destination, typename T::type_t* const source );
|
||||||
|
|
||||||
template<typename T, size_t R, size_t C = R> uf::stl::string /*UF_API*/ toString( const pod::Matrix<T,R,C>& v );
|
template<typename T, size_t R, size_t C = R> /*FORCE_INLINE*/ uf::stl::string /*UF_API*/ toString( const pod::Matrix<T,R,C>& v );
|
||||||
template<typename T, size_t R, size_t C> ext::json::Value /*UF_API*/ encode( const pod::Matrix<T,R,C>& v, const ext::json::EncodingSettings& = {} );
|
template<typename T, size_t R, size_t C> /*FORCE_INLINE*/ ext::json::Value /*UF_API*/ encode( const pod::Matrix<T,R,C>& v, const ext::json::EncodingSettings& = {} );
|
||||||
template<typename T, size_t R, size_t C> pod::Matrix<T,R,C>& /*UF_API*/ decode( const ext::json::Value& v, pod::Matrix<T,R,C>& );
|
template<typename T, size_t R, size_t C> /*FORCE_INLINE*/ pod::Matrix<T,R,C>& /*UF_API*/ decode( const ext::json::Value& v, pod::Matrix<T,R,C>& );
|
||||||
template<typename T, size_t R, size_t C> pod::Matrix<T,R,C> /*UF_API*/ decode( const ext::json::Value& v, const pod::Matrix<T,R,C>& = uf::matrix::identity() );
|
template<typename T, size_t R, size_t C> /*FORCE_INLINE*/ pod::Matrix<T,R,C> /*UF_API*/ decode( const ext::json::Value& v, const pod::Matrix<T,R,C>& = uf::matrix::identity() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,14 +121,14 @@ namespace uf {
|
|||||||
namespace uf {
|
namespace uf {
|
||||||
namespace string {
|
namespace string {
|
||||||
template<typename T, size_t R, size_t C>
|
template<typename T, size_t R, size_t C>
|
||||||
uf::stl::string /*UF_API*/ toString( const pod::Matrix<T,R,C>& v );
|
FORCE_INLINE uf::stl::string /*UF_API*/ toString( const pod::Matrix<T,R,C>& v );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace ext {
|
namespace ext {
|
||||||
namespace json {
|
namespace json {
|
||||||
template<typename T, size_t R, size_t C = R> ext::json::Value /*UF_API*/ encode( const pod::Matrix<T,R,C>& v );
|
template<typename T, size_t R, size_t C = R> FORCE_INLINE ext::json::Value /*UF_API*/ encode( const pod::Matrix<T,R,C>& v );
|
||||||
template<typename T, size_t R, size_t C = R> pod::Matrix<T,R,C>& /*UF_API*/ decode( const ext::json::Value& v, pod::Matrix<T,R,C>& );
|
template<typename T, size_t R, size_t C = R> FORCE_INLINE pod::Matrix<T,R,C>& /*UF_API*/ decode( const ext::json::Value& v, pod::Matrix<T,R,C>& );
|
||||||
template<typename T, size_t R, size_t C = R> pod::Matrix<T,R,C> /*UF_API*/ decode( const ext::json::Value& v, const pod::Matrix<T,R,C>& = uf::matrix::identity() );
|
template<typename T, size_t R, size_t C = R> FORCE_INLINE pod::Matrix<T,R,C> /*UF_API*/ decode( const ext::json::Value& v, const pod::Matrix<T,R,C>& = uf::matrix::identity() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,45 +19,45 @@ namespace pod {
|
|||||||
|
|
||||||
namespace uf {
|
namespace uf {
|
||||||
namespace quaternion {
|
namespace quaternion {
|
||||||
template<typename T = NUM> pod::Quaternion<T> /*UF_API*/ identity();
|
template<typename T = NUM> /*FORCE_INLINE*/ pod::Quaternion<T> /*UF_API*/ identity();
|
||||||
template<typename T> T /*UF_API*/ multiply( const T& left, const T& right );
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& left, const T& right );
|
||||||
template<typename T> pod::Vector3t<T> /*UF_API*/ rotate( const pod::Quaternion<T>& left, const pod::Vector3t<T>& right );
|
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> /*UF_API*/ rotate( const pod::Quaternion<T>& left, const pod::Vector3t<T>& right );
|
||||||
template<typename T> pod::Vector4t<T> /*UF_API*/ rotate( const pod::Quaternion<T>& left, const pod::Vector4t<T>& right );
|
template<typename T> /*FORCE_INLINE*/ pod::Vector4t<T> /*UF_API*/ rotate( const pod::Quaternion<T>& left, const pod::Vector4t<T>& right );
|
||||||
template<typename T> typename T::type_t /*UF_API*/ sum( const T& vector );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ sum( const T& vector );
|
||||||
template<typename T> typename T::type_t /*UF_API*/ product( const T& vector );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ product( const T& vector );
|
||||||
|
|
||||||
|
|
||||||
template<typename T> typename T::type_t /*UF_API*/ dot( const T& left, const T& right );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ dot( const T& left, const T& right );
|
||||||
template<typename T> pod::Angle /*UF_API*/ angle( const T& a, const T& b );
|
template<typename T> /*FORCE_INLINE*/ pod::Angle /*UF_API*/ angle( const T& a, const T& b );
|
||||||
|
|
||||||
template<typename T> T /*UF_API*/ lerp( const T& from, const T& to, typename T::type_t delta );
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ lerp( const T& from, const T& to, typename T::type_t delta );
|
||||||
template<typename T> T /*UF_API*/ slerp( const T& from, const T& to, typename T::type_t delta );
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ slerp( const T& from, const T& to, typename T::type_t delta );
|
||||||
|
|
||||||
template<typename T> typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b );
|
||||||
template<typename T> typename T::type_t /*UF_API*/ distance( const T& a, const T& b );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distance( const T& a, const T& b );
|
||||||
template<typename T> typename T::type_t /*UF_API*/ magnitude( const T& vector );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ magnitude( const T& vector );
|
||||||
template<typename T> typename T::type_t /*UF_API*/ norm( const T& vector );
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ norm( const T& vector );
|
||||||
template<typename T> T /*UF_API*/ normalize( const T& vector );
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ normalize( const T& vector );
|
||||||
|
|
||||||
template<typename T> pod::Matrix4t<T> matrix( const pod::Quaternion<T>& quaternion );
|
template<typename T> /*FORCE_INLINE*/ pod::Matrix4t<T> matrix( const pod::Quaternion<T>& quaternion );
|
||||||
template<typename T> pod::Quaternion<T> axisAngle( const pod::Vector3t<T>& axis, T angle );
|
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> axisAngle( const pod::Vector3t<T>& axis, T angle );
|
||||||
template<typename T> pod::Quaternion<T> unitVectors( const pod::Vector3t<T>& u, const pod::Vector3t<T>& v );
|
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> unitVectors( const pod::Vector3t<T>& u, const pod::Vector3t<T>& v );
|
||||||
template<typename T> pod::Quaternion<T> lookAt( const pod::Vector3t<T>& source, const pod::Vector3t<T>& destination );
|
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> lookAt( const pod::Vector3t<T>& source, const pod::Vector3t<T>& destination );
|
||||||
|
|
||||||
template<typename T> T conjugate( const T& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T conjugate( const T& quaternion );
|
||||||
template<typename T> T inverse( const T& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T inverse( const T& quaternion );
|
||||||
|
|
||||||
template<typename T> T& /*UF_API*/ multiply_( T& left, const T& right );
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& left, const T& right );
|
||||||
template<typename T> T& /*UF_API*/ normalize_( T& vector );
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ normalize_( T& vector );
|
||||||
template<typename T> T& conjugate_( T& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T& conjugate_( T& quaternion );
|
||||||
template<typename T> T& inverse_( T& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T& inverse_( T& quaternion );
|
||||||
|
|
||||||
template<typename T> pod::Vector3t<T> eulerAngles( const pod::Quaternion<T>& quaternion );
|
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> eulerAngles( const pod::Quaternion<T>& quaternion );
|
||||||
template<typename T> T pitch( const pod::Quaternion<T>& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T pitch( const pod::Quaternion<T>& quaternion );
|
||||||
template<typename T> T yaw( const pod::Quaternion<T>& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T yaw( const pod::Quaternion<T>& quaternion );
|
||||||
template<typename T> T roll( const pod::Quaternion<T>& quaternion );
|
template<typename T> /*FORCE_INLINE*/ T roll( const pod::Quaternion<T>& quaternion );
|
||||||
|
|
||||||
template<typename T> pod::Quaternion<T> fromMatrix( const pod::Matrix4t<T>& matrix );
|
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> fromMatrix( const pod::Matrix4t<T>& matrix );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,88 +80,89 @@ namespace pod {
|
|||||||
// POD vector accessing/manipulation
|
// POD vector accessing/manipulation
|
||||||
namespace uf {
|
namespace uf {
|
||||||
namespace vector {
|
namespace vector {
|
||||||
template<typename T> pod::Vector1t<T> /*UF_API*/ create( T x ); // creates a 1D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector1t<T> /*UF_API*/ create( T x ); // creates a 1D vector
|
||||||
template<typename T> pod::Vector2t<T> /*UF_API*/ create( T x, T y ); // creates a 2D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector2t<T> /*UF_API*/ create( T x, T y ); // creates a 2D vector
|
||||||
template<typename T> pod::Vector3t<T> /*UF_API*/ create( T x, T y, T z ); // creates a 3D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> /*UF_API*/ create( T x, T y, T z ); // creates a 3D vector
|
||||||
template<typename T> pod::Vector4t<T> /*UF_API*/ create( T x, T y, T z, T w ); // creates a 4D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector4t<T> /*UF_API*/ create( T x, T y, T z, T w ); // creates a 4D vector
|
||||||
template<typename T, size_t N> pod::Vector<T, N> /*UF_API*/ copy( const pod::Vector<T, N>& = {}); // creates a copy of a vector (for whatever reason)
|
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ copy( const pod::Vector<T, N>& = {}); // creates a copy of a vector (for whatever reason)
|
||||||
template<typename T, size_t N, typename U> pod::Vector<T, N> /*UF_API*/ cast( const U& from ); // casts one vector of one type to another (of the same size)
|
template<typename T, size_t N, typename U> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ cast( const U& from ); // casts one vector of one type to another (of the same size)
|
||||||
// Equality checking
|
// Equality checking
|
||||||
template<typename T> bool /*UF_API*/ equals( const T& left, const T& right ); // equality check between two vectors (==)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ equals( const T& left, const T& right ); // equality check between two vectors (==)
|
||||||
template<typename T> bool /*UF_API*/ notEquals( const T& left, const T& right ); // equality check between two vectors (==)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ notEquals( const T& left, const T& right ); // equality check between two vectors (==)
|
||||||
template<typename T> bool /*UF_API*/ less( const T& left, const T& right ); // equality check between two vectors (<)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ less( const T& left, const T& right ); // equality check between two vectors (<)
|
||||||
template<typename T> bool /*UF_API*/ lessEquals( const T& left, const T& right ); // equality check between two vectors (<=)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ lessEquals( const T& left, const T& right ); // equality check between two vectors (<=)
|
||||||
template<typename T> bool /*UF_API*/ greater( const T& left, const T& right ); // equality check between two vectors (>)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ greater( const T& left, const T& right ); // equality check between two vectors (>)
|
||||||
template<typename T> bool /*UF_API*/ greaterEquals( const T& left, const T& right ); // equality check between two vectors (>=)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ greaterEquals( const T& left, const T& right ); // equality check between two vectors (>=)
|
||||||
|
|
||||||
template<typename T> bool /*UF_API*/ isValid( const T& v ); // checks if all components are valid (non NaN, inf, etc.)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ isValid( const T& v ); // checks if all components are valid (non NaN, inf, etc.)
|
||||||
// Basic arithmetic
|
// Basic arithmetic
|
||||||
template<typename T> T /*UF_API*/ add( const T& left, const T& right ); // adds two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ add( const T& left, const T& right ); // adds two vectors of same type and size together
|
||||||
template<typename T> T /*UF_API*/ add( const T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ add( const T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector
|
||||||
template<typename T> T /*UF_API*/ add( typename T::type_t scalar, const T& vector ); // adds a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ add( typename T::type_t scalar, const T& vector ); // adds a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T /*UF_API*/ subtract( const T& left, const T& right ); // subtracts two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ subtract( const T& left, const T& right ); // subtracts two vectors of same type and size together
|
||||||
template<typename T> T /*UF_API*/ subtract( const T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ subtract( const T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
||||||
template<typename T> T /*UF_API*/ subtract( typename T::type_t scalar, const T& vector ); // subtracts a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ subtract( typename T::type_t scalar, const T& vector ); // subtracts a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T /*UF_API*/ multiply( const T& left, const T& right ); // multiplies two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& left, const T& right ); // multiplies two vectors of same type and size together
|
||||||
template<typename T> T /*UF_API*/ multiply( const T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
||||||
template<typename T> T /*UF_API*/ multiply( typename T::type_t scalar, const T& vector ); // multiplies a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ multiply( typename T::type_t scalar, const T& vector ); // multiplies a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T /*UF_API*/ divide( const T& left, const T& right ); // divides two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ divide( const T& left, const T& right ); // divides two vectors of same type and size together
|
||||||
template<typename T> T /*UF_API*/ divide( const T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ divide( const T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
||||||
template<typename T> T /*UF_API*/ divide( typename T::type_t scalar, const T& vector ); // divides a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ divide( typename T::type_t scalar, const T& vector ); // divides a scalar to every component of the vector (inverted)
|
||||||
|
|
||||||
template<typename T> T& /*UF_API*/ add_( T& left, const T& right ); // adds two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ add_( T& left, const T& right ); // adds two vectors of same type and size together
|
||||||
template<typename T> T& /*UF_API*/ add_( T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ add_( T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector
|
||||||
template<typename T> T& /*UF_API*/ add_( typename T::type_t scalar, T& vector ); // adds a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ add_( typename T::type_t scalar, T& vector ); // adds a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T& /*UF_API*/ subtract_( T& left, const T& right ); // subtracts two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( T& left, const T& right ); // subtracts two vectors of same type and size together
|
||||||
template<typename T> T& /*UF_API*/ subtract_( T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
||||||
template<typename T> T& /*UF_API*/ subtract_( typename T::type_t scalar, T& vector ); // subtracts a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( typename T::type_t scalar, T& vector ); // subtracts a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T& /*UF_API*/ multiply_( T& left, const T& right ); // multiplies two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& left, const T& right ); // multiplies two vectors of same type and size together
|
||||||
template<typename T> T& /*UF_API*/ multiply_( T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
||||||
template<typename T> T& /*UF_API*/ multiply_( typename T::type_t scalar, T& vector ); // multiplies a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( typename T::type_t scalar, T& vector ); // multiplies a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T& /*UF_API*/ divide_( T& left, const T& right ); // divides two vectors of same type and size together
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ divide_( T& left, const T& right ); // divides two vectors of same type and size together
|
||||||
template<typename T> T& /*UF_API*/ divide_( T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ divide_( T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
||||||
template<typename T> T& /*UF_API*/ divide_( typename T::type_t scalar, T& vector ); // divides a scalar to every component of the vector (inverted)
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ divide_( typename T::type_t scalar, T& vector ); // divides a scalar to every component of the vector (inverted)
|
||||||
template<typename T> T& /*UF_API*/ negate_( T& vector ); // flip sign of all components
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ negate_( T& vector ); // flip sign of all components
|
||||||
template<typename T> T& /*UF_API*/ normalize_( T& vector ); // normalizes a vector
|
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ normalize_( T& vector ); // normalizes a vector
|
||||||
|
|
||||||
template<typename T> typename T::type_t /*UF_API*/ sum( const T& vector ); // compute the sum of all components
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ sum( const T& vector ); // compute the sum of all components
|
||||||
template<typename T> typename T::type_t /*UF_API*/ product( const T& vector ); // compute the product of all components
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ product( const T& vector ); // compute the product of all components
|
||||||
template<typename T> T /*UF_API*/ negate( const T& vector ); // flip sign of all components
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ negate( const T& vector ); // flip sign of all components
|
||||||
template<typename T> T /*UF_API*/ abs( const T& vector ); // gets the absolute value of a vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ abs( const T& vector ); // gets the absolute value of a vector
|
||||||
template<typename T> T /*UF_API*/ min( const T& left, const T& right ); // returns the minimum of each component between two vectors
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ min( const T& left, const T& right ); // returns the minimum of each component between two vectors
|
||||||
template<typename T> T /*UF_API*/ max( const T& left, const T& right ); // returns the maximum of each component between two vectors
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ max( const T& left, const T& right ); // returns the maximum of each component between two vectors
|
||||||
template<typename T> T /*UF_API*/ clamp( const T& vector, const T& min, const T& max ); // clamps a vector between two bounds
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ clamp( const T& vector, const T& min, const T& max ); // clamps a vector between two bounds
|
||||||
template<typename T> T /*UF_API*/ ceil( const T& vector ); // rounds each component of the the vector up
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ ceil( const T& vector ); // rounds each component of the the vector up
|
||||||
template<typename T> T /*UF_API*/ floor( const T& vector ); // rounds each component of the vector down
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ floor( const T& vector ); // rounds each component of the vector down
|
||||||
template<typename T> T /*UF_API*/ round( const T& vector ); // rounds each component of the vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ round( const T& vector ); // rounds each component of the vector
|
||||||
// Complex arithmetic
|
// Complex arithmetic
|
||||||
template<typename T> typename T::type_t /*UF_API*/ dot( const T& left, const T& right ); // compute the dot product between two vectors
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ dot( const T& left, const T& right ); // compute the dot product between two vectors
|
||||||
template<typename T> float /*UF_API*/ angle( const T& a, const T& b ); // compute the angle between two vectors
|
template<typename T> /*FORCE_INLINE*/ float /*UF_API*/ angle( const T& a, const T& b ); // compute the angle between two vectors
|
||||||
template<typename T> float /*UF_API*/ signedAngle( const T& a, const T& b, const T& axis ); // compute the signed angle between two vectors
|
template<typename T> /*FORCE_INLINE*/ float /*UF_API*/ signedAngle( const T& a, const T& b, const T& axis ); // compute the signed angle between two vectors
|
||||||
template<typename T> T /*UF_API*/ cross( const T& a, const T& b ); // compute the cross product between two vectors
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ cross( const T& a, const T& b ); // compute the cross product between two vectors
|
||||||
|
|
||||||
template<typename T> T /*UF_API*/ lerp( const T& from, const T& to, double, bool = true ); // linearly interpolate between two vectors
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ lerp( const T& from, const T& to, double, bool = true ); // linearly interpolate between two vectors
|
||||||
template<typename T> T /*UF_API*/ lerp( const T& from, const T& to, const T&, bool = true ); // linearly interpolate between two vectors, component-wise
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ lerp( const T& from, const T& to, const T&, bool = true ); // linearly interpolate between two vectors, component-wise
|
||||||
|
|
||||||
template<typename T> T /*UF_API*/ slerp( const T& from, const T& to, double, bool = false ); // spherically interpolate between two vectors
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ slerp( const T& from, const T& to, double, bool = false ); // spherically interpolate between two vectors
|
||||||
template<typename T> T /*UF_API*/ mix( const T& from, const T& to, double, bool = false );
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ mix( const T& from, const T& to, double, bool = false );
|
||||||
|
|
||||||
template<typename T> typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b ); // compute the distance between two vectors (doesn't sqrt)
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b ); // compute the distance between two vectors (doesn't sqrt)
|
||||||
template<typename T> typename T::type_t /*UF_API*/ distance( const T& a, const T& b ); // compute the distance between two vectors
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distance( const T& a, const T& b ); // compute the distance between two vectors
|
||||||
template<typename T> typename T::type_t /*UF_API*/ magnitude( const T& vector ); // gets the magnitude of the vector
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ magnitude( const T& vector ); // gets the magnitude of the vector
|
||||||
template<typename T> typename T::type_t /*UF_API*/ norm( const T& vector ); // compute the norm (length) of the vector
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ norm( const T& vector ); // compute the norm (length) of the vector
|
||||||
template<typename T> T /*UF_API*/ normalize( const T& vector ); // normalizes a vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ normalize( const T& vector ); // normalizes a vector
|
||||||
template<typename T> T /*UF_API*/ clampMagnitude( const T& vector ); // clamps the magnitude of a vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ clampMagnitude( const T& vector ); // clamps the magnitude of a vector
|
||||||
template<typename T> void /*UF_API*/ orthonormalize( T& x, T& y ); // orthonormalizes a vector against another vector
|
template<typename T> /*FORCE_INLINE*/ void /*UF_API*/ orthonormalize( T& x, T& y ); // orthonormalizes a vector against another vector
|
||||||
template<typename T> T /*UF_API*/ orthonormalize( const T& x, const T& y ); // orthonormalizes a vector against another vector
|
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ orthonormalize( const T& x, const T& y ); // orthonormalizes a vector against another vector
|
||||||
|
|
||||||
template<typename T> uf::stl::string /*UF_API*/ toString( const T& vector ); // parses a vector as a string
|
template<typename T> /*FORCE_INLINE*/ size_t /*UF_API*/ hash( const T& vector ); // hashes a vector
|
||||||
template<typename T, size_t N> ext::json::Value encode( const pod::Vector<T,N>& v, const ext::json::EncodingSettings& = {} ); // parses a vector into a JSON value
|
template<typename T> /*FORCE_INLINE*/ uf::stl::string /*UF_API*/ toString( const T& vector ); // parses a vector as a string
|
||||||
|
template<typename T, size_t N> /*FORCE_INLINE*/ ext::json::Value encode( const pod::Vector<T,N>& v, const ext::json::EncodingSettings& = {} ); // parses a vector into a JSON value
|
||||||
|
|
||||||
template<typename T, size_t N> pod::Vector<T,N>& decode( const ext::json::Value& v, pod::Vector<T,N>& ); // parses a JSON value into a vector
|
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T,N>& decode( const ext::json::Value& v, pod::Vector<T,N>& ); // parses a JSON value into a vector
|
||||||
template<typename T, size_t N> pod::Vector<T,N> decode( const ext::json::Value& v, const pod::Vector<T,N>& = {} ); // parses a JSON value into a vector
|
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T,N> decode( const ext::json::Value& v, const pod::Vector<T,N>& = {} ); // parses a JSON value into a vector
|
||||||
|
|
||||||
template<typename T> typename T::type_t /*UF_API*/ mips( const T& size ); // calculate amount of mips to use given a size
|
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ mips( const T& size ); // calculate amount of mips to use given a size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +198,12 @@ namespace uf {
|
|||||||
FORCE_INLINE explicit operator bool() const { return uf::vector::notEquals(*this, Vector<T,N>{}); } \
|
FORCE_INLINE explicit operator bool() const { return uf::vector::notEquals(*this, Vector<T,N>{}); } \
|
||||||
template<typename U, size_t M> FORCE_INLINE operator Vector<U,M>() const { return uf::vector::cast<U,M>(*this); }
|
template<typename U, size_t M> FORCE_INLINE operator Vector<U,M>() const { return uf::vector::cast<U,M>(*this); }
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_EXT(T, N) \
|
||||||
|
template<typename T> FORCE_INLINE pod::Vector<T,N> operator+( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::add(scalar, v); }\
|
||||||
|
template<typename T> FORCE_INLINE pod::Vector<T,N> operator-( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::subtract(scalar, v); }\
|
||||||
|
template<typename T> FORCE_INLINE pod::Vector<T,N> operator*( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::multiply(scalar, v); }\
|
||||||
|
template<typename T> FORCE_INLINE pod::Vector<T,N> operator/( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::divide(scalar, v); }\
|
||||||
|
|
||||||
namespace pod {
|
namespace pod {
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
struct Vector {
|
struct Vector {
|
||||||
@ -238,30 +245,35 @@ namespace pod {
|
|||||||
|
|
||||||
// external functions
|
// external functions
|
||||||
|
|
||||||
//#include <uf/utils/string/ext.h>
|
// scalar operator vector
|
||||||
#include <sstream>
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N> operator+( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::add(scalar, v); }
|
||||||
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N> operator-( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::subtract(scalar, v); }
|
||||||
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N> operator*( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::multiply(scalar, v); }
|
||||||
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N> operator/( T scalar, const pod::Vector<T,N>& v ) { return uf::vector::divide(scalar, v); }
|
||||||
|
|
||||||
|
DEFINE_VECTOR_EXT(T, 2);
|
||||||
|
DEFINE_VECTOR_EXT(T, 3);
|
||||||
|
DEFINE_VECTOR_EXT(T, 4);
|
||||||
|
|
||||||
|
// stringify
|
||||||
namespace uf {
|
namespace uf {
|
||||||
namespace string {
|
namespace string {
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N> FORCE_INLINE uf::stl::string toString( const pod::Vector<T,N>& v );
|
||||||
uf::stl::string toString( const pod::Vector<T,N>& v );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// jsonify
|
||||||
namespace ext {
|
namespace ext {
|
||||||
namespace json {
|
namespace json {
|
||||||
template<typename T, size_t N> ext::json::Value encode( const pod::Vector<T,N>& v );
|
template<typename T, size_t N> FORCE_INLINE ext::json::Value encode( const pod::Vector<T,N>& v );
|
||||||
template<typename T, size_t N> pod::Vector<T,N>& decode( const ext::json::Value&, pod::Vector<T,N>& );
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N>& decode( const ext::json::Value&, pod::Vector<T,N>& );
|
||||||
template<typename T, size_t N> pod::Vector<T,N> decode( const ext::json::Value&, const pod::Vector<T,N>& = {} );
|
template<typename T, size_t N> FORCE_INLINE pod::Vector<T,N> decode( const ext::json::Value&, const pod::Vector<T,N>& = {} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// hash
|
||||||
namespace std {
|
namespace std {
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
struct hash<pod::Vector<T,N>> {
|
struct hash<pod::Vector<T,N>> {
|
||||||
size_t operator()(const pod::Vector<T,N>& v) const {
|
FORCE_INLINE size_t operator()(const pod::Vector<T,N>& v) const;
|
||||||
size_t hash = 0;
|
|
||||||
for ( size_t i = 0; i < N; ++i ) hash ^= v[i];
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,9 +276,9 @@ T uf::vector::divide( const T& vector, typename T::type_t scalar ) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
T res;
|
T res;
|
||||||
scalar = static_cast<typename T::type_t>(1) / scalar;
|
float recip = static_cast<typename T::type_t>(1) / scalar;
|
||||||
FOR_EACH(T::size, {
|
FOR_EACH(T::size, {
|
||||||
res[i] = vector[i] * scalar;
|
res[i] = vector[i] * recip;
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -298,9 +298,9 @@ T uf::vector::divide( typename T::type_t scalar, const T& vector ) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
T res;
|
T res;
|
||||||
scalar = static_cast<T>(1) / scalar;
|
float recip = static_cast<typename T::type_t>(1) / scalar;
|
||||||
FOR_EACH(T::size, {
|
FOR_EACH(T::size, {
|
||||||
res[i] = scalar / vector[i];
|
res[i] = vector[i] * recip;
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -740,6 +740,15 @@ typename T::type_t uf::vector::mips( const T& size ) {
|
|||||||
return static_cast<uint32_t>(std::floor(std::log2(max))) + 1;
|
return static_cast<uint32_t>(std::floor(std::log2(max))) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
size_t uf::vector::hash( const T& v ) {
|
||||||
|
size_t hash = 0;
|
||||||
|
FOR_EACH(T::size, {
|
||||||
|
hash ^= v[i];
|
||||||
|
});
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
uf::stl::string uf::vector::toString( const T& v ) {
|
uf::stl::string uf::vector::toString( const T& v ) {
|
||||||
uf::stl::stringstream ss;
|
uf::stl::stringstream ss;
|
||||||
|
@ -18,3 +18,8 @@ template<typename T, size_t N>
|
|||||||
pod::Vector<T,N> /*UF_API*/ ext::json::decode( const ext::json::Value& json, const pod::Vector<T,N>& v ) {
|
pod::Vector<T,N> /*UF_API*/ ext::json::decode( const ext::json::Value& json, const pod::Vector<T,N>& v ) {
|
||||||
return uf::vector::decode<T,N>(json, v);
|
return uf::vector::decode<T,N>(json, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
size_t std::hash<pod::Vector<T,N>>::operator()( const pod::Vector<T,N>& v ) const {
|
||||||
|
return uf::vector::hash( v );
|
||||||
|
}
|
@ -191,15 +191,10 @@ namespace uf {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
struct Bounds {
|
|
||||||
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
|
||||||
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
|
||||||
} bounds;
|
|
||||||
*/
|
|
||||||
uf::stl::vector<buffer_t> buffers;
|
uf::stl::vector<buffer_t> buffers;
|
||||||
|
|
||||||
// crunge, but it's better this way
|
// crunge, but it's better this way for streaming in mesh data
|
||||||
uf::stl::vector<uf::stl::string> buffer_paths;
|
uf::stl::vector<uf::stl::string> buffer_paths;
|
||||||
protected:
|
protected:
|
||||||
void _destroy( uf::Mesh::Input& input );
|
void _destroy( uf::Mesh::Input& input );
|
||||||
|
@ -1,24 +1,74 @@
|
|||||||
namespace {
|
namespace {
|
||||||
inline bool aabbOverlap( const pod::AABB& a, const pod::AABB& b, float eps ) {
|
FORCE_INLINE bool aabbOverlap( const pod::AABB& a, const pod::AABB& b, float eps ) {
|
||||||
|
#if UF_USE_SIMD
|
||||||
|
return uf::simd::all( uf::simd::lessEquals( a.min, b.max ) ) && uf::simd::all( uf::simd::greaterEquals( a.max, b.min ) );
|
||||||
|
#else
|
||||||
return ( a.min - eps ) <= ( b.max + eps ) && ( a.max + eps ) >= ( b.min - eps );
|
return ( a.min - eps ) <= ( b.max + eps ) && ( a.max + eps ) >= ( b.min - eps );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float aabbSurfaceArea(const pod::AABB& aabb) {
|
FORCE_INLINE float aabbSurfaceArea(const pod::AABB& aabb) {
|
||||||
auto d = uf::vector::max( ( aabb.max - aabb.min ), pod::Vector3f{} );
|
auto d = uf::vector::max( ( aabb.max - aabb.min ), pod::Vector3f{} );
|
||||||
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::AABB computeSegmentAABB( const pod::Vector3f& p1, const pod::Vector3f p2, float r ) {
|
FORCE_INLINE pod::AABB computeSegmentAABB( const pod::Vector3f& p1, const pod::Vector3f p2, float r ) {
|
||||||
return {
|
return {
|
||||||
uf::vector::min( p1, p2 ) - r,
|
uf::vector::min( p1, p2 ) - r,
|
||||||
uf::vector::max( p1, p2 ) + r,
|
uf::vector::max( p1, p2 ) + r,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::Vector3f closestPointOnAABB(const pod::Vector3f& p, const pod::AABB& box) {
|
FORCE_INLINE pod::Vector3f closestPointOnAABB(const pod::Vector3f& p, const pod::AABB& box) {
|
||||||
return uf::vector::clamp( p, box.min, box.max );
|
return uf::vector::clamp( p, box.min, box.max );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE pod::AABB computeTriangleAABB( const pod::Triangle& tri ) {
|
||||||
|
return {
|
||||||
|
uf::vector::min( uf::vector::min( tri.points[0], tri.points[1] ), tri.points[2] ),
|
||||||
|
uf::vector::max( uf::vector::max( tri.points[0], tri.points[1] ), tri.points[2] ),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE pod::AABB mergeAabb( const pod::AABB& a, const pod::AABB& b ) {
|
||||||
|
return {
|
||||||
|
uf::vector::min( a.min, b.min ),
|
||||||
|
uf::vector::max( a.max, b.max ),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE pod::Vector3f aabbCenter( const pod::AABB& aabb ) {
|
||||||
|
return ( aabb.max + aabb.min ) * 0.5f;
|
||||||
|
}
|
||||||
|
FORCE_INLINE pod::Vector3f aabbExtent( const pod::AABB& aabb ) {
|
||||||
|
return ( aabb.max - aabb.min ) * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::AABB transformAabbToWorld( const pod::AABB& localBox, const pod::Transform<>& transform ) {
|
||||||
|
const auto& q = transform.orientation;
|
||||||
|
const auto& p = transform.position;
|
||||||
|
|
||||||
|
pod::Vector3f center = (localBox.min + localBox.max) * 0.5f;
|
||||||
|
pod::Vector3f extents = (localBox.max - localBox.min) * 0.5f;
|
||||||
|
|
||||||
|
pod::Vector3f axisX = uf::quaternion::rotate(q, pod::Vector3f{1,0,0});
|
||||||
|
pod::Vector3f axisY = uf::quaternion::rotate(q, pod::Vector3f{0,1,0});
|
||||||
|
pod::Vector3f axisZ = uf::quaternion::rotate(q, pod::Vector3f{0,0,1});
|
||||||
|
|
||||||
|
pod::Vector3f worldCenter = uf::quaternion::rotate(q, center) + p;
|
||||||
|
|
||||||
|
pod::Vector3f worldExtents = {
|
||||||
|
fabs(axisX.x) * extents.x + fabs(axisY.x) * extents.y + fabs(axisZ.x) * extents.z,
|
||||||
|
fabs(axisX.y) * extents.x + fabs(axisY.y) * extents.y + fabs(axisZ.y) * extents.z,
|
||||||
|
fabs(axisX.z) * extents.x + fabs(axisY.z) * extents.y + fabs(axisZ.z) * extents.z
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
worldCenter - worldExtents,
|
||||||
|
worldCenter + worldExtents
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<pod::Vector3f, pod::Vector3f> getCapsuleSegment( const pod::PhysicsBody& body ) {
|
std::pair<pod::Vector3f, pod::Vector3f> getCapsuleSegment( const pod::PhysicsBody& body ) {
|
||||||
const auto transform = ::getTransform( body );
|
const auto transform = ::getTransform( body );
|
||||||
const auto& capsule = body.collider.capsule;
|
const auto& capsule = body.collider.capsule;
|
||||||
@ -34,10 +84,13 @@ namespace {
|
|||||||
const auto transform = ::getTransform( body );
|
const auto transform = ::getTransform( body );
|
||||||
switch ( body.collider.type ) {
|
switch ( body.collider.type ) {
|
||||||
case pod::ShapeType::AABB: {
|
case pod::ShapeType::AABB: {
|
||||||
|
/*
|
||||||
return {
|
return {
|
||||||
transform.position + body.collider.aabb.min,
|
transform.position + body.collider.aabb.min,
|
||||||
transform.position + body.collider.aabb.max,
|
transform.position + body.collider.aabb.max,
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
return ::transformAabbToWorld( body.collider.aabb, *body.transform );
|
||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::SPHERE: {
|
case pod::ShapeType::SPHERE: {
|
||||||
return {
|
return {
|
||||||
@ -63,20 +116,13 @@ namespace {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::AABB computeTriangleAABB( const pod::Triangle& tri ) {
|
|
||||||
return {
|
|
||||||
uf::vector::min( uf::vector::min( tri.points[0], tri.points[1] ), tri.points[2] ),
|
|
||||||
uf::vector::max( uf::vector::max( tri.points[0], tri.points[1] ), tri.points[2] ),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
float triAabbDistanceSq( const pod::Triangle& tri, const pod::AABB& box ) {
|
float triAabbDistanceSq( const pod::Triangle& tri, const pod::AABB& box ) {
|
||||||
float minDistSq = FLT_MAX;
|
float minDistSq = FLT_MAX;
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
FOR_EACH(3, {
|
||||||
auto cp = ::closestPointOnAABB( tri.points[i], box );
|
auto cp = ::closestPointOnAABB( tri.points[i], box );
|
||||||
auto d = tri.points[i] - cp;
|
auto d = tri.points[i] - cp;
|
||||||
minDistSq = std::min( minDistSq, uf::vector::dot( d, d ) );
|
minDistSq = std::min( minDistSq, uf::vector::dot( d, d ) );
|
||||||
}
|
});
|
||||||
return minDistSq;
|
return minDistSq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,11 +170,11 @@ namespace {
|
|||||||
if ( !axisTest( {-f2.y, f2.x, 0} ) ) return false;
|
if ( !axisTest( {-f2.y, f2.x, 0} ) ) return false;
|
||||||
|
|
||||||
// test AABB face axes
|
// test AABB face axes
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
FOR_EACH(3, {
|
||||||
float minVal = std::min({v0[i], v1[i], v2[i]});
|
float minVal = std::min({v0[i], v1[i], v2[i]});
|
||||||
float maxVal = std::max({v0[i], v1[i], v2[i]});
|
float maxVal = std::max({v0[i], v1[i], v2[i]});
|
||||||
if ( minVal > e[i] || maxVal < -e[i] ) return false;
|
if ( minVal > e[i] || maxVal < -e[i] ) return false;
|
||||||
}
|
});
|
||||||
|
|
||||||
// test triangle normal axis
|
// test triangle normal axis
|
||||||
auto n = uf::vector::cross( f0, f1 );
|
auto n = uf::vector::cross( f0, f1 );
|
||||||
@ -139,13 +185,6 @@ namespace {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::AABB mergeAabb( const pod::AABB& a, const pod::AABB& b ) {
|
|
||||||
return {
|
|
||||||
uf::vector::min( a.min, b.min ),
|
|
||||||
uf::vector::max( a.max, b.max ),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pod::AABB transformAabbToLocal( const pod::AABB& box, const pod::Transform<>& transform ) {
|
pod::AABB transformAabbToLocal( const pod::AABB& box, const pod::Transform<>& transform ) {
|
||||||
auto inv = uf::transform::inverse( transform );
|
auto inv = uf::transform::inverse( transform );
|
||||||
|
|
||||||
@ -166,21 +205,14 @@ namespace {
|
|||||||
{ -FLT_MAX, -FLT_MAX, -FLT_MAX },
|
{ -FLT_MAX, -FLT_MAX, -FLT_MAX },
|
||||||
};
|
};
|
||||||
|
|
||||||
for ( auto i = 0; i < 8; ++i ) {
|
FOR_EACH(8, {
|
||||||
auto local = uf::transform::apply( inv, corners[i] );
|
auto local = uf::transform::apply( inv, corners[i] );
|
||||||
out.min = uf::vector::min( out.min, local );
|
out.min = uf::vector::min( out.min, local );
|
||||||
out.max = uf::vector::max( out.max, local );
|
out.max = uf::vector::max( out.max, local );
|
||||||
}
|
});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::Vector3f aabbCenter( const pod::AABB& aabb ) {
|
|
||||||
return ( aabb.max + aabb.min ) * 0.5f;
|
|
||||||
}
|
|
||||||
pod::Vector3f aabbExtent( const pod::AABB& aabb ) {
|
|
||||||
return ( aabb.max - aabb.min ) * 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES(AABB, AABB);
|
ASSERT_COLLIDER_TYPES(AABB, AABB);
|
||||||
|
|
||||||
@ -195,12 +227,12 @@ namespace {
|
|||||||
// determine collision axis = smallest overlap
|
// determine collision axis = smallest overlap
|
||||||
auto axis = -1;
|
auto axis = -1;
|
||||||
float minOverlap = FLT_MAX;
|
float minOverlap = FLT_MAX;
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
FOR_EACH(3, {
|
||||||
if ( overlaps[i] < minOverlap ) {
|
if ( overlaps[i] < minOverlap ) {
|
||||||
minOverlap = overlaps[i];
|
minOverlap = overlaps[i];
|
||||||
axis = i;
|
axis = i;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
pod::Vector3f delta = ::getPosition( b ) - ::getPosition( a );
|
pod::Vector3f delta = ::getPosition( b ) - ::getPosition( a );
|
||||||
pod::Vector3f normal{0,0,0};
|
pod::Vector3f normal{0,0,0};
|
||||||
@ -211,13 +243,13 @@ namespace {
|
|||||||
auto Max = uf::vector::min( A.max, B.max );
|
auto Max = uf::vector::min( A.max, B.max );
|
||||||
|
|
||||||
// on chosen axis, clamp to overlapped rectangle -> 4 potential points
|
// on chosen axis, clamp to overlapped rectangle -> 4 potential points
|
||||||
if (axis == 0) { // x-axis separation, so face-on overlap in YZ plane
|
if ( axis == 0 ) { // x-axis separation, so face-on overlap in YZ plane
|
||||||
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Min.y, Min.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Min.y, Min.z }, normal, minOverlap });
|
||||||
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Min.y, Max.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Min.y, Max.z }, normal, minOverlap });
|
||||||
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Max.y, Min.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Max.y, Min.z }, normal, minOverlap });
|
||||||
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Max.y, Max.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { (normal.x > 0 ? A.max.x : A.min.x), Max.y, Max.z }, normal, minOverlap });
|
||||||
}
|
}
|
||||||
else if (axis == 1) { // y-axis separation, overlap in XZ plane
|
else if ( axis == 1 ) { // y-axis separation, overlap in XZ plane
|
||||||
manifold.points.emplace_back(pod::Contact{ { Min.x, (normal.y > 0 ? A.max.y : A.min.y), Min.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { Min.x, (normal.y > 0 ? A.max.y : A.min.y), Min.z }, normal, minOverlap });
|
||||||
manifold.points.emplace_back(pod::Contact{ { Min.x, (normal.y > 0 ? A.max.y : A.min.y), Max.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { Min.x, (normal.y > 0 ? A.max.y : A.min.y), Max.z }, normal, minOverlap });
|
||||||
manifold.points.emplace_back(pod::Contact{ { Max.x, (normal.y > 0 ? A.max.y : A.min.y), Min.z }, normal, minOverlap });
|
manifold.points.emplace_back(pod::Contact{ { Max.x, (normal.y > 0 ? A.max.y : A.min.y), Min.z }, normal, minOverlap });
|
||||||
@ -235,30 +267,18 @@ namespace {
|
|||||||
|
|
||||||
bool aabbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool aabbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( AABB, SPHERE );
|
ASSERT_COLLIDER_TYPES( AABB, SPHERE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, sphereAabb );
|
||||||
if ( !::sphereAabb( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool aabbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool aabbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( AABB, PLANE );
|
ASSERT_COLLIDER_TYPES( AABB, PLANE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, planeAabb );
|
||||||
if ( !::planeAabb( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool aabbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool aabbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( AABB, CAPSULE );
|
ASSERT_COLLIDER_TYPES( AABB, CAPSULE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, capsuleAabb );
|
||||||
if ( !::capsuleAabb( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool aabbMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool aabbMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( AABB, MESH );
|
ASSERT_COLLIDER_TYPES( AABB, MESH );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, meshAabb );
|
||||||
if ( !::meshAabb( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,13 @@
|
|||||||
|
namespace {
|
||||||
|
int32_t flattenBVH( pod::BVH& bvh, int32_t nodeID );
|
||||||
|
|
||||||
|
void queryFlatBVH( const pod::BVH&, const pod::AABB& bounds, uf::stl::vector<int32_t>& out );
|
||||||
|
void queryFlatBVH( const pod::BVH&, const pod::Ray& ray, uf::stl::vector<int32_t>& out, float maxDist = FLT_MAX );
|
||||||
|
|
||||||
|
void queryFlatOverlaps( const pod::BVH& bvh, pod::BVH::pairs_t& outPairs );
|
||||||
|
void queryFlatOverlaps( const pod::BVH& bvhA, const pod::BVH& bvhB, pod::BVH::pairs_t& outPairs );
|
||||||
|
}
|
||||||
|
|
||||||
// BVH
|
// BVH
|
||||||
namespace {
|
namespace {
|
||||||
int32_t buildBVHNode( pod::BVH& bvh, const uf::stl::vector<pod::AABB>& bounds, int32_t start, int32_t end, int32_t capacity = 2 ) {
|
int32_t buildBVHNode( pod::BVH& bvh, const uf::stl::vector<pod::AABB>& bounds, int32_t start, int32_t end, int32_t capacity = 2 ) {
|
||||||
@ -212,7 +222,7 @@ namespace {
|
|||||||
|
|
||||||
auto tris = view.index.count / 3;
|
auto tris = view.index.count / 3;
|
||||||
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
||||||
auto tri = ::fetchTriangle( positions.data(view.vertex.first), positions.stride(), indices.data(view.index.first), mesh.index.size, triIndexID );
|
auto tri = ::fetchTriangle( view, indices, positions, triIndexID );
|
||||||
auto aabb = ::computeTriangleAABB( tri );
|
auto aabb = ::computeTriangleAABB( tri );
|
||||||
auto triID = triIndexID + (view.index.first / 3);
|
auto triID = triIndexID + (view.index.first / 3);
|
||||||
|
|
||||||
@ -363,7 +373,7 @@ namespace {
|
|||||||
|
|
||||||
auto tris = view.index.count / 3;
|
auto tris = view.index.count / 3;
|
||||||
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
||||||
auto tri = ::fetchTriangle( positions.data(view.vertex.first), positions.stride(), indices.data(view.index.first), mesh.index.size, triIndexID );
|
auto tri = ::fetchTriangle( view, indices, positions, triIndexID );
|
||||||
auto aabb = ::computeTriangleAABB( tri );
|
auto aabb = ::computeTriangleAABB( tri );
|
||||||
bounds.emplace_back(aabb);
|
bounds.emplace_back(aabb);
|
||||||
}
|
}
|
||||||
|
@ -104,9 +104,6 @@ namespace {
|
|||||||
}
|
}
|
||||||
bool capsuleMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool capsuleMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( CAPSULE, MESH );
|
ASSERT_COLLIDER_TYPES( CAPSULE, MESH );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, meshCapsule );
|
||||||
if ( !::meshCapsule( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,9 @@
|
|||||||
|
#define REVERSE_COLLIDER( a, b, fun )\
|
||||||
|
auto start = manifold.points.size();\
|
||||||
|
if ( !::fun( b, a, manifold, eps ) ) return false;\
|
||||||
|
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;\
|
||||||
|
return true;
|
||||||
|
|
||||||
// forward declare
|
// forward declare
|
||||||
namespace {
|
namespace {
|
||||||
bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) );
|
bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) );
|
||||||
@ -37,31 +43,16 @@ namespace {
|
|||||||
bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) );
|
bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) );
|
||||||
|
|
||||||
// ugh
|
// ugh
|
||||||
|
FORCE_INLINE bool aabbOverlap( const pod::AABB& a, const pod::AABB& b, float eps = EPS(1.0e-6f) );
|
||||||
|
|
||||||
pod::Vector3f aabbCenter( const pod::AABB& aabb );
|
pod::Vector3f aabbCenter( const pod::AABB& aabb );
|
||||||
bool aabbOverlap( const pod::AABB& a, const pod::AABB& b, float eps = EPS(1.0e-6f) );
|
|
||||||
pod::AABB computeTriangleAABB( const pod::Triangle& tri );
|
|
||||||
|
|
||||||
void solveContacts( uf::stl::vector<pod::Manifold>& manifolds, float dt );
|
|
||||||
|
|
||||||
int32_t flattenBVH( pod::BVH& bvh, int32_t nodeID );
|
|
||||||
|
|
||||||
void traverseNodePair( const pod::BVH& bvh, int32_t leftID, int32_t rightID, pod::BVH::pairs_t& pairs );
|
|
||||||
void traverseNodePair( const pod::BVH& a, int32_t nodeA, const pod::BVH& b, int32_t nodeB, pod::BVH::pairs_t& out );
|
|
||||||
|
|
||||||
void queryBVH( const pod::BVH& bvh, const pod::AABB& bounds, uf::stl::vector<int32_t>& indices );
|
void queryBVH( const pod::BVH& bvh, const pod::AABB& bounds, uf::stl::vector<int32_t>& indices );
|
||||||
void queryBVH( const pod::BVH& bvh, const pod::AABB& bounds, uf::stl::vector<int32_t>& indices, int32_t nodeID );
|
void queryBVH( const pod::BVH& bvh, const pod::AABB& bounds, uf::stl::vector<int32_t>& indices, int32_t nodeID );
|
||||||
|
|
||||||
void queryBVH( const pod::BVH& bvh, const pod::Ray& ray, uf::stl::vector<int32_t>& indices, float maxDist = FLT_MAX );
|
void queryBVH( const pod::BVH& bvh, const pod::Ray& ray, uf::stl::vector<int32_t>& indices, float maxDist = FLT_MAX );
|
||||||
void queryBVH( const pod::BVH& bvh, const pod::Ray& ray, uf::stl::vector<int32_t>& indices, int32_t nodeID, float maxDist = FLT_MAX );
|
void queryBVH( const pod::BVH& bvh, const pod::Ray& ray, uf::stl::vector<int32_t>& indices, int32_t nodeID, float maxDist = FLT_MAX );
|
||||||
|
|
||||||
void queryFlatBVH( const pod::BVH&, const pod::AABB& bounds, uf::stl::vector<int32_t>& out );
|
|
||||||
void queryFlatBVH( const pod::BVH&, const pod::Ray& ray, uf::stl::vector<int32_t>& out, float maxDist = FLT_MAX );
|
|
||||||
|
|
||||||
void queryOverlaps( const pod::BVH& bvh, pod::BVH::pairs_t& outPairs );
|
void queryOverlaps( const pod::BVH& bvh, pod::BVH::pairs_t& outPairs );
|
||||||
void queryOverlaps( const pod::BVH& bvhA, const pod::BVH& bvhB, pod::BVH::pairs_t& outPairs );
|
void queryOverlaps( const pod::BVH& bvhA, const pod::BVH& bvhB, pod::BVH::pairs_t& outPairs );
|
||||||
|
|
||||||
void queryFlatOverlaps( const pod::BVH& bvh, pod::BVH::pairs_t& outPairs );
|
|
||||||
void queryFlatOverlaps( const pod::BVH& bvhA, const pod::BVH& bvhB, pod::BVH::pairs_t& outPairs );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -381,22 +372,4 @@ namespace {
|
|||||||
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool triangleTriangleIntersect( const pod::Triangle& a, const pod::Triangle& b, float eps = EPS(1e-6f) ) {
|
|
||||||
auto boxA = ::computeTriangleAABB( a );
|
|
||||||
auto boxB = ::computeTriangleAABB( b );
|
|
||||||
|
|
||||||
if ( !::aabbOverlap( boxA, boxB ) ) return false;
|
|
||||||
|
|
||||||
// check vertices of a inside b or vice versa
|
|
||||||
for ( auto i = 0; i < 3; i++ ) {
|
|
||||||
auto q = ::closestPointOnTriangle( a.points[i], b );
|
|
||||||
if ( uf::vector::magnitude( q - a.points[i] ) < eps ) return true;
|
|
||||||
}
|
|
||||||
for ( auto i = 0; i < 3; i++ ) {
|
|
||||||
auto q = ::closestPointOnTriangle( b.points[i], a );
|
|
||||||
if ( uf::vector::magnitude( q - b.points[i] ) < eps ) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,41 +5,45 @@
|
|||||||
#include <uf/utils/memory/stack.h>
|
#include <uf/utils/memory/stack.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool warmupSolver = true;
|
bool warmupSolver = true; // cache manifold data to warm up the solver
|
||||||
bool blockContactSolver = true;
|
bool blockContactSolver = true; // use BlockNxN solvers (where N = number of contacts for a manifold)
|
||||||
bool psgContactSolver = true; // iterative solver is flawed
|
bool psgContactSolver = true; // use PSG contact solver
|
||||||
bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK
|
bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK
|
||||||
bool fixedStep = true;
|
bool fixedStep = true; // run physics simulation with a fixed delta time (with accumulation), rather than rely on actual engine deltatime
|
||||||
|
int32_t substeps = 0; // number of substeps per frame tick
|
||||||
|
int32_t reserveCount = 32; // amount of elements to reserve for vectors used in this system, to-do: have it tie to a memory pool allocator
|
||||||
|
|
||||||
int32_t substeps = 0;
|
// increasing these make things lag for reasons I can imagine why
|
||||||
int32_t reserveCount = 32;
|
int32_t broadphaseBvhCapacity = 1; // number of bodies per leaf node
|
||||||
|
int32_t meshBvhCapacity = 1; // number of triangles per leaf node
|
||||||
|
|
||||||
// increasing these make things lag
|
// additionally flattens a BVH for linear iteration, rather than a recursive / stack-based traversal
|
||||||
int32_t broadphaseBvhCapacity = 1;
|
bool flattenBvhBodies = true;
|
||||||
int32_t meshBvhCapacity = 1;
|
|
||||||
|
|
||||||
bool flattenBvhBodies = false; // bugged
|
|
||||||
bool flattenBvhMeshes = true;
|
bool flattenBvhMeshes = true;
|
||||||
|
|
||||||
// it actually seems slower to use these......
|
// use surface area heuristics for building the BVH, rather than naive splits
|
||||||
bool useBvhSahBodies = false;
|
bool useBvhSahBodies = false; // it actually seems slower to use these......
|
||||||
bool useBvhSahMeshes = false;
|
bool useBvhSahMeshes = true;
|
||||||
|
|
||||||
bool useSplitBvhs = true; // currently bugged if enabled
|
bool useSplitBvhs = true; // creates separate BVHs for static / dynamic objects
|
||||||
|
|
||||||
|
// to-do: find possibly better values for this
|
||||||
int32_t solverIterations = 10;
|
int32_t solverIterations = 10;
|
||||||
float baumgarteCorrectionPercent = 0.2f;
|
float baumgarteCorrectionPercent = 0.2f;
|
||||||
float baumgarteCorrectionSlop = 0.01f;
|
float baumgarteCorrectionSlop = 0.01f;
|
||||||
|
|
||||||
uf::stl::unordered_map<size_t, pod::Manifold> manifoldsCache;
|
uf::stl::unordered_map<size_t, pod::Manifold> manifoldsCache;
|
||||||
int32_t manifoldCacheLifetime = 6;
|
int32_t manifoldCacheLifetime = 6; // to-do: find a good value for this
|
||||||
|
|
||||||
uint32_t frameCounter = 0;
|
uint32_t frameCounter = 0;
|
||||||
|
|
||||||
|
// to-do: tweak this to not be annoying
|
||||||
|
// currently seems only reliable when it hits its TTL, but too long of a wait is gross, and too frequent of an update causes lag
|
||||||
pod::BVH::UpdatePolicy bvhUpdatePolicy = {
|
pod::BVH::UpdatePolicy bvhUpdatePolicy = {
|
||||||
.displacementThreshold = 0.25f,
|
.displacementThreshold = 0.25f,
|
||||||
.overlapThreshold = 2.0f,
|
.overlapThreshold = 2.0f,
|
||||||
.dirtyRatioThreshold = 0.3f,
|
.dirtyRatioThreshold = 0.3f,
|
||||||
.maxFramesBeforeRebuild = 60,
|
.maxFramesBeforeRebuild = 120,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +65,7 @@ namespace {
|
|||||||
#include "integration.inl"
|
#include "integration.inl"
|
||||||
#include "solvers.inl"
|
#include "solvers.inl"
|
||||||
|
|
||||||
// unused
|
// unused, as these are from reactphysics
|
||||||
float uf::physics::impl::timescale = 1.0f / 60.0f;
|
float uf::physics::impl::timescale = 1.0f / 60.0f;
|
||||||
bool uf::physics::impl::interpolate = false;
|
bool uf::physics::impl::interpolate = false;
|
||||||
bool uf::physics::impl::shared = false;
|
bool uf::physics::impl::shared = false;
|
||||||
@ -264,9 +268,7 @@ void uf::physics::impl::updateInertia( pod::PhysicsBody& body ) {
|
|||||||
extents *= extents; // square it;
|
extents *= extents; // square it;
|
||||||
|
|
||||||
body.inertiaTensor = extents * (body.mass / 12.0f);
|
body.inertiaTensor = extents * (body.mass / 12.0f);
|
||||||
// to-do: add overloaded inverse order arithmetic operators
|
body.inverseInertiaTensor = 1.0f / body.inertiaTensor;
|
||||||
//body.inverseInertiaTensor = 1.0f / body.inertiaTensor;
|
|
||||||
body.inverseInertiaTensor = { 1.0f / body.inertiaTensor.x, 1.0f / body.inertiaTensor.y, 1.0f / body.inertiaTensor.z };
|
|
||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::SPHERE: {
|
case pod::ShapeType::SPHERE: {
|
||||||
float I = 0.4f * body.mass * body.collider.sphere.radius * body.collider.sphere.radius;
|
float I = 0.4f * body.mass * body.collider.sphere.radius * body.collider.sphere.radius;
|
||||||
|
@ -48,16 +48,10 @@ namespace {
|
|||||||
}
|
}
|
||||||
bool planeCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool planeCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( PLANE, CAPSULE );
|
ASSERT_COLLIDER_TYPES( PLANE, CAPSULE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, capsulePlane );
|
||||||
if ( !::capsulePlane( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool planeMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool planeMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( PLANE, MESH );
|
ASSERT_COLLIDER_TYPES( PLANE, MESH );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, meshPlane );
|
||||||
if ( !::meshPlane( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,23 +53,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
bool spherePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool spherePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( SPHERE, PLANE );
|
ASSERT_COLLIDER_TYPES( SPHERE, PLANE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, planeSphere );
|
||||||
if ( !::planeSphere( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool sphereCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool sphereCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( SPHERE, CAPSULE );
|
ASSERT_COLLIDER_TYPES( SPHERE, CAPSULE );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, capsuleSphere );
|
||||||
if ( !::capsuleSphere( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool sphereMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
bool sphereMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||||
ASSERT_COLLIDER_TYPES( SPHERE, MESH );
|
ASSERT_COLLIDER_TYPES( SPHERE, MESH );
|
||||||
auto start = manifold.points.size();
|
REVERSE_COLLIDER( a, b, meshSphere );
|
||||||
if ( !::meshSphere( b, a, manifold, eps ) ) return false;
|
|
||||||
for ( auto i = start; i < manifold.points.size(); ++i ) manifold.points[i].normal = -manifold.points[i].normal;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,23 +1,9 @@
|
|||||||
#define REORIENT_NORMALS_ON_FETCH 0
|
#define REORIENT_NORMALS_ON_FETCH 0
|
||||||
#define REORIENT_NORMALS_ON_CONTACT 1
|
#define REORIENT_NORMALS_ON_CONTACT 1
|
||||||
|
|
||||||
// mesh BVH
|
#include <uf/utils/math/quant.h>
|
||||||
namespace {
|
|
||||||
// to-do: clean this up
|
|
||||||
uint32_t getIndex( const void* indexData, size_t indexSize, size_t idx ) {
|
|
||||||
if ( indexSize == sizeof(uint8_t) ) {
|
|
||||||
auto* ptr = reinterpret_cast<const uint8_t*>(indexData);
|
|
||||||
return static_cast<uint32_t>(ptr[idx]);
|
|
||||||
} else if ( indexSize == sizeof(uint16_t) ) {
|
|
||||||
auto* ptr = reinterpret_cast<const uint16_t*>(indexData);
|
|
||||||
return static_cast<uint32_t>(ptr[idx]);
|
|
||||||
} else if ( indexSize == sizeof(uint32_t) ) {
|
|
||||||
auto* ptr = reinterpret_cast<const uint32_t*>(indexData);
|
|
||||||
return ptr[idx];
|
|
||||||
}
|
|
||||||
UF_EXCEPTION("Unsupported index type of size {}", indexSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
pod::Vector3f triangleCenter( const pod::Triangle& tri ) {
|
pod::Vector3f triangleCenter( const pod::Triangle& tri ) {
|
||||||
return ( tri.points[0] + tri.points[1] + tri.points[2] ) / 3.0f;
|
return ( tri.points[0] + tri.points[1] + tri.points[2] ) / 3.0f;
|
||||||
}
|
}
|
||||||
@ -29,12 +15,80 @@ namespace {
|
|||||||
//return uf::vector::normalize( tri.normals[0] + tri.normals[1] + tri.normals[2] );
|
//return uf::vector::normalize( tri.normals[0] + tri.normals[1] + tri.normals[2] );
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::Triangle fetchTriangle( const void* vertices, size_t vertexStride, const void* indexData, size_t indexSize, size_t triID ) {
|
bool triangleTriangleIntersect( const pod::Triangle& a, const pod::Triangle& b, float eps = EPS(1e-6f) ) {
|
||||||
return {
|
auto boxA = ::computeTriangleAABB( a );
|
||||||
*reinterpret_cast<const pod::Vector3f*>(reinterpret_cast<const uint8_t*>(vertices) + ::getIndex( indexData, indexSize, (triID * 3) + 0 ) * vertexStride),
|
auto boxB = ::computeTriangleAABB( b );
|
||||||
*reinterpret_cast<const pod::Vector3f*>(reinterpret_cast<const uint8_t*>(vertices) + ::getIndex( indexData, indexSize, (triID * 3) + 1 ) * vertexStride),
|
|
||||||
*reinterpret_cast<const pod::Vector3f*>(reinterpret_cast<const uint8_t*>(vertices) + ::getIndex( indexData, indexSize, (triID * 3) + 2 ) * vertexStride),
|
if ( !::aabbOverlap( boxA, boxB ) ) return false;
|
||||||
};
|
|
||||||
|
// check vertices of a inside b or vice versa
|
||||||
|
FOR_EACH(3, {
|
||||||
|
auto q = ::closestPointOnTriangle( a.points[i], b );
|
||||||
|
if ( uf::vector::magnitude( q - a.points[i] ) < eps ) return true;
|
||||||
|
});
|
||||||
|
FOR_EACH(3, {
|
||||||
|
auto q = ::closestPointOnTriangle( b.points[i], a );
|
||||||
|
if ( uf::vector::magnitude( q - b.points[i] ) < eps ) return true;
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getIndex( const void* pointer, size_t stride, size_t index ) {
|
||||||
|
#define CAST_INDEX(T) case sizeof(T): return ((T*) pointer)[index];
|
||||||
|
switch ( stride ) {
|
||||||
|
CAST_INDEX(uint8_t);
|
||||||
|
CAST_INDEX(uint16_t);
|
||||||
|
CAST_INDEX(uint32_t);
|
||||||
|
default: {
|
||||||
|
UF_EXCEPTION("invalid stride type: {}", stride);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t getIndex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, size_t index ) {
|
||||||
|
return ::getIndex( indices.data(view.index.first), indices.stride(), index );
|
||||||
|
}
|
||||||
|
pod::Vector3f getVertex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, size_t index ) {
|
||||||
|
const auto stride = positions.stride();
|
||||||
|
#define CAST_VERTEX(T) {\
|
||||||
|
const T* vertices = (T*) positions.data(view.vertex.first + index);\
|
||||||
|
return { vertices[0], vertices[1], vertices[2], };\
|
||||||
|
}
|
||||||
|
#define DEQUANTIZE_VERTEX(T) {\
|
||||||
|
const T* vertices = (T*) positions.data(view.vertex.first + index);\
|
||||||
|
return { uf::quant::dequantize(vertices[0]), uf::quant::dequantize(vertices[1]), uf::quant::dequantize(vertices[2]), };\
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( positions.attribute.descriptor.type ) {
|
||||||
|
// dequantize
|
||||||
|
case uf::renderer::enums::Type::USHORT:
|
||||||
|
case uf::renderer::enums::Type::SHORT: {
|
||||||
|
DEQUANTIZE_VERTEX(uint16_t);
|
||||||
|
} break;
|
||||||
|
case uf::renderer::enums::Type::FLOAT: {
|
||||||
|
CAST_VERTEX(float);
|
||||||
|
} break;
|
||||||
|
#if UF_USE_FLOAT16
|
||||||
|
case uf::renderer::enums::Type::HALF: {
|
||||||
|
CAST_VERTEX(std::float16_t);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
#if UF_USE_BFLOAT16
|
||||||
|
case uf::renderer::enums::Type::BFLOAT: {
|
||||||
|
CAST_VERTEX(std::bfloat16_t);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
default: UF_EXCEPTION("unsupported vertex type: {}", positions.attribute.descriptor.type); break;
|
||||||
|
}
|
||||||
|
// return ::getVertex( positions.data(view.vertex.first), positions.stride(), index );
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::Triangle fetchTriangle( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID ) {
|
||||||
|
auto index = triID * 3;
|
||||||
|
pod::Triangle tri;
|
||||||
|
FOR_EACH(3, {
|
||||||
|
tri.points[i] = ::getVertex( view, positions, ::getIndex( view, indices, index + i ) );
|
||||||
|
});
|
||||||
|
return tri;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID ) {
|
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID ) {
|
||||||
@ -43,49 +97,42 @@ namespace {
|
|||||||
|
|
||||||
// find which view contains this triangle index.
|
// find which view contains this triangle index.
|
||||||
size_t triBase = 0;
|
size_t triBase = 0;
|
||||||
const uf::Mesh::View* found = nullptr;
|
const uf::Mesh::View* view = nullptr;
|
||||||
for ( auto& v : views ) {
|
for ( auto& v : views ) {
|
||||||
auto trisInView = v.index.count / 3;
|
auto trisInView = v.index.count / 3;
|
||||||
if (triID < triBase + trisInView) {
|
if (triID < triBase + trisInView) {
|
||||||
found = &v;
|
view = &v;
|
||||||
triID -= triBase; // local triangle index inside this view
|
triID -= triBase; // local triangle index inside this view
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
triBase += trisInView;
|
triBase += trisInView;
|
||||||
}
|
}
|
||||||
UF_ASSERT( found );
|
UF_ASSERT( view );
|
||||||
|
|
||||||
auto& positions = (*found)["position"];
|
auto& positions = (*view)["position"];
|
||||||
auto& normals = (*found)["normal"];
|
auto& normals = (*view)["normal"];
|
||||||
auto& indices = (*found)["index"];
|
auto& indices = (*view)["index"];
|
||||||
|
|
||||||
pod::TriangleWithNormal tri = { ::fetchTriangle( positions.data(found->vertex.first), positions.stride(), indices.data(found->index.first), mesh.index.size, triID ) };
|
pod::TriangleWithNormal tri = { ::fetchTriangle( *view, indices, positions, triID ) };
|
||||||
tri.normal = uf::vector::normalize(uf::vector::cross(tri.points[1] - tri.points[0], tri.points[2] - tri.points[0]));
|
tri.normal = uf::vector::normalize(uf::vector::cross(tri.points[1] - tri.points[0], tri.points[2] - tri.points[0]));
|
||||||
|
|
||||||
/*
|
|
||||||
if ( false && normals.valid() ) {
|
|
||||||
auto* base = reinterpret_cast<const uint8_t*>(normals.data(found->vertex.first));
|
|
||||||
size_t stride = normals.stride();
|
|
||||||
for ( auto i = 0; i < 3; ++i ) tri.normals[i] = *reinterpret_cast<const pod::Vector3f*>(base + idxs[i] * stride);
|
|
||||||
} else {
|
|
||||||
auto normal = ::triangleNormal( (pod::Triangle&) tri );
|
|
||||||
for ( auto i = 0; i < 3; ++i ) tri.normals[i] = normal;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return tri;
|
return tri;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body
|
// if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body
|
||||||
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body, bool fast = true ) {
|
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body, bool fast = false ) {
|
||||||
auto tri = ::fetchTriangle( mesh, triID );
|
auto tri = ::fetchTriangle( mesh, triID );
|
||||||
auto transform = ::getTransform( body );
|
auto transform = ::getTransform( body );
|
||||||
|
|
||||||
if ( body.collider.type == pod::ShapeType::MESH ) {
|
if ( body.collider.type == pod::ShapeType::MESH ) {
|
||||||
if ( fast ) {
|
if ( fast ) {
|
||||||
for ( auto i = 0; i < 3; ++i ) tri.points[i] += transform.position;
|
FOR_EACH(3, {
|
||||||
|
tri.points[i] += transform.position;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
for ( auto i = 0; i < 3; ++i ) tri.points[i] = uf::transform::apply( transform, tri.points[i] );
|
FOR_EACH(3, {
|
||||||
|
tri.points[i] = uf::transform::apply( transform, tri.points[i] );
|
||||||
|
});
|
||||||
tri.normal = uf::quaternion::rotate( transform.orientation, tri.normal );
|
tri.normal = uf::quaternion::rotate( transform.orientation, tri.normal );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,24 +179,24 @@ namespace {
|
|||||||
|
|
||||||
// clip edges of A against plane of B
|
// clip edges of A against plane of B
|
||||||
const pod::Vector3f At[3] = { A.points[0], A.points[1], A.points[2] };
|
const pod::Vector3f At[3] = { A.points[0], A.points[1], A.points[2] };
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
FOR_EACH(3, {
|
||||||
auto j = ( i + 1 ) % 3;
|
auto j = ( i + 1 ) % 3;
|
||||||
pod::Vector3f p;
|
pod::Vector3f p;
|
||||||
if ( intersectSegmentPlane( At[i], At[j], nB, dB, p ) ) {
|
if ( intersectSegmentPlane( At[i], At[j], nB, dB, p ) ) {
|
||||||
// check if intersection lies inside triangle B
|
// check if intersection lies inside triangle B
|
||||||
if ( ::pointInTriangle( p, B ) ) checkAndPush(p);
|
if ( ::pointInTriangle( p, B ) ) checkAndPush(p);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// clip edges of B against plane of A
|
// clip edges of B against plane of A
|
||||||
const pod::Vector3f Bt[3] = { B.points[0], B.points[1], B.points[2] };
|
const pod::Vector3f Bt[3] = { B.points[0], B.points[1], B.points[2] };
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
FOR_EACH(3, {
|
||||||
auto j = ( i + 1 ) % 3;
|
auto j = ( i + 1 ) % 3;
|
||||||
pod::Vector3f p;
|
pod::Vector3f p;
|
||||||
if ( intersectSegmentPlane( Bt[i], Bt[j], nA, dA, p ) ) {
|
if ( intersectSegmentPlane( Bt[i], Bt[j], nA, dA, p ) ) {
|
||||||
if ( ::pointInTriangle( p, A ) ) checkAndPush(p);
|
if ( ::pointInTriangle( p, A ) ) checkAndPush(p);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
if ( intersections.empty() ) return false;
|
if ( intersections.empty() ) return false;
|
||||||
|
|
||||||
@ -295,7 +342,9 @@ namespace {
|
|||||||
|
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
pod::Vector3f dist;
|
pod::Vector3f dist;
|
||||||
for ( auto i = 0; i < 3; i++ ) dist[i] = uf::vector::dot(normal, tri.points[i] ) - d;
|
FOR_EACH(3, {
|
||||||
|
dist[i] = uf::vector::dot(normal, tri.points[i] ) - d;
|
||||||
|
});
|
||||||
|
|
||||||
// completely on one side
|
// completely on one side
|
||||||
bool allAbove = ( dist.x > eps && dist.y > eps && dist.z > eps );
|
bool allAbove = ( dist.x > eps && dist.y > eps && dist.z > eps );
|
||||||
@ -305,10 +354,10 @@ namespace {
|
|||||||
|
|
||||||
if ( allBelow ) {
|
if ( allBelow ) {
|
||||||
hit = true;
|
hit = true;
|
||||||
for ( auto i = 0; i < 3; i++ ) {
|
FOR_EACH(3, {
|
||||||
float penetration = -dist[i];
|
float penetration = -dist[i];
|
||||||
manifold.points.emplace_back(pod::Contact{tri.points[i], normal, penetration});
|
manifold.points.emplace_back(pod::Contact{tri.points[i], normal, -dist[i]});
|
||||||
}
|
});
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user