// // Test_quat_aos_neon.cpp // BulletTest // // Copyright (c) 2011 Apple Inc., Inc. // #include "LinearMath/btScalar.h" #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON) #include "Test_quat_aos_neon.h" #include "vector.h" #include "Utils.h" #include "main.h" #include //typedef Vectormath::Aos::Vector3 vmVector3; //typedef Vectormath::Aos::Quat vmQuat; //typedef Vectormath::Aos::Matrix3 vmMatrix3; //typedef Vectormath::Aos::Transform3 vmTransform3; //typedef Vectormath::Aos::Point3 vmPoint3; typedef Vectormath::Aos::Vector4 vmVector4; // reference code for testing purposes ATTRIBUTE_ALIGNED16(class) Quat_ref { float mX; float mY; float mZ; float mW; public: // Default constructor; does no initialization // inline Quat_ref( ) { }; // Copy a quaternion // inline Quat_ref( const Quat_ref & quat ); // Construct a quaternion from x, y, z, and w elements // inline Quat_ref( float x, float y, float z, float w ); // Construct a quaternion from a 3-D vector and a scalar // inline Quat_ref( const vmVector3 & xyz, float w ); // Copy elements from a 4-D vector into a quaternion // explicit inline Quat_ref( const vmVector4 & vec ); // Convert a rotation matrix to a unit-length quaternion // explicit inline Quat_ref( const vmMatrix3 & rotMat ); // Set all elements of a quaternion to the same scalar value // explicit inline Quat_ref( float scalar ); // Assign one quaternion to another // inline Quat_ref & operator =( const Quat_ref & quat ); // Set the x, y, and z elements of a quaternion // NOTE: // This function does not change the w element. // inline Quat_ref & setXYZ( const vmVector3 & vec ); // Get the x, y, and z elements of a quaternion // inline const vmVector3 getXYZ( ) const; // Set the x element of a quaternion // inline Quat_ref & setX( float x ); // Set the y element of a quaternion // inline Quat_ref & setY( float y ); // Set the z element of a quaternion // inline Quat_ref & setZ( float z ); // Set the w element of a quaternion // inline Quat_ref & setW( float w ); // Get the x element of a quaternion // inline float getX( ) const; // Get the y element of a quaternion // inline float getY( ) const; // Get the z element of a quaternion // inline float getZ( ) const; // Get the w element of a quaternion // inline float getW( ) const; // Set an x, y, z, or w element of a quaternion by index // inline Quat_ref & setElem( int idx, float value ); // Get an x, y, z, or w element of a quaternion by index // inline float getElem( int idx ) const; // Subscripting operator to set or get an element // inline float & operator []( int idx ); // Subscripting operator to get an element // inline float operator []( int idx ) const; // Add two quaternions // inline const Quat_ref operator +( const Quat_ref & quat ) const; // Subtract a quaternion from another quaternion // inline const Quat_ref operator -( const Quat_ref & quat ) const; // Multiply two quaternions // inline const Quat_ref operator *( const Quat_ref & quat ) const; // Multiply a quaternion by a scalar // inline const Quat_ref operator *( float scalar ) const; // Divide a quaternion by a scalar // inline const Quat_ref operator /( float scalar ) const; // Perform compound assignment and addition with a quaternion // inline Quat_ref & operator +=( const Quat_ref & quat ); // Perform compound assignment and subtraction by a quaternion // inline Quat_ref & operator -=( const Quat_ref & quat ); // Perform compound assignment and multiplication by a quaternion // inline Quat_ref & operator *=( const Quat_ref & quat ); // Perform compound assignment and multiplication by a scalar // inline Quat_ref & operator *=( float scalar ); // Perform compound assignment and division by a scalar // inline Quat_ref & operator /=( float scalar ); // Negate all elements of a quaternion // inline const Quat_ref operator -( ) const; // Construct an identity quaternion // static inline const Quat_ref identity( ); // Construct a quaternion to rotate between two unit-length 3-D vectors // NOTE: // The result is unpredictable if unitVec0 and unitVec1 point in opposite directions. // static inline const Quat_ref rotation( const vmVector3 & unitVec0, const vmVector3 & unitVec1 ); // Construct a quaternion to rotate around a unit-length 3-D vector // static inline const Quat_ref rotation( float radians, const vmVector3 & unitVec ); // Construct a quaternion to rotate around the x axis // static inline const Quat_ref rotationX( float radians ); // Construct a quaternion to rotate around the y axis // static inline const Quat_ref rotationY( float radians ); // Construct a quaternion to rotate around the z axis // static inline const Quat_ref rotationZ( float radians ); }; inline Quat_ref::Quat_ref( const Quat_ref & quat ) { mX = quat.mX; mY = quat.mY; mZ = quat.mZ; mW = quat.mW; } inline Quat_ref::Quat_ref( float _x, float _y, float _z, float _w ) { mX = _x; mY = _y; mZ = _z; mW = _w; } inline Quat_ref::Quat_ref( const vmVector3 & xyz, float _w ) { this->setXYZ( xyz ); this->setW( _w ); } inline Quat_ref::Quat_ref( const vmVector4 & vec ) { mX = vec.getX(); mY = vec.getY(); mZ = vec.getZ(); mW = vec.getW(); } inline Quat_ref::Quat_ref( float scalar ) { mX = scalar; mY = scalar; mZ = scalar; mW = scalar; } inline const Quat_ref Quat_ref::identity( ) { return Quat_ref( 0.0f, 0.0f, 0.0f, 1.0f ); } inline void loadXYZW_ref( Quat_ref & quat, const float * fptr ) { quat = Quat_ref( fptr[0], fptr[1], fptr[2], fptr[3] ); } inline void storeXYZW_ref( const Quat_ref & quat, float * fptr ) { fptr[0] = quat.getX(); fptr[1] = quat.getY(); fptr[2] = quat.getZ(); fptr[3] = quat.getW(); } inline Quat_ref & Quat_ref::operator =( const Quat_ref & quat ) { mX = quat.mX; mY = quat.mY; mZ = quat.mZ; mW = quat.mW; return *this; } inline Quat_ref & Quat_ref::setXYZ( const vmVector3 & vec ) { mX = vec.getX(); mY = vec.getY(); mZ = vec.getZ(); return *this; } inline const vmVector3 Quat_ref::getXYZ( ) const { return vmVector3( mX, mY, mZ ); } inline Quat_ref & Quat_ref::setX( float _x ) { mX = _x; return *this; } inline float Quat_ref::getX( ) const { return mX; } inline Quat_ref & Quat_ref::setY( float _y ) { mY = _y; return *this; } inline float Quat_ref::getY( ) const { return mY; } inline Quat_ref & Quat_ref::setZ( float _z ) { mZ = _z; return *this; } inline float Quat_ref::getZ( ) const { return mZ; } inline Quat_ref & Quat_ref::setW( float _w ) { mW = _w; return *this; } inline float Quat_ref::getW( ) const { return mW; } inline Quat_ref & Quat_ref::setElem( int idx, float value ) { *(&mX + idx) = value; return *this; } inline float Quat_ref::getElem( int idx ) const { return *(&mX + idx); } inline float & Quat_ref::operator []( int idx ) { return *(&mX + idx); } inline float Quat_ref::operator []( int idx ) const { return *(&mX + idx); } inline const Quat_ref Quat_ref::operator +( const Quat_ref & quat ) const { return Quat_ref( ( mX + quat.mX ), ( mY + quat.mY ), ( mZ + quat.mZ ), ( mW + quat.mW ) ); } inline const Quat_ref Quat_ref::operator -( const Quat_ref & quat ) const { return Quat_ref( ( mX - quat.mX ), ( mY - quat.mY ), ( mZ - quat.mZ ), ( mW - quat.mW ) ); } inline const Quat_ref Quat_ref::operator *( float scalar ) const { return Quat_ref( ( mX * scalar ), ( mY * scalar ), ( mZ * scalar ), ( mW * scalar ) ); } inline Quat_ref & Quat_ref::operator +=( const Quat_ref & quat ) { *this = *this + quat; return *this; } inline Quat_ref & Quat_ref::operator -=( const Quat_ref & quat ) { *this = *this - quat; return *this; } inline Quat_ref & Quat_ref::operator *=( float scalar ) { *this = *this * scalar; return *this; } inline const Quat_ref Quat_ref::operator /( float scalar ) const { return Quat_ref( ( mX / scalar ), ( mY / scalar ), ( mZ / scalar ), ( mW / scalar ) ); } inline Quat_ref & Quat_ref::operator /=( float scalar ) { *this = *this / scalar; return *this; } inline const Quat_ref Quat_ref::operator -( ) const { return Quat_ref( -mX, -mY, -mZ, -mW ); } inline const Quat_ref operator *( float scalar, const Quat_ref & quat ) { return quat * scalar; } inline float dot( const Quat_ref & quat0, const Quat_ref & quat1 ) { float result; result = ( quat0.getX() * quat1.getX() ); result = ( result + ( quat0.getY() * quat1.getY() ) ); result = ( result + ( quat0.getZ() * quat1.getZ() ) ); result = ( result + ( quat0.getW() * quat1.getW() ) ); return result; } inline const Quat_ref lerp( float t, const Quat_ref & quat0, const Quat_ref & quat1 ) { return ( quat0 + ( ( quat1 - quat0 ) * t ) ); } inline const Quat_ref slerp( float t, const Quat_ref & unitQuat0, const Quat_ref & unitQuat1 ) { Quat_ref start; float recipSinAngle, scale0, scale1, cosAngle, angle; cosAngle = dot( unitQuat0, unitQuat1 ); if ( cosAngle < 0.0f ) { cosAngle = -cosAngle; start = ( -unitQuat0 ); } else { start = unitQuat0; } if ( cosAngle < _VECTORMATH_SLERP_TOL ) { angle = acosf( cosAngle ); recipSinAngle = ( 1.0f / sinf( angle ) ); scale0 = ( sinf( ( ( 1.0f - t ) * angle ) ) * recipSinAngle ); scale1 = ( sinf( ( t * angle ) ) * recipSinAngle ); } else { scale0 = ( 1.0f - t ); scale1 = t; } return ( ( start * scale0 ) + ( unitQuat1 * scale1 ) ); } inline const Quat_ref squad( float t, const Quat_ref & unitQuat0, const Quat_ref & unitQuat1, const Quat_ref & unitQuat2, const Quat_ref & unitQuat3 ) { Quat_ref tmp0, tmp1; tmp0 = slerp( t, unitQuat0, unitQuat3 ); tmp1 = slerp( t, unitQuat1, unitQuat2 ); return slerp( ( ( 2.0f * t ) * ( 1.0f - t ) ), tmp0, tmp1 ); } inline float norm( const Quat_ref & quat ) { float result; result = ( quat.getX() * quat.getX() ); result = ( result + ( quat.getY() * quat.getY() ) ); result = ( result + ( quat.getZ() * quat.getZ() ) ); result = ( result + ( quat.getW() * quat.getW() ) ); return result; } inline float length( const Quat_ref & quat ) { return ::sqrtf( norm( quat ) ); } inline const Quat_ref normalize( const Quat_ref & quat ) { float lenSqr, lenInv; lenSqr = norm( quat ); lenInv = ( 1.0f / sqrtf( lenSqr ) ); return Quat_ref( ( quat.getX() * lenInv ), ( quat.getY() * lenInv ), ( quat.getZ() * lenInv ), ( quat.getW() * lenInv ) ); } inline const Quat_ref Quat_ref::rotation( const vmVector3 & unitVec0, const vmVector3 & unitVec1 ) { float cosHalfAngleX2, recipCosHalfAngleX2; cosHalfAngleX2 = sqrtf( ( 2.0f * ( 1.0f + dot( unitVec0, unitVec1 ) ) ) ); recipCosHalfAngleX2 = ( 1.0f / cosHalfAngleX2 ); return Quat_ref( ( cross( unitVec0, unitVec1 ) * recipCosHalfAngleX2 ), ( cosHalfAngleX2 * 0.5f ) ); } inline const Quat_ref Quat_ref::rotation( float radians, const vmVector3 & unitVec ) { float s, c, angle; angle = ( radians * 0.5f ); s = sinf( angle ); c = cosf( angle ); return Quat_ref( ( unitVec * s ), c ); } inline const Quat_ref Quat_ref::rotationX( float radians ) { float s, c, angle; angle = ( radians * 0.5f ); s = sinf( angle ); c = cosf( angle ); return Quat_ref( s, 0.0f, 0.0f, c ); } inline const Quat_ref Quat_ref::rotationY( float radians ) { float s, c, angle; angle = ( radians * 0.5f ); s = sinf( angle ); c = cosf( angle ); return Quat_ref( 0.0f, s, 0.0f, c ); } inline const Quat_ref Quat_ref::rotationZ( float radians ) { float s, c, angle; angle = ( radians * 0.5f ); s = sinf( angle ); c = cosf( angle ); return Quat_ref( 0.0f, 0.0f, s, c ); } inline const Quat_ref Quat_ref::operator *( const Quat_ref & quat ) const { return Quat_ref( ( ( ( ( mW * quat.mX ) + ( mX * quat.mW ) ) + ( mY * quat.mZ ) ) - ( mZ * quat.mY ) ), ( ( ( ( mW * quat.mY ) + ( mY * quat.mW ) ) + ( mZ * quat.mX ) ) - ( mX * quat.mZ ) ), ( ( ( ( mW * quat.mZ ) + ( mZ * quat.mW ) ) + ( mX * quat.mY ) ) - ( mY * quat.mX ) ), ( ( ( ( mW * quat.mW ) - ( mX * quat.mX ) ) - ( mY * quat.mY ) ) - ( mZ * quat.mZ ) ) ); } inline Quat_ref & Quat_ref::operator *=( const Quat_ref & quat ) { *this = *this * quat; return *this; } inline const vmVector3 rotate( const Quat_ref & quat, const vmVector3 & vec ) { float tmpX, tmpY, tmpZ, tmpW; tmpX = ( ( ( quat.getW() * vec.getX() ) + ( quat.getY() * vec.getZ() ) ) - ( quat.getZ() * vec.getY() ) ); tmpY = ( ( ( quat.getW() * vec.getY() ) + ( quat.getZ() * vec.getX() ) ) - ( quat.getX() * vec.getZ() ) ); tmpZ = ( ( ( quat.getW() * vec.getZ() ) + ( quat.getX() * vec.getY() ) ) - ( quat.getY() * vec.getX() ) ); tmpW = ( ( ( quat.getX() * vec.getX() ) + ( quat.getY() * vec.getY() ) ) + ( quat.getZ() * vec.getZ() ) ); return vmVector3( ( ( ( ( tmpW * quat.getX() ) + ( tmpX * quat.getW() ) ) - ( tmpY * quat.getZ() ) ) + ( tmpZ * quat.getY() ) ), ( ( ( ( tmpW * quat.getY() ) + ( tmpY * quat.getW() ) ) - ( tmpZ * quat.getX() ) ) + ( tmpX * quat.getZ() ) ), ( ( ( ( tmpW * quat.getZ() ) + ( tmpZ * quat.getW() ) ) - ( tmpX * quat.getY() ) ) + ( tmpY * quat.getX() ) ) ); } inline const Quat_ref conj( const Quat_ref & quat ) { return Quat_ref( -quat.getX(), -quat.getY(), -quat.getZ(), quat.getW() ); } inline const Quat_ref select( const Quat_ref & quat0, const Quat_ref & quat1, bool select1 ) { return Quat_ref( ( select1 )? quat1.getX() : quat0.getX(), ( select1 )? quat1.getY() : quat0.getY(), ( select1 )? quat1.getZ() : quat0.getZ(), ( select1 )? quat1.getW() : quat0.getW() ); } #define LOOPCOUNT 1000 #define NUM_CYCLES 10000 #define DATA_SIZE 1024 int Test_quat_aos_neon(void) { return 0; } #endif