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": {
|
||||
"mass": 0,
|
||||
"inertia": [0, 0, 0],
|
||||
"type": "bounding box",
|
||||
"recenter": true
|
||||
"type": "mesh" // "bounding box"
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
"physics": {
|
||||
"mass": 0,
|
||||
"type": "bounding box"
|
||||
// "type": "mesh"
|
||||
}
|
||||
}
|
||||
}
|
@ -8,10 +8,16 @@ namespace pod {
|
||||
template<typename T = NUM, size_t R = 4, size_t C = R>
|
||||
struct /*UF_API*/ Matrix {
|
||||
// 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
|
||||
typedef T type_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 columns = C;
|
||||
// Overload access
|
||||
@ -23,12 +29,12 @@ namespace pod {
|
||||
FORCE_INLINE const T& operator()(size_t r, size_t c) const;
|
||||
|
||||
// Arithmetic
|
||||
Matrix<T,R,C> operator*( const Matrix<T,R,C>& matrix ) const;
|
||||
Matrix<T,R,C> operator*( T scalar ) const;
|
||||
Matrix<T,R,C> operator+( const Matrix<T,R,C>& matrix ) const;
|
||||
Matrix<T,R,C>& operator *=( const Matrix<T,R,C>& matrix );
|
||||
bool operator==( const Matrix<T,R,C>& matrix ) const;
|
||||
bool operator!=( const Matrix<T,R,C>& matrix ) const;
|
||||
FORCE_INLINE Matrix<T,R,C> operator*( const Matrix<T,R,C>& matrix ) const;
|
||||
FORCE_INLINE Matrix<T,R,C> operator*( T scalar ) const;
|
||||
FORCE_INLINE 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 );
|
||||
FORCE_INLINE 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>;
|
||||
@ -48,66 +54,66 @@ namespace uf {
|
||||
namespace matrix {
|
||||
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> 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=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ initialize( const T* );
|
||||
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ initialize( const uf::stl::vector<T>& );
|
||||
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> 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, typename U> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> multiply( const T& left, const U& 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> /*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> 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::Matrix2t<T> inverse(const pod::Matrix2t<T>& mat );
|
||||
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix3t<T> inverse(const pod::Matrix3t<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> 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> pod::Vector4t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector, bool = false );
|
||||
template<typename T=NUM> /*FORCE_INLINE*/ pod::Vector2t<T> multiply(const pod::Matrix2t<T>& mat, const pod::Vector2t<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> /*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> /*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> T /*UF_API*/ add( const T& lhs, const T& rhs );
|
||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar );
|
||||
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, typename U> 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=pod::Matrix4> 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> T& /*UF_API*/ scale_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T& /*UF_API*/ inverse_( T& matrix );
|
||||
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> /*FORCE_INLINE*/ pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const T& right );
|
||||
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> /*FORCE_INLINE*/ T& /*UF_API*/ rotate_( 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> 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> pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
||||
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> /*FORCE_INLINE*/ 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*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
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> 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( T, T, T, T, T, T );
|
||||
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T );
|
||||
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 );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
|
||||
template<typename T=NUM> 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, T, T, T );
|
||||
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 );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
// Setting
|
||||
template<typename T=pod::Matrix4> 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, const T& 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> 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> 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*/ uf::stl::string /*UF_API*/ toString( const pod::Matrix<T,R,C>& v );
|
||||
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> /*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> /*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 string {
|
||||
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 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> 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 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 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, const pod::Matrix<T,R,C>& = uf::matrix::identity() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,45 +19,45 @@ namespace pod {
|
||||
|
||||
namespace uf {
|
||||
namespace quaternion {
|
||||
template<typename T = NUM> pod::Quaternion<T> /*UF_API*/ identity();
|
||||
template<typename T> 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> 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> typename T::type_t /*UF_API*/ product( const T& vector );
|
||||
template<typename T = NUM> /*FORCE_INLINE*/ pod::Quaternion<T> /*UF_API*/ identity();
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& left, const 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> /*FORCE_INLINE*/ pod::Vector4t<T> /*UF_API*/ rotate( const pod::Quaternion<T>& left, const pod::Vector4t<T>& right );
|
||||
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ sum( 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> pod::Angle /*UF_API*/ angle( const T& a, const T& b );
|
||||
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ dot( const T& left, const T& right );
|
||||
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> T /*UF_API*/ slerp( 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> /*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> 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> 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*/ typename T::type_t /*UF_API*/ distanceSquared( 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> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ magnitude( const T& vector );
|
||||
template<typename T> /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ norm( 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> 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> pod::Quaternion<T> lookAt( const pod::Vector3t<T>& source, const pod::Vector3t<T>& destination );
|
||||
template<typename T> /*FORCE_INLINE*/ pod::Matrix4t<T> matrix( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> axisAngle( const pod::Vector3t<T>& axis, T angle );
|
||||
template<typename T> /*FORCE_INLINE*/ pod::Quaternion<T> unitVectors( const pod::Vector3t<T>& u, const pod::Vector3t<T>& v );
|
||||
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> T inverse( const T& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ T conjugate( 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> T& /*UF_API*/ normalize_( T& vector );
|
||||
template<typename T> T& conjugate_( T& quaternion );
|
||||
template<typename T> T& inverse_( T& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& left, const T& right );
|
||||
template<typename T> /*FORCE_INLINE*/ T& /*UF_API*/ normalize_( T& vector );
|
||||
template<typename T> /*FORCE_INLINE*/ T& conjugate_( 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> T pitch( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> T yaw( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> T roll( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> eulerAngles( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ T pitch( const pod::Quaternion<T>& quaternion );
|
||||
template<typename T> /*FORCE_INLINE*/ T yaw( 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
|
||||
namespace uf {
|
||||
namespace vector {
|
||||
template<typename T> 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> 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, 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, 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> /*FORCE_INLINE*/ pod::Vector1t<T> /*UF_API*/ create( T x ); // creates a 1D vector
|
||||
template<typename T> /*FORCE_INLINE*/ pod::Vector2t<T> /*UF_API*/ create( T x, T y ); // creates a 2D 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> /*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> /*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> /*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
|
||||
template<typename T> 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> 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> 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*/ equals( 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> /*FORCE_INLINE*/ bool /*UF_API*/ less( 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> /*FORCE_INLINE*/ bool /*UF_API*/ greater( 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
|
||||
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> 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> 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> 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> 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> 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> 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*/ 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, typename T::type_t scalar ); // adds a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ 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, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ 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& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ 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, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
||||
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> 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> 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> 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> 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> 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> 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> T& /*UF_API*/ normalize_( T& vector ); // normalizes a vector
|
||||
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> /*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> /*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> /*FORCE_INLINE*/ 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, typename T::type_t scalar ); // subtracts a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ 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& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ 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, typename T::type_t scalar ); // divides a scalar to every component of the vector
|
||||
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> /*FORCE_INLINE*/ T& /*UF_API*/ negate_( T& vector ); // flip sign of all components
|
||||
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> 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> 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> 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> 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> T /*UF_API*/ round( const T& vector ); // rounds each component of the vector
|
||||
template<typename T> /*FORCE_INLINE*/ 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*/ product( const T& vector ); // compute the product of all components
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ negate( const T& vector ); // flip sign of all components
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ abs( const T& vector ); // gets the absolute value of a vector
|
||||
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> /*FORCE_INLINE*/ 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*/ clamp( const T& vector, const T& min, const T& max ); // clamps a vector between two bounds
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ ceil( const T& vector ); // rounds each component of the the vector up
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ floor( const T& vector ); // rounds each component of the vector down
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ round( const T& vector ); // rounds each component of the vector
|
||||
// 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> 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> T /*UF_API*/ cross( const T& a, const T& b ); // compute the cross 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> /*FORCE_INLINE*/ float /*UF_API*/ angle( const T& a, const T& b ); // compute the 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> /*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> 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, double, bool = true ); // linearly interpolate between two vectors
|
||||
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> T /*UF_API*/ mix( const T& from, const T& to, double, bool = false );
|
||||
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> /*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> 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> 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> 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> T /*UF_API*/ orthonormalize( const T& x, const T& y ); // orthonormalizes a vector against another vector
|
||||
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> /*FORCE_INLINE*/ 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*/ magnitude( const T& vector ); // gets the magnitude 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> /*FORCE_INLINE*/ T /*UF_API*/ normalize( const T& vector ); // normalizes a vector
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ clampMagnitude( const T& vector ); // clamps the magnitude of a vector
|
||||
template<typename T> /*FORCE_INLINE*/ void /*UF_API*/ orthonormalize( T& x, 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, 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*/ size_t /*UF_API*/ hash( const T& vector ); // hashes a vector
|
||||
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> 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, 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>{}); } \
|
||||
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 {
|
||||
template<typename T, size_t N>
|
||||
struct Vector {
|
||||
@ -238,30 +245,35 @@ namespace pod {
|
||||
|
||||
// external functions
|
||||
|
||||
//#include <uf/utils/string/ext.h>
|
||||
#include <sstream>
|
||||
// scalar operator vector
|
||||
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 string {
|
||||
template<typename T, size_t N>
|
||||
uf::stl::string toString( const pod::Vector<T,N>& v );
|
||||
template<typename T, size_t N> FORCE_INLINE uf::stl::string toString( const pod::Vector<T,N>& v );
|
||||
}
|
||||
}
|
||||
// jsonify
|
||||
namespace ext {
|
||||
namespace json {
|
||||
template<typename T, size_t N> 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> pod::Vector<T,N> decode( const ext::json::Value&, const pod::Vector<T,N>& = {} );
|
||||
template<typename T, size_t N> FORCE_INLINE ext::json::Value encode( const pod::Vector<T,N>& v );
|
||||
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> FORCE_INLINE pod::Vector<T,N> decode( const ext::json::Value&, const pod::Vector<T,N>& = {} );
|
||||
}
|
||||
}
|
||||
|
||||
// hash
|
||||
namespace std {
|
||||
template<typename T, size_t N>
|
||||
struct hash<pod::Vector<T,N>> {
|
||||
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;
|
||||
}
|
||||
FORCE_INLINE size_t operator()(const pod::Vector<T,N>& v) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -276,9 +276,9 @@ T uf::vector::divide( const T& vector, typename T::type_t scalar ) {
|
||||
}
|
||||
#endif
|
||||
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, {
|
||||
res[i] = vector[i] * scalar;
|
||||
res[i] = vector[i] * recip;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
@ -298,9 +298,9 @@ T uf::vector::divide( typename T::type_t scalar, const T& vector ) {
|
||||
}
|
||||
#endif
|
||||
T res;
|
||||
scalar = static_cast<T>(1) / scalar;
|
||||
float recip = static_cast<typename T::type_t>(1) / scalar;
|
||||
FOR_EACH(T::size, {
|
||||
res[i] = scalar / vector[i];
|
||||
res[i] = vector[i] * recip;
|
||||
});
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
uf::stl::string uf::vector::toString( const T& v ) {
|
||||
uf::stl::stringstream ss;
|
||||
|
@ -17,4 +17,9 @@ pod::Vector<T,N>& /*UF_API*/ ext::json::decode( const ext::json::Value& json, po
|
||||
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 ) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
/*
|
||||
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;
|
||||
|
||||
// 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;
|
||||
protected:
|
||||
void _destroy( uf::Mesh::Input& input );
|
||||
|
@ -1,24 +1,74 @@
|
||||
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 );
|
||||
#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{} );
|
||||
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 {
|
||||
uf::vector::min( 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 );
|
||||
}
|
||||
|
||||
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 ) {
|
||||
const auto transform = ::getTransform( body );
|
||||
const auto& capsule = body.collider.capsule;
|
||||
@ -34,10 +84,13 @@ namespace {
|
||||
const auto transform = ::getTransform( body );
|
||||
switch ( body.collider.type ) {
|
||||
case pod::ShapeType::AABB: {
|
||||
/*
|
||||
return {
|
||||
transform.position + body.collider.aabb.min,
|
||||
transform.position + body.collider.aabb.max,
|
||||
};
|
||||
*/
|
||||
return ::transformAabbToWorld( body.collider.aabb, *body.transform );
|
||||
} break;
|
||||
case pod::ShapeType::SPHERE: {
|
||||
return {
|
||||
@ -63,20 +116,13 @@ namespace {
|
||||
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 minDistSq = FLT_MAX;
|
||||
for ( auto i = 0; i < 3; ++i ) {
|
||||
FOR_EACH(3, {
|
||||
auto cp = ::closestPointOnAABB( tri.points[i], box );
|
||||
auto d = tri.points[i] - cp;
|
||||
minDistSq = std::min( minDistSq, uf::vector::dot( d, d ) );
|
||||
}
|
||||
});
|
||||
return minDistSq;
|
||||
}
|
||||
|
||||
@ -124,11 +170,11 @@ namespace {
|
||||
if ( !axisTest( {-f2.y, f2.x, 0} ) ) return false;
|
||||
|
||||
// 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 maxVal = std::max({v0[i], v1[i], v2[i]});
|
||||
if ( minVal > e[i] || maxVal < -e[i] ) return false;
|
||||
}
|
||||
});
|
||||
|
||||
// test triangle normal axis
|
||||
auto n = uf::vector::cross( f0, f1 );
|
||||
@ -139,13 +185,6 @@ namespace {
|
||||
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 ) {
|
||||
auto inv = uf::transform::inverse( transform );
|
||||
|
||||
@ -166,21 +205,14 @@ namespace {
|
||||
{ -FLT_MAX, -FLT_MAX, -FLT_MAX },
|
||||
};
|
||||
|
||||
for ( auto i = 0; i < 8; ++i ) {
|
||||
FOR_EACH(8, {
|
||||
auto local = uf::transform::apply( inv, corners[i] );
|
||||
out.min = uf::vector::min( out.min, local );
|
||||
out.max = uf::vector::max( out.max, local );
|
||||
}
|
||||
});
|
||||
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 ) {
|
||||
ASSERT_COLLIDER_TYPES(AABB, AABB);
|
||||
|
||||
@ -195,12 +227,12 @@ namespace {
|
||||
// determine collision axis = smallest overlap
|
||||
auto axis = -1;
|
||||
float minOverlap = FLT_MAX;
|
||||
for ( auto i = 0; i < 3; ++i ) {
|
||||
FOR_EACH(3, {
|
||||
if ( overlaps[i] < minOverlap ) {
|
||||
minOverlap = overlaps[i];
|
||||
axis = i;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pod::Vector3f delta = ::getPosition( b ) - ::getPosition( a );
|
||||
pod::Vector3f normal{0,0,0};
|
||||
@ -211,13 +243,13 @@ namespace {
|
||||
auto Max = uf::vector::min( A.max, B.max );
|
||||
|
||||
// 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, 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, 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), 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 });
|
||||
@ -235,30 +267,18 @@ namespace {
|
||||
|
||||
bool aabbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( AABB, SPHERE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, sphereAabb );
|
||||
}
|
||||
bool aabbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( AABB, PLANE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, planeAabb );
|
||||
}
|
||||
bool aabbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( AABB, CAPSULE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, capsuleAabb );
|
||||
}
|
||||
bool aabbMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( AABB, MESH );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, meshAabb );
|
||||
}
|
||||
}
|
@ -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
|
||||
namespace {
|
||||
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;
|
||||
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 triID = triIndexID + (view.index.first / 3);
|
||||
|
||||
@ -363,7 +373,7 @@ namespace {
|
||||
|
||||
auto tris = view.index.count / 3;
|
||||
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 );
|
||||
bounds.emplace_back(aabb);
|
||||
}
|
||||
|
@ -104,9 +104,6 @@ namespace {
|
||||
}
|
||||
bool capsuleMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( CAPSULE, MESH );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, meshCapsule );
|
||||
}
|
||||
}
|
@ -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
|
||||
namespace {
|
||||
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) );
|
||||
|
||||
// ugh
|
||||
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 );
|
||||
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 );
|
||||
|
||||
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::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 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& 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 {
|
||||
@ -381,22 +372,4 @@ namespace {
|
||||
|
||||
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>
|
||||
|
||||
namespace {
|
||||
bool warmupSolver = true;
|
||||
bool blockContactSolver = true;
|
||||
bool psgContactSolver = true; // iterative solver is flawed
|
||||
bool warmupSolver = true; // cache manifold data to warm up the solver
|
||||
bool blockContactSolver = true; // use BlockNxN solvers (where N = number of contacts for a manifold)
|
||||
bool psgContactSolver = true; // use PSG contact solver
|
||||
bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK
|
||||
bool fixedStep = true;
|
||||
|
||||
int32_t substeps = 0;
|
||||
int32_t reserveCount = 32;
|
||||
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
|
||||
|
||||
// increasing these make things lag
|
||||
int32_t broadphaseBvhCapacity = 1;
|
||||
int32_t meshBvhCapacity = 1;
|
||||
// increasing these make things lag for reasons I can imagine why
|
||||
int32_t broadphaseBvhCapacity = 1; // number of bodies per leaf node
|
||||
int32_t meshBvhCapacity = 1; // number of triangles per leaf node
|
||||
|
||||
bool flattenBvhBodies = false; // bugged
|
||||
// additionally flattens a BVH for linear iteration, rather than a recursive / stack-based traversal
|
||||
bool flattenBvhBodies = true;
|
||||
bool flattenBvhMeshes = true;
|
||||
|
||||
// it actually seems slower to use these......
|
||||
bool useBvhSahBodies = false;
|
||||
bool useBvhSahMeshes = false;
|
||||
// use surface area heuristics for building the BVH, rather than naive splits
|
||||
bool useBvhSahBodies = false; // it actually seems slower to use these......
|
||||
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;
|
||||
float baumgarteCorrectionPercent = 0.2f;
|
||||
float baumgarteCorrectionSlop = 0.01f;
|
||||
|
||||
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;
|
||||
|
||||
// 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 = {
|
||||
.displacementThreshold = 0.25f,
|
||||
.overlapThreshold = 2.0f,
|
||||
.dirtyRatioThreshold = 0.3f,
|
||||
.maxFramesBeforeRebuild = 60,
|
||||
.maxFramesBeforeRebuild = 120,
|
||||
};
|
||||
}
|
||||
|
||||
@ -61,7 +65,7 @@ namespace {
|
||||
#include "integration.inl"
|
||||
#include "solvers.inl"
|
||||
|
||||
// unused
|
||||
// unused, as these are from reactphysics
|
||||
float uf::physics::impl::timescale = 1.0f / 60.0f;
|
||||
bool uf::physics::impl::interpolate = false;
|
||||
bool uf::physics::impl::shared = false;
|
||||
@ -264,9 +268,7 @@ void uf::physics::impl::updateInertia( pod::PhysicsBody& body ) {
|
||||
extents *= extents; // square it;
|
||||
|
||||
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.x, 1.0f / body.inertiaTensor.y, 1.0f / body.inertiaTensor.z };
|
||||
body.inverseInertiaTensor = 1.0f / body.inertiaTensor;
|
||||
} break;
|
||||
case pod::ShapeType::SPHERE: {
|
||||
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 ) {
|
||||
ASSERT_COLLIDER_TYPES( PLANE, CAPSULE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, capsulePlane );
|
||||
}
|
||||
bool planeMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( PLANE, MESH );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, meshPlane );
|
||||
}
|
||||
}
|
@ -53,23 +53,14 @@ namespace {
|
||||
}
|
||||
bool spherePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( SPHERE, PLANE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, planeSphere );
|
||||
}
|
||||
bool sphereCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( SPHERE, CAPSULE );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, capsuleSphere );
|
||||
}
|
||||
bool sphereMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
|
||||
ASSERT_COLLIDER_TYPES( SPHERE, MESH );
|
||||
auto start = manifold.points.size();
|
||||
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;
|
||||
REVERSE_COLLIDER( a, b, meshSphere );
|
||||
}
|
||||
}
|
@ -1,23 +1,9 @@
|
||||
#define REORIENT_NORMALS_ON_FETCH 0
|
||||
#define REORIENT_NORMALS_ON_CONTACT 1
|
||||
|
||||
// mesh BVH
|
||||
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);
|
||||
}
|
||||
#include <uf/utils/math/quant.h>
|
||||
|
||||
namespace {
|
||||
pod::Vector3f triangleCenter( const pod::Triangle& tri ) {
|
||||
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] );
|
||||
}
|
||||
|
||||
pod::Triangle fetchTriangle( const void* vertices, size_t vertexStride, const void* indexData, size_t indexSize, size_t triID ) {
|
||||
return {
|
||||
*reinterpret_cast<const pod::Vector3f*>(reinterpret_cast<const uint8_t*>(vertices) + ::getIndex( indexData, indexSize, (triID * 3) + 0 ) * vertexStride),
|
||||
*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),
|
||||
};
|
||||
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_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 ) {
|
||||
@ -43,49 +97,42 @@ namespace {
|
||||
|
||||
// find which view contains this triangle index.
|
||||
size_t triBase = 0;
|
||||
const uf::Mesh::View* found = nullptr;
|
||||
const uf::Mesh::View* view = nullptr;
|
||||
for ( auto& v : views ) {
|
||||
auto trisInView = v.index.count / 3;
|
||||
if (triID < triBase + trisInView) {
|
||||
found = &v;
|
||||
view = &v;
|
||||
triID -= triBase; // local triangle index inside this view
|
||||
break;
|
||||
}
|
||||
triBase += trisInView;
|
||||
}
|
||||
UF_ASSERT( found );
|
||||
UF_ASSERT( view );
|
||||
|
||||
auto& positions = (*found)["position"];
|
||||
auto& normals = (*found)["normal"];
|
||||
auto& indices = (*found)["index"];
|
||||
auto& positions = (*view)["position"];
|
||||
auto& normals = (*view)["normal"];
|
||||
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]));
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 transform = ::getTransform( body );
|
||||
|
||||
if ( body.collider.type == pod::ShapeType::MESH ) {
|
||||
if ( fast ) {
|
||||
for ( auto i = 0; i < 3; ++i ) tri.points[i] += transform.position;
|
||||
FOR_EACH(3, {
|
||||
tri.points[i] += transform.position;
|
||||
});
|
||||
} 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 );
|
||||
}
|
||||
}
|
||||
@ -132,24 +179,24 @@ namespace {
|
||||
|
||||
// clip edges of A against plane of B
|
||||
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;
|
||||
pod::Vector3f p;
|
||||
if ( intersectSegmentPlane( At[i], At[j], nB, dB, p ) ) {
|
||||
// check if intersection lies inside triangle B
|
||||
if ( ::pointInTriangle( p, B ) ) checkAndPush(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// clip edges of B against plane of A
|
||||
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;
|
||||
pod::Vector3f p;
|
||||
if ( intersectSegmentPlane( Bt[i], Bt[j], nA, dA, p ) ) {
|
||||
if ( ::pointInTriangle( p, A ) ) checkAndPush(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ( intersections.empty() ) return false;
|
||||
|
||||
@ -295,7 +342,9 @@ namespace {
|
||||
|
||||
bool hit = false;
|
||||
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
|
||||
bool allAbove = ( dist.x > eps && dist.y > eps && dist.z > eps );
|
||||
@ -305,10 +354,10 @@ namespace {
|
||||
|
||||
if ( allBelow ) {
|
||||
hit = true;
|
||||
for ( auto i = 0; i < 3; i++ ) {
|
||||
FOR_EACH(3, {
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user