Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include <stdio.h>
  9. #include "convert.h"
  10. #include "ivp_cache_object.hxx"
  11. #include "coordsize.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. #if 1
  15. // game is in inches
  16. vphysics_units_t g_PhysicsUnits =
  17. {
  18. METERS_PER_INCH, //float unitScaleMeters; // factor that converts game units to meters
  19. 1.0f / METERS_PER_INCH, //float unitScaleMetersInv; // factor that converts meters to game units
  20. 0.25f, // float globalCollisionTolerance; // global collision tolerance in game units
  21. DIST_EPSILON, // float collisionSweepEpsilon; // collision sweep tests clip at this, must be the same as engine's DIST_EPSILON
  22. 1.0f/256.0f, // float collisionSweepIncrementalEpsilon; // near-zero test for incremental steps in collision sweep tests
  23. };
  24. #else
  25. // game is in meters
  26. vphysics_units_t g_PhysicsUnits =
  27. {
  28. 1.0f, //float unitScaleMeters; // factor that converts game units to meters
  29. 1.0f, //float unitScaleMetersInv; // factor that converts meters to game units
  30. 0.01f, // float globalCollisionTolerance; // global collision tolerance in game units
  31. 0.01f, // float collisionSweepEpsilon; // collision sweep tests clip at this, must be the same as engine's DIST_EPSILON
  32. 1e-4f, // float collisionSweepIncrementalEpsilon; // near-zero test for incremental steps in collision sweep tests
  33. };
  34. #endif
  35. //-----------------------------------------------------------------------------
  36. // HL to IVP conversions
  37. //-----------------------------------------------------------------------------
  38. void ConvertBoxToIVP( const Vector &mins, const Vector &maxs, Vector &outmins, Vector &outmaxs )
  39. {
  40. float tmpZ;
  41. tmpZ = mins.y;
  42. outmins.y = -HL2IVP(mins.z);
  43. outmins.z = HL2IVP(tmpZ);
  44. outmins.x = HL2IVP(mins.x);
  45. tmpZ = maxs.y;
  46. outmaxs.y = -HL2IVP(maxs.z);
  47. outmaxs.z = HL2IVP(tmpZ);
  48. outmaxs.x = HL2IVP(maxs.x);
  49. tmpZ = outmaxs.y;
  50. outmaxs.y = outmins.y;
  51. outmins.y = tmpZ;
  52. }
  53. void ConvertMatrixToIVP( const matrix3x4_t& matrix, IVP_U_Matrix &out )
  54. {
  55. Vector forward, left, up;
  56. forward.x = matrix[0][0];
  57. forward.y = matrix[1][0];
  58. forward.z = matrix[2][0];
  59. left.x = matrix[0][1];
  60. left.y = matrix[1][1];
  61. left.z = matrix[2][1];
  62. up.x = matrix[0][2];
  63. up.y = matrix[1][2];
  64. up.z = matrix[2][2];
  65. up = -up;
  66. IVP_U_Float_Point ivpForward, ivpLeft, ivpUp;
  67. ConvertDirectionToIVP( forward, ivpForward );
  68. ConvertDirectionToIVP( left, ivpLeft );
  69. ConvertDirectionToIVP( up, ivpUp );
  70. out.set_col( IVP_INDEX_X, &ivpForward );
  71. out.set_col( IVP_INDEX_Z, &ivpLeft );
  72. out.set_col( IVP_INDEX_Y, &ivpUp );
  73. out.vv.k[0] = HL2IVP(matrix[0][3]);
  74. out.vv.k[1] = -HL2IVP(matrix[2][3]);
  75. out.vv.k[2] = HL2IVP(matrix[1][3]);
  76. }
  77. void ConvertRotationToIVP( const QAngle& angles, IVP_U_Matrix3 &out )
  78. {
  79. Vector forward, right, up;
  80. IVP_U_Float_Point ivpForward, ivpLeft, ivpUp;
  81. AngleVectors( angles, &forward, &right, &up );
  82. // now this is left
  83. right = -right;
  84. up = -up;
  85. ConvertDirectionToIVP( forward, ivpForward );
  86. ConvertDirectionToIVP( right, ivpLeft );
  87. ConvertDirectionToIVP( up, ivpUp );
  88. out.set_col( IVP_INDEX_X, &ivpForward );
  89. out.set_col( IVP_INDEX_Z, &ivpLeft );
  90. out.set_col( IVP_INDEX_Y, &ivpUp );
  91. }
  92. void ConvertRotationToIVP( const QAngle& angles, IVP_U_Quat &out )
  93. {
  94. IVP_U_Matrix3 tmp;
  95. ConvertRotationToIVP( angles, tmp );
  96. out.set_quaternion( &tmp );
  97. }
  98. //-----------------------------------------------------------------------------
  99. // IVP to HL conversions
  100. //-----------------------------------------------------------------------------
  101. void ConvertMatrixToHL( const IVP_U_Matrix &in, matrix3x4_t& output )
  102. {
  103. #if 1
  104. // copy the row vectors over, swapping z & -y. Also, negate output z
  105. output[0][0] = in.get_elem(0, 0);
  106. output[0][2] = -in.get_elem(0, 1);
  107. output[0][1] = in.get_elem(0, 2);
  108. output[1][0] = in.get_elem(2, 0);
  109. output[1][2] = -in.get_elem(2, 1);
  110. output[1][1] = in.get_elem(2, 2);
  111. output[2][0] = -in.get_elem(1, 0);
  112. output[2][2] = in.get_elem(1, 1);
  113. output[2][1] = -in.get_elem(1, 2);
  114. #else
  115. // this code is conceptually simpler, but the above is smaller/faster
  116. Vector forward, left, up;
  117. IVP_U_Float_Point out;
  118. in.get_col( IVP_INDEX_X, &out );
  119. ConvertDirectionToHL( out, forward );
  120. in.get_col( IVP_INDEX_Z, &out );
  121. ConvertDirectionToHL( out, left);
  122. in.get_col( IVP_INDEX_Y, &out );
  123. ConvertDirectionToHL( out, up );
  124. up = -up;
  125. output[0][0] = forward.x;
  126. output[1][0] = forward.y;
  127. output[2][0] = forward.z;
  128. output[0][1] = left.x;
  129. output[1][1] = left.y;
  130. output[2][1] = left.z;
  131. output[0][2] = up.x;
  132. output[1][2] = up.y;
  133. output[2][2] = up.z;
  134. #endif
  135. output[0][3] = IVP2HL(in.vv.k[0]);
  136. output[1][3] = IVP2HL(in.vv.k[2]);
  137. output[2][3] = -IVP2HL(in.vv.k[1]);
  138. }
  139. void ConvertRotationToHL( const IVP_U_Matrix3 &in, QAngle& angles )
  140. {
  141. IVP_U_Float_Point out;
  142. Vector forward, right, up;
  143. in.get_col( IVP_INDEX_X, &out );
  144. ConvertDirectionToHL( out, forward );
  145. in.get_col( IVP_INDEX_Z, &out );
  146. ConvertDirectionToHL( out, right );
  147. in.get_col( IVP_INDEX_Y, &out );
  148. ConvertDirectionToHL( out, up );
  149. float xyDist = sqrt( forward[0] * forward[0] + forward[1] * forward[1] );
  150. // enough here to get angles?
  151. if ( xyDist > 0.001 )
  152. {
  153. // (yaw) y = ATAN( forward.y, forward.x ); -- in our space, forward is the X axis
  154. angles[1] = RAD2DEG( atan2( forward[1], forward[0] ) );
  155. // (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) );
  156. angles[0] = RAD2DEG( atan2( -forward[2], xyDist ) );
  157. // (roll) z = ATAN( -right.z, up.z );
  158. angles[2] = RAD2DEG( atan2( -right[2], up[2] ) ) + 180;
  159. }
  160. else // forward is mostly Z, gimbal lock
  161. {
  162. // (yaw) y = ATAN( -right.x, right.y ); -- forward is mostly z, so use right for yaw
  163. angles[1] = RAD2DEG( atan2( right[0], -right[1] ) );
  164. // (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) );
  165. angles[0] = RAD2DEG( atan2( -forward[2], xyDist ) );
  166. // Assume no roll in this case as one degree of freedom has been lost (i.e. yaw == roll)
  167. angles[2] = 180;
  168. }
  169. }
  170. void ConvertRotationToHL( const IVP_U_Quat &in, QAngle& angles )
  171. {
  172. IVP_U_Matrix3 tmp;
  173. in.set_matrix( &tmp );
  174. ConvertRotationToHL( tmp, angles );
  175. }
  176. // utiltiy code
  177. void TransformIVPToLocal( IVP_U_Point &point, IVP_Real_Object *pObject, bool translate )
  178. {
  179. IVP_U_Point tmp = point;
  180. TransformIVPToLocal( tmp, point, pObject, translate );
  181. }
  182. void TransformLocalToIVP( IVP_U_Point &point, IVP_Real_Object *pObject, bool translate )
  183. {
  184. IVP_U_Point tmp = point;
  185. TransformLocalToIVP( tmp, point, pObject, translate );
  186. }
  187. // UNDONE: use IVP_Cache_Object instead? Measure perf differences.
  188. #define USE_CACHE_OBJECT 0
  189. //-----------------------------------------------------------------------------
  190. // Purpose: This is ONLY for use by the routines below. It's not reentrant!!!
  191. // No threads or recursive calls!
  192. //-----------------------------------------------------------------------------
  193. #if USE_CACHE_OBJECT
  194. #else
  195. static const IVP_U_Matrix *GetTmpObjectMatrix( IVP_Real_Object *pObject )
  196. {
  197. static IVP_U_Matrix coreShiftMatrix;
  198. const IVP_U_Matrix *pOut = pObject->get_core()->get_m_world_f_core_PSI();
  199. if ( !pObject->flags.shift_core_f_object_is_zero )
  200. {
  201. coreShiftMatrix.set_matrix( pOut );
  202. coreShiftMatrix.vmult4( pObject->get_shift_core_f_object(), &coreShiftMatrix.vv );
  203. return &coreShiftMatrix;
  204. }
  205. return pOut;
  206. }
  207. #endif
  208. void TransformIVPToLocal( const IVP_U_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate )
  209. {
  210. #if USE_CACHE_OBJECT
  211. IVP_Cache_Object *cache = pObject->get_cache_object_no_lock();
  212. if ( translate )
  213. {
  214. cache->transform_position_to_object_coords( &pointIn, &pointOut );
  215. }
  216. else
  217. {
  218. cache->transform_vector_to_object_coords( &pointIn, &pointOut );
  219. }
  220. #else
  221. const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject );
  222. if ( translate )
  223. {
  224. pMatrix->inline_vimult4( &pointIn, &pointOut );
  225. }
  226. else
  227. {
  228. pMatrix->inline_vimult3( &pointIn, &pointOut );
  229. }
  230. #endif
  231. }
  232. void TransformLocalToIVP( const IVP_U_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate )
  233. {
  234. #if USE_CACHE_OBJECT
  235. IVP_Cache_Object *cache = pObject->get_cache_object_no_lock();
  236. if ( translate )
  237. {
  238. IVP_U_Float_Point floatPointIn;
  239. floatPointIn.set( &pointIn );
  240. cache->transform_position_to_world_coords( &floatPointIn, &pointOut );
  241. }
  242. else
  243. {
  244. cache->transform_vector_to_world_coords( &pointIn, &pointOut );
  245. }
  246. #else
  247. const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject );
  248. if ( translate )
  249. {
  250. pMatrix->inline_vmult4( &pointIn, &pointOut );
  251. }
  252. else
  253. {
  254. pMatrix->inline_vmult3( &pointIn, &pointOut );
  255. }
  256. #endif
  257. }
  258. void TransformLocalToIVP( const IVP_U_Float_Point &pointIn, IVP_U_Point &pointOut, IVP_Real_Object *pObject, bool translate )
  259. {
  260. #if USE_CACHE_OBJECT
  261. IVP_Cache_Object *cache = pObject->get_cache_object_no_lock();
  262. if ( translate )
  263. {
  264. cache->transform_position_to_world_coords( &pointIn, &pointOut );
  265. }
  266. else
  267. {
  268. IVP_U_Point doublePointIn;
  269. doublePointIn.set( &pointIn );
  270. cache->transform_vector_to_world_coords( &doublePointIn, &pointOut );
  271. }
  272. #else
  273. const IVP_U_Matrix *pMatrix = GetTmpObjectMatrix( pObject );
  274. IVP_U_Float_Point out;
  275. if ( translate )
  276. {
  277. pMatrix->inline_vmult4( &pointIn, &out );
  278. }
  279. else
  280. {
  281. pMatrix->inline_vmult3( &pointIn, &out );
  282. }
  283. pointOut.set( &out );
  284. #endif
  285. }
  286. void TransformLocalToIVP( const IVP_U_Float_Point &pointIn, IVP_U_Float_Point &pointOut, IVP_Real_Object *pObject, bool translate )
  287. {
  288. IVP_U_Point tmpOut;
  289. TransformLocalToIVP( pointIn, tmpOut, pObject, translate );
  290. pointOut.set( &tmpOut );
  291. }
  292. static char axisMap[] = {0,2,1,3};
  293. int ConvertCoordinateAxisToIVP( int axisIndex )
  294. {
  295. return axisIndex < 4 ? axisMap[axisIndex] : 0;
  296. }
  297. int ConvertCoordinateAxisToHL( int axisIndex )
  298. {
  299. return axisIndex < 4 ? axisMap[axisIndex] : 0;
  300. }