Skip to content

Commit

Permalink
Merge pull request #29 from floorman/QuaternionSlerpCosFFix
Browse files Browse the repository at this point in the history
Fixing an issue where >= 1.0f cosTheta values produced NaN results
  • Loading branch information
dangmoody authored Jan 18, 2020
2 parents 1034da3 + 3dce4dc commit a88d281
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
27 changes: 24 additions & 3 deletions code/generator/gen_funcs_quaternion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ void Gen_QuaternionLerp( const genLanguage_t language, const genType_t type, str
const char* typeString = Gen_GetTypeString( type );

const char* parmAccessStr = GEN_TYPE_ACCESS_OPERATORS[language];

char oneStr[GEN_STRING_LENGTH_NUMERIC_LITERAL];
Gen_GetNumericLiteral( type, 1, oneStr, 1 );

char fullTypeName[GEN_STRING_LENGTH_TYPE_NAME];
Gen_GetFullTypeName( type, 1, 4, fullTypeName );
Expand All @@ -417,7 +420,7 @@ void Gen_QuaternionLerp( const genLanguage_t language, const genType_t type, str
String_Append( sbImpl, "{\n" );

String_Appendf( sbImpl, "\t%s quat;\n", fullTypeName );
String_Appendf( sbImpl, "\t%s t = 1 - percent;\n", typeString );
String_Appendf( sbImpl, "\t%s t = %s - percent;\n", typeString, oneStr );

for ( u32 i = 0; i < GEN_COMPONENT_COUNT_MAX; i++ ) {
const char componentName = GEN_COMPONENT_NAMES_VECTOR[i];
Expand All @@ -438,6 +441,9 @@ void Gen_QuaternionSlerp( const genLanguage_t language, const genType_t type, st
const char* typeString = Gen_GetTypeString(type);

const char* parmAccessStr = GEN_TYPE_ACCESS_OPERATORS[language];

char oneStr[GEN_STRING_LENGTH_NUMERIC_LITERAL];
Gen_GetNumericLiteral( type, 1, oneStr, 1 );

char fullTypeName[GEN_STRING_LENGTH_TYPE_NAME];
Gen_GetFullTypeName( type, 1, 4, fullTypeName );
Expand All @@ -461,7 +467,7 @@ void Gen_QuaternionSlerp( const genLanguage_t language, const genType_t type, st
String_Append( sbImpl, "{\n" );

String_Appendf( sbImpl, "\t%s quat;\n", fullTypeName );
String_Appendf( sbImpl, "\t%s t = 1 - percent;\n", typeString );
String_Appendf( sbImpl, "\t%s t = %s - percent;\n", typeString, oneStr );

String_Appendf( sbImpl, "\t%s cosTheta = ", typeString );

Expand All @@ -477,8 +483,23 @@ void Gen_QuaternionSlerp( const genLanguage_t language, const genType_t type, st
}

String_Append( sbImpl, ";\n" );
String_Appendf( sbImpl, "\tif ( cosTheta >= %s )\n", oneStr );
String_Append( sbImpl, "\t{\n" );
String_Appendf( sbImpl, "\t\treturn HLML_CONSTRUCT( %s ) { ", fullTypeName );
for (u32 i = 0; i < numComponents; i++) {
const char componentName = GEN_COMPONENT_NAMES_VECTOR[i];

String_Appendf( sbImpl, "lhs%s%c", parmAccessStr, componentName );

if (i != numComponents - 1) {
String_Append( sbImpl, ", " );
}
}
String_Append( sbImpl, " };\n" );
String_Append( sbImpl, "\t}\n" );

String_Appendf( sbImpl, "\t%s theta = %s( cosTheta );\n", typeString, Gen_GetFuncNameAcos( type ) );
String_Appendf( sbImpl, "\t%s sn = %s( 1 - cosTheta * cosTheta );\n", typeString, Gen_GetFuncNameSqrt( type ) );
String_Appendf( sbImpl, "\t%s sn = %s( %s - cosTheta * cosTheta );\n", typeString, Gen_GetFuncNameSqrt( type ), oneStr );

String_Appendf( sbImpl, "\t%s Wa = %s( t * theta ) / sn;\n", typeString, sinFunc );
String_Appendf( sbImpl, "\t%s Wb = %s( percent * theta ) / sn;\n", typeString, sinFunc );
Expand Down
20 changes: 14 additions & 6 deletions code/out/c/hlml_functions_quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ inline float3 float4_quaternion_rotate( const float3* vect, const float angle, c
inline float4 float4_quaternion_lerp( const float4* lhs, const float4* rhs, const float percent )
{
float4 quat;
float t = 1 - percent;
float t = 1.0f - percent;
quat.x = t * lhs->x + percent * rhs->x;
quat.y = t * lhs->y + percent * rhs->y;
quat.z = t * lhs->z + percent * rhs->z;
Expand All @@ -257,10 +257,14 @@ inline float4 float4_quaternion_lerp( const float4* lhs, const float4* rhs, cons
inline float4 float4_quaternion_slerp( const float4* lhs, const float4* rhs, const float percent )
{
float4 quat;
float t = 1 - percent;
float t = 1.0f - percent;
float cosTheta = ( lhs->x * rhs->x ) + ( lhs->y * rhs->y ) + ( lhs->z * rhs->z ) + ( lhs->w * rhs->w );
if ( cosTheta >= 1.0f )
{
return HLML_CONSTRUCT( float4 ) { lhs->x, lhs->y, lhs->z, lhs->w };
}
float theta = acosf( cosTheta );
float sn = sqrtf( 1 - cosTheta * cosTheta );
float sn = sqrtf( 1.0f - cosTheta * cosTheta );
float Wa = sinf( t * theta ) / sn;
float Wb = sinf( percent * theta ) / sn;
quat.x = Wa * rhs->x + Wb * lhs->x;
Expand Down Expand Up @@ -347,7 +351,7 @@ inline double3 double4_quaternion_rotate( const double3* vect, const double angl
inline double4 double4_quaternion_lerp( const double4* lhs, const double4* rhs, const double percent )
{
double4 quat;
double t = 1 - percent;
double t = 1.0 - percent;
quat.x = t * lhs->x + percent * rhs->x;
quat.y = t * lhs->y + percent * rhs->y;
quat.z = t * lhs->z + percent * rhs->z;
Expand All @@ -358,10 +362,14 @@ inline double4 double4_quaternion_lerp( const double4* lhs, const double4* rhs,
inline double4 double4_quaternion_slerp( const double4* lhs, const double4* rhs, const double percent )
{
double4 quat;
double t = 1 - percent;
double t = 1.0 - percent;
double cosTheta = ( lhs->x * rhs->x ) + ( lhs->y * rhs->y ) + ( lhs->z * rhs->z ) + ( lhs->w * rhs->w );
if ( cosTheta >= 1.0 )
{
return HLML_CONSTRUCT( double4 ) { lhs->x, lhs->y, lhs->z, lhs->w };
}
double theta = acos( cosTheta );
double sn = sqrt( 1 - cosTheta * cosTheta );
double sn = sqrt( 1.0 - cosTheta * cosTheta );
double Wa = sin( t * theta ) / sn;
double Wb = sin( percent * theta ) / sn;
quat.x = Wa * rhs->x + Wb * lhs->x;
Expand Down
20 changes: 14 additions & 6 deletions code/out/cpp/hlml_functions_quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ inline float3 quaternion_rotate( const float3& vect, const float angle, const fl
inline float4 quaternion_lerp( const float4& lhs, const float4& rhs, const float percent )
{
float4 quat;
float t = 1 - percent;
float t = 1.0f - percent;
quat.x = t * lhs.x + percent * rhs.x;
quat.y = t * lhs.y + percent * rhs.y;
quat.z = t * lhs.z + percent * rhs.z;
Expand All @@ -254,10 +254,14 @@ inline float4 quaternion_lerp( const float4& lhs, const float4& rhs, const float
inline float4 quaternion_slerp( const float4& lhs, const float4& rhs, const float percent )
{
float4 quat;
float t = 1 - percent;
float t = 1.0f - percent;
float cosTheta = ( lhs.x * rhs.x ) + ( lhs.y * rhs.y ) + ( lhs.z * rhs.z ) + ( lhs.w * rhs.w );
if ( cosTheta >= 1.0f )
{
return HLML_CONSTRUCT( float4 ) { lhs.x, lhs.y, lhs.z, lhs.w };
}
float theta = acosf( cosTheta );
float sn = sqrtf( 1 - cosTheta * cosTheta );
float sn = sqrtf( 1.0f - cosTheta * cosTheta );
float Wa = sinf( t * theta ) / sn;
float Wb = sinf( percent * theta ) / sn;
quat.x = Wa * rhs.x + Wb * lhs.x;
Expand Down Expand Up @@ -341,7 +345,7 @@ inline double3 quaternion_rotate( const double3& vect, const double angle, const
inline double4 quaternion_lerp( const double4& lhs, const double4& rhs, const double percent )
{
double4 quat;
double t = 1 - percent;
double t = 1.0 - percent;
quat.x = t * lhs.x + percent * rhs.x;
quat.y = t * lhs.y + percent * rhs.y;
quat.z = t * lhs.z + percent * rhs.z;
Expand All @@ -352,10 +356,14 @@ inline double4 quaternion_lerp( const double4& lhs, const double4& rhs, const do
inline double4 quaternion_slerp( const double4& lhs, const double4& rhs, const double percent )
{
double4 quat;
double t = 1 - percent;
double t = 1.0 - percent;
double cosTheta = ( lhs.x * rhs.x ) + ( lhs.y * rhs.y ) + ( lhs.z * rhs.z ) + ( lhs.w * rhs.w );
if ( cosTheta >= 1.0 )
{
return HLML_CONSTRUCT( double4 ) { lhs.x, lhs.y, lhs.z, lhs.w };
}
double theta = acos( cosTheta );
double sn = sqrt( 1 - cosTheta * cosTheta );
double sn = sqrt( 1.0 - cosTheta * cosTheta );
double Wa = sin( t * theta ) / sn;
double Wb = sin( percent * theta ) / sn;
quat.x = Wa * rhs.x + Wb * lhs.x;
Expand Down

0 comments on commit a88d281

Please sign in to comment.