You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
9.7 KiB
365 lines
9.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
#include <stdio.h> |
|
#include "convert.h" |
|
#include "ivp_cache_object.hxx" |
|
#include "coordsize.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#if 1 |
|
// game is in inches |
|
vphysics_units_t g_PhysicsUnits = |
|
{ |
|
METERS_PER_INCH, //float unitScaleMeters; // factor that converts game units to meters |
|
1.0f / METERS_PER_INCH, //float unitScaleMetersInv; // factor that converts meters to game units |
|
0.25f, // float globalCollisionTolerance; // global collision tolerance in game units |
|
DIST_EPSILON, // float collisionSweepEpsilon; // collision sweep tests clip at this, must be the same as engine's DIST_EPSILON |
|
1.0f/256.0f, // float collisionSweepIncrementalEpsilon; // near-zero test for incremental steps in collision sweep tests |
|
}; |
|
#else |
|
// game is in meters |
|
vphysics_units_t g_PhysicsUnits = |
|
{ |
|
1.0f, //float unitScaleMeters; // factor that converts game units to meters |
|
1.0f, //float unitScaleMetersInv; // factor that converts meters to game units |
|
0.01f, // float globalCollisionTolerance; // global collision tolerance in game units |
|
0.01f, // float collisionSweepEpsilon; // collision sweep tests clip at this, must be the same as engine's DIST_EPSILON |
|
1e-4f, // float collisionSweepIncrementalEpsilon; // near-zero test for incremental steps in collision sweep tests |
|
}; |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// HL to IVP conversions |
|
//----------------------------------------------------------------------------- |
|
|
|
void ConvertBoxToIVP( const Vector &mins, const Vector &maxs, Vector &outmins, Vector &outmaxs ) |
|
{ |
|
float tmpZ; |
|
|
|
tmpZ = mins.y; |
|
outmins.y = -HL2IVP(mins.z); |
|
outmins.z = HL2IVP(tmpZ); |
|
outmins.x = HL2IVP(mins.x); |
|
tmpZ = maxs.y; |
|
outmaxs.y = -HL2IVP(maxs.z); |
|
outmaxs.z = HL2IVP(tmpZ); |
|
outmaxs.x = HL2IVP(maxs.x); |
|
|
|
tmpZ = outmaxs.y; |
|
outmaxs.y = outmins.y; |
|
outmins.y = tmpZ; |
|
} |
|
|
|
|
|
void ConvertMatrixToIVP( const matrix3x4_t& matrix, IVP_U_Matrix &out ) |
|
{ |
|
Vector forward, left, up; |
|
|
|
forward.x = matrix[0][0]; |
|
forward.y = matrix[1][0]; |
|
forward.z = matrix[2][0]; |
|
|
|
left.x = matrix[0][1]; |
|
left.y = matrix[1][1]; |
|
left.z = matrix[2][1]; |
|
|
|
up.x = matrix[0][2]; |
|
up.y = matrix[1][2]; |
|
up.z = matrix[2][2]; |
|
|
|
up = -up; |
|
|
|
IVP_U_Float_Point ivpForward, ivpLeft, ivpUp; |
|
|
|
ConvertDirectionToIVP( forward, ivpForward ); |
|
ConvertDirectionToIVP( left, ivpLeft ); |
|
ConvertDirectionToIVP( up, ivpUp ); |
|
|
|
out.set_col( IVP_INDEX_X, &ivpForward ); |
|
out.set_col( IVP_INDEX_Z, &ivpLeft ); |
|
out.set_col( IVP_INDEX_Y, &ivpUp ); |
|
|
|
out.vv.k[0] = HL2IVP(matrix[0][3]); |
|
out.vv.k[1] = -HL2IVP(matrix[2][3]); |
|
out.vv.k[2] = HL2IVP(matrix[1][3]); |
|
} |
|
|
|
|
|
void ConvertRotationToIVP( const QAngle& angles, IVP_U_Matrix3 &out ) |
|
{ |
|
Vector forward, right, up; |
|
IVP_U_Float_Point ivpForward, ivpLeft, ivpUp; |
|
|
|
AngleVectors( angles, &forward, &right, &up ); |
|
// now this is left |
|
right = -right; |
|
|
|
up = -up; |
|
|
|
ConvertDirectionToIVP( forward, ivpForward ); |
|
ConvertDirectionToIVP( right, ivpLeft ); |
|
ConvertDirectionToIVP( up, ivpUp ); |
|
|
|
out.set_col( IVP_INDEX_X, &ivpForward ); |
|
out.set_col( IVP_INDEX_Z, &ivpLeft ); |
|
out.set_col( IVP_INDEX_Y, &ivpUp ); |
|
} |
|
|
|
void ConvertRotationToIVP( const QAngle& angles, IVP_U_Quat &out ) |
|
{ |
|
IVP_U_Matrix3 tmp; |
|
ConvertRotationToIVP( angles, tmp ); |
|
out.set_quaternion( &tmp ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// IVP to HL conversions |
|
//----------------------------------------------------------------------------- |
|
|
|
void ConvertMatrixToHL( const IVP_U_Matrix &in, matrix3x4_t& output ) |
|
{ |
|
#if 1 |
|
// copy the row vectors over, swapping z & -y. Also, negate output z |
|
output[0][0] = in.get_elem(0, 0); |
|
output[0][2] = -in.get_elem(0, 1); |
|
output[0][1] = in.get_elem(0, 2); |
|
|
|
output[1][0] = in.get_elem(2, 0); |
|
output[1][2] = -in.get_elem(2, 1); |
|
output[1][1] = in.get_elem(2, 2); |
|
|
|
output[2][0] = -in.get_elem(1, 0); |
|
output[2][2] = in.get_elem(1, 1); |
|
output[2][1] = -in.get_elem(1, 2); |
|
|
|
#else |
|
|
|
// this code is conceptually simpler, but the above is smaller/faster |
|
Vector forward, left, up; |
|
IVP_U_Float_Point out; |
|
|
|
in.get_col( IVP_INDEX_X, &out ); |
|
ConvertDirectionToHL( out, forward ); |
|
in.get_col( IVP_INDEX_Z, &out ); |
|
ConvertDirectionToHL( out, left); |
|
in.get_col( IVP_INDEX_Y, &out ); |
|
ConvertDirectionToHL( out, up ); |
|
up = -up; |
|
|
|
output[0][0] = forward.x; |
|
output[1][0] = forward.y; |
|
output[2][0] = forward.z; |
|
|
|
output[0][1] = left.x; |
|
output[1][1] = left.y; |
|
output[2][1] = left.z; |
|
|
|
output[0][2] = up.x; |
|
output[1][2] = up.y; |
|
output[2][2] = up.z; |
|
#endif |
|
output[0][3] = IVP2HL(in.vv.k[0]); |
|
output[1][3] = IVP2HL(in.vv.k[2]); |
|
output[2][3] = -IVP2HL(in.vv.k[1]); |
|
} |
|
|
|
|
|
void ConvertRotationToHL( const IVP_U_Matrix3 &in, QAngle& angles ) |
|
{ |
|
IVP_U_Float_Point out; |
|
Vector forward, right, up; |
|
|
|
in.get_col( IVP_INDEX_X, &out ); |
|
ConvertDirectionToHL( out, forward ); |
|
in.get_col( IVP_INDEX_Z, &out ); |
|
ConvertDirectionToHL( out, right ); |
|
in.get_col( IVP_INDEX_Y, &out ); |
|
ConvertDirectionToHL( out, up ); |
|
|
|
float xyDist = sqrt( forward[0] * forward[0] + forward[1] * forward[1] ); |
|
|
|
// enough here to get angles? |
|
if ( xyDist > 0.001 ) |
|
{ |
|
// (yaw) y = ATAN( forward.y, forward.x ); -- in our space, forward is the X axis |
|
angles[1] = RAD2DEG( atan2( forward[1], forward[0] ) ); |
|
|
|
// (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) ); |
|
angles[0] = RAD2DEG( atan2( -forward[2], xyDist ) ); |
|
|
|
// (roll) z = ATAN( -right.z, up.z ); |
|
angles[2] = RAD2DEG( atan2( -right[2], up[2] ) ) + 180; |
|
} |
|
else // forward is mostly Z, gimbal lock |
|
{ |
|
// (yaw) y = ATAN( -right.x, right.y ); -- forward is mostly z, so use right for yaw |
|
angles[1] = RAD2DEG( atan2( right[0], -right[1] ) ); |
|
|
|
// (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) ); |
|
angles[0] = RAD2DEG( atan2( -forward[2], xyDist ) ); |
|
|
|
// Assume no roll in this case as one degree of freedom has been lost (i.e. yaw == roll) |
|
angles[2] = 180; |
|
} |
|
} |
|
|
|
|
|
void ConvertRotationToHL( const IVP_U_Quat &in, QAngle& angles ) |
|
{ |
|
IVP_U_Matrix3 tmp; |
|
in.set_matrix( &tmp ); |
|
ConvertRotationToHL( tmp, angles ); |
|
} |
|
|
|
// utiltiy code |
|
void TransformIVPToLocal( IVP_U_Point &point, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
IVP_U_Point tmp = point; |
|
TransformIVPToLocal( tmp, point, pObject, translate ); |
|
} |
|
|
|
void TransformLocalToIVP( IVP_U_Point &point, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
IVP_U_Point tmp = point; |
|
TransformLocalToIVP( tmp, point, pObject, translate ); |
|
} |
|
|
|
|
|
// UNDONE: use IVP_Cache_Object instead? Measure perf differences. |
|
#define USE_CACHE_OBJECT 0 |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: This is ONLY for use by the routines below. It's not reentrant!!! |
|
// No threads or recursive calls! |
|
//----------------------------------------------------------------------------- |
|
#if USE_CACHE_OBJECT |
|
#else |
|
static const IVP_U_Matrix *GetTmpObjectMatrix( IVP_Real_Object *pObject ) |
|
{ |
|
static IVP_U_Matrix coreShiftMatrix; |
|
const IVP_U_Matrix *pOut = pObject->get_core()->get_m_world_f_core_PSI(); |
|
|
|
if ( !pObject->flags.shift_core_f_object_is_zero ) |
|
{ |
|
coreShiftMatrix.set_matrix( pOut ); |
|
coreShiftMatrix.vmult4( pObject->get_shift_core_f_object(), &coreShiftMatrix.vv ); |
|
return &coreShiftMatrix; |
|
} |
|
return pOut; |
|
} |
|
#endif |
|
|
|
void TransformIVPToLocal( const IVP_U_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
#if USE_CACHE_OBJECT |
|
IVP_Cache_Object *cache = pObject->get_cache_object_no_lock(); |
|
|
|
if ( translate ) |
|
{ |
|
cache->transform_position_to_object_coords( &pointIn, &pointOut ); |
|
} |
|
else |
|
{ |
|
cache->transform_vector_to_object_coords( &pointIn, &pointOut ); |
|
} |
|
#else |
|
const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject ); |
|
if ( translate ) |
|
{ |
|
pMatrix->inline_vimult4( &pointIn, &pointOut ); |
|
} |
|
else |
|
{ |
|
pMatrix->inline_vimult3( &pointIn, &pointOut ); |
|
} |
|
#endif |
|
} |
|
|
|
|
|
void TransformLocalToIVP( const IVP_U_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
#if USE_CACHE_OBJECT |
|
IVP_Cache_Object *cache = pObject->get_cache_object_no_lock(); |
|
|
|
if ( translate ) |
|
{ |
|
IVP_U_Float_Point floatPointIn; |
|
floatPointIn.set( &pointIn ); |
|
cache->transform_position_to_world_coords( &floatPointIn, &pointOut ); |
|
} |
|
else |
|
{ |
|
cache->transform_vector_to_world_coords( &pointIn, &pointOut ); |
|
} |
|
#else |
|
const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject ); |
|
|
|
if ( translate ) |
|
{ |
|
pMatrix->inline_vmult4( &pointIn, &pointOut ); |
|
} |
|
else |
|
{ |
|
pMatrix->inline_vmult3( &pointIn, &pointOut ); |
|
} |
|
#endif |
|
} |
|
|
|
void TransformLocalToIVP( const IVP_U_Float_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
#if USE_CACHE_OBJECT |
|
IVP_Cache_Object *cache = pObject->get_cache_object_no_lock(); |
|
|
|
if ( translate ) |
|
{ |
|
cache->transform_position_to_world_coords( &pointIn, &pointOut ); |
|
} |
|
else |
|
{ |
|
IVP_U_Point doublePointIn; |
|
doublePointIn.set( &pointIn ); |
|
cache->transform_vector_to_world_coords( &doublePointIn, &pointOut ); |
|
} |
|
#else |
|
const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject ); |
|
IVP_U_Float_Point out; |
|
|
|
if ( translate ) |
|
{ |
|
pMatrix->inline_vmult4( &pointIn, &out ); |
|
} |
|
else |
|
{ |
|
pMatrix->inline_vmult3( &pointIn, &out ); |
|
} |
|
pointOut.set( &out ); |
|
#endif |
|
} |
|
|
|
void TransformLocalToIVP( const IVP_U_Float_Point &pointIn, IVP_U_Float_Point &pointOut, IVP_Real_Object *pObject, bool translate ) |
|
{ |
|
IVP_U_Point tmpOut; |
|
TransformLocalToIVP( pointIn, tmpOut, pObject, translate ); |
|
pointOut.set( &tmpOut ); |
|
} |
|
|
|
static char axisMap[] = {0,2,1,3}; |
|
|
|
int ConvertCoordinateAxisToIVP( int axisIndex ) |
|
{ |
|
return axisIndex < 4 ? axisMap[axisIndex] : 0; |
|
} |
|
|
|
int ConvertCoordinateAxisToHL( int axisIndex ) |
|
{ |
|
return axisIndex < 4 ? axisMap[axisIndex] : 0; |
|
} |
|
|
|
|