Counter Strike : Global Offensive Source Code
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.

122 lines
4.2 KiB

  1. //--------------------------------------------------------------------------------------------------
  2. // qhMass.cpp
  3. //
  4. // Copyright(C) 2011 by D. Gregorius. All rights reserved.
  5. //--------------------------------------------------------------------------------------------------
  6. #include "qhMass.h"
  7. //--------------------------------------------------------------------------------------------------
  8. // Local utilities
  9. //--------------------------------------------------------------------------------------------------
  10. inline qhMatrix3 qhSteiner( qhReal Weight, const qhVector3& Center )
  11. {
  12. // Usage: Io = Ic + Is and Ic = Io - Is
  13. qhReal Ixx = Weight * ( Center.Y * Center.Y + Center.Z * Center.Z );
  14. qhReal Iyy = Weight * ( Center.X * Center.X + Center.Z * Center.Z );
  15. qhReal Izz = Weight * ( Center.X * Center.X + Center.Y * Center.Y );
  16. qhReal Ixy = -Weight * Center.X * Center.Y;
  17. qhReal Ixz = -Weight * Center.X * Center.Z;
  18. qhReal Iyz = -Weight * Center.Y * Center.Z;
  19. // Write
  20. qhMatrix3 Out;
  21. Out.C1.X = Ixx; Out.C2.X = Ixy; Out.C3.X = Ixz;
  22. Out.C1.Y = Ixy; Out.C2.Y = Iyy; Out.C3.Y = Iyz;
  23. Out.C1.Z = Ixz; Out.C2.Z = Iyz; Out.C3.Z = Izz;
  24. return Out;
  25. }
  26. //--------------------------------------------------------------------------------------------------
  27. // qhMass
  28. //--------------------------------------------------------------------------------------------------
  29. qhMass::qhMass( void )
  30. : Weight( 0 )
  31. , Center( QH_VEC3_ZERO )
  32. , Inertia( QH_MAT3_ZERO )
  33. {
  34. }
  35. //--------------------------------------------------------------------------------------------------
  36. qhMass& qhMass::operator+=( const qhMass& Other )
  37. {
  38. Inertia += Other.Inertia;
  39. Center = ( Weight * Center + Other.Weight * Other.Center ) / ( Weight + Other.Weight );
  40. Weight += Other.Weight;
  41. return *this;
  42. }
  43. //--------------------------------------------------------------------------------------------------
  44. void qhMass::ShiftToOrigin( void )
  45. {
  46. Inertia += qhSteiner( Weight, Center );
  47. }
  48. //--------------------------------------------------------------------------------------------------
  49. void qhMass::ShiftToCenter( void )
  50. {
  51. Inertia -= qhSteiner( Weight, Center );
  52. }
  53. //--------------------------------------------------------------------------------------------------
  54. qhMass qhSphereMass( const qhVector3& Center, qhReal Radius, qhReal Density )
  55. {
  56. qhReal Volume = qhReal( 0.4 ) * QH_PI * Radius * Radius * Radius;
  57. qhReal Weight = Volume * Density;
  58. qhReal I = qhReal( 0.4 ) * Weight * Radius * Radius;
  59. qhMass Mass;
  60. Mass.Weight = Weight;
  61. Mass.Center = Center;
  62. Mass.Inertia = qhMatrix3( I, I, I ) + qhSteiner( Weight, Center );
  63. return Mass;
  64. }
  65. //--------------------------------------------------------------------------------------------------
  66. qhMass qhCapsuleMass( const qhVector3& Center1, const qhVector3& Center2, qhReal Radius, qhReal Density )
  67. {
  68. // Compute height and check if we degenerate into a sphere
  69. qhReal Height = qhDistance( Center1, Center2 );
  70. if ( Height < qhReal( 100 ) * QH_REAL_EPSILON )
  71. {
  72. return qhSphereMass( qhReal( 0.5 ) * ( Center1 + Center2 ), Radius, Density );
  73. }
  74. // Cylinder
  75. qhReal CylinderVolume = ( QH_PI * Radius * Radius ) * Height;
  76. qhReal CylinderWeight = CylinderVolume * Density;
  77. // Sphere
  78. qhReal SphereVolume = qhReal( 4.0 / 3.0 ) * QH_PI * Radius * Radius * Radius;
  79. qhReal SphereWeight = SphereVolume * Density;
  80. // Parallel Axis Theorem (Steiner)
  81. qhReal Offset = qhReal( 0.5 ) * Height + qhReal( 3.0 / 8.0 ) * Radius;
  82. qhReal Ix = qhReal( 1.0 / 12.0 ) * CylinderWeight * ( qhReal( 3 ) * Radius * Radius + Height * Height ) + qhReal( 83.0 / 320.0 ) * SphereWeight * Radius * Radius + SphereWeight * Offset * Offset;
  83. qhReal Iy = qhReal( 0.5 ) * CylinderWeight * Radius * Radius + qhReal( 0.4 ) * SphereWeight * Radius * Radius;
  84. // Align capsule axis with chosen up-axis
  85. qhReal Weight = SphereWeight + CylinderWeight;
  86. qhVector3 Center = qhReal( 0.5 ) * ( Center1 + Center2 );
  87. qhVector3 Direction = qhNormalize( Center2 - Center1 );
  88. qhQuaternion Q = qhRotation( QH_VEC3_AXIS_Y, Direction );
  89. qhMatrix3 R = qhConvert( Q );
  90. qhMass Mass;
  91. Mass.Weight = Weight;
  92. Mass.Center = Center;
  93. Mass.Inertia = R * qhMatrix3( Ix, Iy, Ix ) * qhTranspose( R ) + qhSteiner( Weight, Center );
  94. return Mass;
  95. }