diff --git a/apps/renderer.c b/apps/renderer.c index caaacac57bcc9b3685405b891cd8bc1bdc7a97c6..46f263303cd5435f76d07dcd4d46a833683640ec 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -946,7 +946,7 @@ int main( if ( !args.quietModeEnabled ) { - fprintf( stdout, "\n------ Running the rondoror ------\n\n" ); + fprintf( stdout, "\n------ Running the renderer ------\n\n" ); fprintf( stdout, "Frames processed: " ); } else diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c index 5fe33986874a8c34f3a59aef182784b1f43bd996..d63decba09c291bde9352fc35beed4f0d172e90b 100644 --- a/lib_rend/ivas_orient_trk.c +++ b/lib_rend/ivas_orient_trk.c @@ -30,6 +30,7 @@ *******************************************************************************************************/ +#include "common_api_types.h" #include #include "options.h" #include "ivas_prot.h" @@ -508,7 +509,17 @@ ivas_error ivas_orient_trk_SetReferenceRotation( { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - pOTR->refRot = refRot; + + /* check for Euler angle signaling */ + if ( refRot.w == -3.0f ) + { + Euler2Quat(deg2rad( refRot.x ), deg2rad( refRot.y ), deg2rad( refRot.z ), &pOTR->refRot ); + } + else + { + pOTR->refRot = refRot; + } + return IVAS_ERR_OK; } @@ -654,48 +665,57 @@ ivas_error ivas_orient_trk_Process( float alpha = pOTR->alpha; float ang; ivas_error result; -#ifdef OTR_REFERENCE_VECTOR_TRACKING - IVAS_QUATERNION refRot_absRot_product; -#endif /* OTR_REFERENCE_VECTOR_TRACKING */ + IVAS_QUATERNION absQuat, trkQuat; + IVAS_QUATERNION trkEuler; if ( pOTR == NULL || pTrkRot == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } + /* check for Euler angle signaling */ + if ( pAbsRot->w == -3.0f ) + { + Euler2Quat(deg2rad( pAbsRot->x ), deg2rad( pAbsRot->y ), deg2rad( pAbsRot->z ), &absQuat); + } + else + { + absQuat = *pAbsRot; + } + result = IVAS_ERR_OK; switch ( pOTR->trackingType ) { case OTR_TRACKING_NONE: - *pTrkRot = *pAbsRot; + trkQuat = absQuat; break; case OTR_TRACKING_REF_ORIENT: /* Reset average orientation */ - pOTR->absAvgRot = *pAbsRot; + pOTR->absAvgRot = absQuat; /* Reset adaptation filter - start adaptation at center rate */ pOTR->alpha = sinf( 2.0f * EVS_PI * pOTR->centerAdaptationRate / updateRate ); /* Compute relative orientation = (absolute orientation) - (reference orientation) */ - QuaternionInverse( pOTR->refRot, pTrkRot ); - QuaternionProduct( *pTrkRot, *pAbsRot, pTrkRot ); + QuaternionInverse( pOTR->refRot, &trkQuat ); + QuaternionProduct( trkQuat, absQuat, &trkQuat ); break; case OTR_TRACKING_AVG_ORIENT: /* Compute average (low-pass filtered) absolute orientation */ - QuaternionSlerp( pOTR->absAvgRot, *pAbsRot, alpha, &pOTR->absAvgRot ); + QuaternionSlerp( pOTR->absAvgRot, absQuat, alpha, &pOTR->absAvgRot ); /* Compute relative orientation = (absolute orientation) - (average absolute orientation) */ - QuaternionInverse( pOTR->absAvgRot, pTrkRot ); - QuaternionProduct( *pTrkRot, *pAbsRot, pTrkRot ); + QuaternionInverse( pOTR->absAvgRot, &trkQuat ); + QuaternionProduct( trkQuat, absQuat, &trkQuat ); /* Adapt LPF constant based on orientation excursion relative to current mean: - low cutoff (slow adaptation) for small excursions (around center) - high cutoff (fast adaptation) for large excursions (off-center) */ - ang = QuaternionAngle( *pAbsRot, *pTrkRot ); + ang = QuaternionAngle( absQuat, trkQuat ); normalizedOrientation = ang * ang; relativeOrientationRate = sqrtf( normalizedOrientation ) / pOTR->adaptationAngle; @@ -724,12 +744,7 @@ ivas_error ivas_orient_trk_Process( case OTR_TRACKING_REF_VEC_LEV: { /* This processing step of the OTR_TRACKING_REF_VEC/OTR_TRACKING_REF_VEC_LEVEL is identical */ - QuaternionProduct( pOTR->refRot, *pAbsRot, &refRot_absRot_product ); - - pTrkRot->w = refRot_absRot_product.w; - pTrkRot->x = refRot_absRot_product.x; - pTrkRot->y = refRot_absRot_product.y; - pTrkRot->z = refRot_absRot_product.z; + QuaternionProduct( pOTR->refRot, absQuat, &trkQuat ); break; } #endif /* OTR_REFERENCE_VECTOR_TRACKING */ @@ -740,7 +755,21 @@ ivas_error ivas_orient_trk_Process( if ( result == IVAS_ERR_OK ) { - pOTR->trkRot = *pTrkRot; + pOTR->trkRot = trkQuat; + + if ( pAbsRot->w == -3.0f ) + { + Quat2Euler( trkQuat, &trkEuler.z, &trkEuler.y, &trkEuler.x ); + trkEuler.x = rad2deg( trkEuler.x ); + trkEuler.y = rad2deg( trkEuler.y ); + trkEuler.z = rad2deg( trkEuler.z ); + trkEuler.w = -3.0f; + *pTrkRot = trkEuler; + } + else + { + *pTrkRot = trkQuat; + } } return result; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 95d3338b98e9af70bbf2429543949289a80ea93f..49dadd271d9161f28c1d039512a93bb0f083a029 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -806,12 +806,25 @@ void ivas_headTrack_close( #endif void Quat2Euler( - const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw (z) */ + float *pitch, /* o : pitch (y) */ + float *roll /* o : roll (x) */ +); + +#ifdef FIX_I109_ORIENTATION_TRACKING +void Euler2Quat( + const float roll, /* i : roll (x) */ + const float pitch, /* i : pitch (y) */ + const float yaw, /* i : yaw (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ ); +float deg2rad( float degrees ); + +float rad2deg( float radians ); +#endif + void QuatToRotMat( const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 90354497a005af5d57b2b815bedfab91795f9da2..409626de0bf3a8d6eae98d4476ad1a773d75d8d0 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -30,6 +30,7 @@ *******************************************************************************************************/ +#include "ivas_cnst.h" #include #include #include "options.h" @@ -127,7 +128,11 @@ void QuatToRotMat( * Euler angles instead of quaternions. In this case, all the w values must * be set to -3.0 in the trajectory file to signal switching to Euler angles. * The x,y, and z components of the quaternion are then interpreted as +#ifdef FIX_I109_ORIENTATION_TRACKING * yaw-pitch-roll. +#else // see below: "Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention" + * roll-pitch-yaw. +#endif */ if ( quat.w != -3.0 ) { @@ -176,25 +181,30 @@ void QuatToRotMat( return; } -#ifndef FIX_I109_ORIENTATION_TRACKING /*------------------------------------------------------------------------- * Quat2Euler() * - * Quaternion handling: calculate corresponding Euler angles + * Quaternion handling: calculate corresponding Euler angles in radians *------------------------------------------------------------------------*/ void Quat2Euler( const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ + float *yaw, /* o : yaw (z) */ + float *pitch, /* o : pitch (y) */ + float *roll /* o : roll (x) */ ) { if ( quat.w != -3.0 ) { +#ifdef FIX_I109_ORIENTATION_TRACKING + *roll = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); + *pitch = asinf( 2 * ( quat.w * quat.y - quat.z * quat.x ) ); + *yaw = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); +#else // bug: x and z swapped *yaw = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); *pitch = asinf( 2 * ( quat.w * quat.y - quat.z * quat.x ) ); *roll = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); +#endif } else { @@ -204,13 +214,63 @@ void Quat2Euler( * pitch: rotate scene in the median plane, increase elevation with positive values * roll: rotate scene from the right ear to the top */ - *yaw = quat.z; + *yaw = quat.z; *pitch = quat.y; - *roll = quat.x; + *roll = quat.x; } return; } + +#ifdef FIX_I109_ORIENTATION_TRACKING +/*------------------------------------------------------------------------- + * Euler2Quat() + * + * Calculate corresponding Quaternion from Euler angles in radians + *------------------------------------------------------------------------*/ + +void Euler2Quat( + const float roll, /* i : roll (x) */ + const float pitch, /* i : pitch (y) */ + const float yaw, /* i : yaw (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +) +{ + float cr = cosf( roll * 0.5f ); + float sr = sinf( roll * 0.5f ); + float cp = cosf( pitch * 0.5f ); + float sp = sinf( pitch * 0.5f ); + float cy = cosf( yaw * 0.5f ); + float sy = sinf( yaw * 0.5f ); + + quat->w = cr * cp * cy + sr * sp * sy; + quat->x = sr * cp * cy - cr * sp * sy; + quat->y = cr * sp * cy + sr * cp * sy; + quat->z = cr * cp * sy - sr * sp * cy; + + return; +} + +/*------------------------------------------------------------------------- + * rad2deg() + * + * Return angle in radians from degrees + *------------------------------------------------------------------------*/ +float deg2rad( float degrees ) +{ + return PI_OVER_180 * degrees; +} + +/*------------------------------------------------------------------------- + * deg2rad() + * + * Return angle in degrees from radians + *------------------------------------------------------------------------*/ +float rad2deg( float radians ) +{ + return _180_OVER_PI * radians; +} + #endif