wheelvehicle.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/wheelvehicle.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 8/17/01 8:52p $*
  29. * *
  30. * $Revision:: 41 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "wheelvehicle.h"
  36. #include "rendobj.h"
  37. #include "lineseg.h"
  38. #include "physcoltest.h"
  39. #include "pscene.h"
  40. #include "physcontrol.h"
  41. #include "wwphysids.h"
  42. #include "persistfactory.h"
  43. #include "simpledefinitionfactory.h"
  44. #include "wwhack.h"
  45. #include "wwprofile.h"
  46. #include "wheel.h"
  47. #include <string.h>
  48. DECLARE_FORCE_LINK(wheelvehicle);
  49. /*
  50. ** Declare a PersistFactory for WheeledVehicleClasses
  51. */
  52. SimplePersistFactoryClass<WheeledVehicleClass,PHYSICS_CHUNKID_WHEELEDVEHICLE> _WheeledVehicleFactory;
  53. /*
  54. ** Chunk-ID's used by wheeled vehicle class
  55. */
  56. enum
  57. {
  58. WHEELEDVEHICLE_CHUNK_MOTORVEHICLE = 0x00119801,
  59. WHEELEDVEHICLE_CHUNK_VARIABLES,
  60. WV_VARIABLE_STEERINGANGLE = 0x00,
  61. OBSOLETE_WV_VARIABLE_MAXSTEERINGANGLE,
  62. OBSOLETE_WV_VARIABLE_SPRINGCONSTANT,
  63. OBSOLETE_WV_VARIABLE_DAMPINGCONSTANT,
  64. OBSOLETE_WV_VARIABLE_SPRINGLENGTH,
  65. };
  66. // Steering constant defaults
  67. const float DEFAULT_MAX_STEER_ANGLE = (float)WWMATH_PI/4.0f;
  68. // Debugging colors
  69. const Vector3 SPRING_COLOR(1.0f,0.5f,0.0f);
  70. const Vector3 SUSPENSION_FORCE_COLOR(1.0f,0.0f,0.0f);
  71. WheeledVehicleClass::WheeledVehicleClass(void) :
  72. SteeringAngle(0)
  73. {
  74. }
  75. void WheeledVehicleClass::Init(const WheeledVehicleDefClass & def)
  76. {
  77. MotorVehicleClass::Init(def);
  78. }
  79. WheeledVehicleClass::~WheeledVehicleClass(void)
  80. {
  81. }
  82. SuspensionElementClass * WheeledVehicleClass::Alloc_Suspension_Element(void)
  83. {
  84. return new WVWheelClass;
  85. }
  86. void WheeledVehicleClass::Compute_Force_And_Torque(Vector3 * force,Vector3 * torque)
  87. {
  88. {
  89. WWPROFILE("WheeledVehicleClass::Compute_Force_And_Torque");
  90. const WheeledVehicleDefClass * def = Get_WheeledVehicleDef();
  91. WWASSERT(def != NULL);
  92. /*
  93. ** Compute the steering angle for normal vehicles
  94. */
  95. if (Controller) {
  96. SteeringAngle = Controller->Get_Turn_Left() * def->MaxSteeringAngle;
  97. } else {
  98. SteeringAngle = 0.0f;
  99. }
  100. /*
  101. ** Compute the steering angle for "leaning" vehicles (motorcycles)
  102. ** (gth) Tilt steering isn't working out very well, changing to normal steering
  103. */
  104. #if 0
  105. const float STEER_ANGLE_PER_ROLL = DEG_TO_RADF(30.0f) / DEG_TO_RADF(60.0f);
  106. Vector3 yvec;
  107. Get_Transform().Get_Y_Vector(&yvec);
  108. float roll = atan2(yvec.Z,sqrt(yvec.X * yvec.X + yvec.Y * yvec.Y));
  109. float tilt_steer_angle = - roll / STEER_ANGLE_PER_ROLL;
  110. #else
  111. float tilt_steer_angle = SteeringAngle;
  112. #endif
  113. /*
  114. ** Compute forces and torques for each wheel.
  115. */
  116. for (int iwheel = 0; iwheel<Wheels.Length(); iwheel++) {
  117. /*
  118. ** update the steering input to the wheel
  119. */
  120. if (Wheels[iwheel]->Get_Flag(SuspensionElementClass::STEERING)) {
  121. Wheels[iwheel]->Set_Steering_Angle(SteeringAngle);
  122. } else if (Wheels[iwheel]->Get_Flag(SuspensionElementClass::INV_STEERING)) {
  123. Wheels[iwheel]->Set_Steering_Angle(-SteeringAngle);
  124. } else if (Wheels[iwheel]->Get_Flag(SuspensionElementClass::TILT_STEERING)) {
  125. Wheels[iwheel]->Set_Steering_Angle(tilt_steer_angle);
  126. }
  127. /*
  128. ** update the braking state of the wheel
  129. */
  130. Wheels[iwheel]->Set_Flag(SuspensionElementClass::BRAKING,Is_Braking());
  131. /*
  132. ** update the engine torque
  133. */
  134. if (Wheels[iwheel]->Get_Flag(SuspensionElementClass::ENGINE)) {
  135. ((WVWheelClass *)Wheels[iwheel])->Set_Axle_Torque(Get_Axle_Torque() / Get_Drive_Wheel_Count() );
  136. }
  137. }
  138. /*
  139. ** Let base class add in its forces
  140. */
  141. }
  142. MotorVehicleClass::Compute_Force_And_Torque(force,torque);
  143. }
  144. float WheeledVehicleClass::Get_Ideal_Drive_Axle_Angular_Velocity(void)
  145. {
  146. // return the highest angular velocity of any of the drive wheels
  147. float avel = -10000.0f;
  148. for (int i=0; i<Wheels.Length(); i++) {
  149. avel = ((WVWheelClass *)Wheels[i])->Get_Ideal_Drive_Wheel_Angular_Velocity(avel);
  150. }
  151. return avel;
  152. }
  153. bool WheeledVehicleClass::Drive_Wheels_In_Contact(void)
  154. {
  155. for (int i=0; i<Wheels.Length(); i++) {
  156. if ( Wheels[i]->Get_Flag(SuspensionElementClass::ENGINE) && Wheels[i]->Get_Flag(SuspensionElementClass::INCONTACT)) {
  157. return true;
  158. }
  159. }
  160. return false;
  161. }
  162. /*
  163. ** Save-Load System
  164. */
  165. const PersistFactoryClass & WheeledVehicleClass::Get_Factory (void) const
  166. {
  167. return _WheeledVehicleFactory;
  168. }
  169. bool WheeledVehicleClass::Save (ChunkSaveClass &csave)
  170. {
  171. csave.Begin_Chunk(WHEELEDVEHICLE_CHUNK_MOTORVEHICLE);
  172. MotorVehicleClass::Save(csave);
  173. csave.End_Chunk();
  174. csave.Begin_Chunk(WHEELEDVEHICLE_CHUNK_VARIABLES);
  175. WRITE_MICRO_CHUNK(csave,WV_VARIABLE_STEERINGANGLE,SteeringAngle);
  176. csave.End_Chunk();
  177. return true;
  178. }
  179. bool WheeledVehicleClass::Load (ChunkLoadClass &cload)
  180. {
  181. while (cload.Open_Chunk()) {
  182. switch(cload.Cur_Chunk_ID())
  183. {
  184. case WHEELEDVEHICLE_CHUNK_MOTORVEHICLE:
  185. MotorVehicleClass::Load(cload);
  186. break;
  187. case WHEELEDVEHICLE_CHUNK_VARIABLES:
  188. while (cload.Open_Micro_Chunk()) {
  189. switch(cload.Cur_Micro_Chunk_ID()) {
  190. READ_MICRO_CHUNK(cload,WV_VARIABLE_STEERINGANGLE,SteeringAngle);
  191. OBSOLETE_MICRO_CHUNK(OBSOLETE_WV_VARIABLE_MAXSTEERINGANGLE);
  192. OBSOLETE_MICRO_CHUNK(OBSOLETE_WV_VARIABLE_SPRINGCONSTANT);
  193. OBSOLETE_MICRO_CHUNK(OBSOLETE_WV_VARIABLE_DAMPINGCONSTANT);
  194. OBSOLETE_MICRO_CHUNK(OBSOLETE_WV_VARIABLE_SPRINGLENGTH);
  195. }
  196. cload.Close_Micro_Chunk();
  197. }
  198. break;
  199. default:
  200. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  201. break;
  202. }
  203. cload.Close_Chunk();
  204. }
  205. return true;
  206. }
  207. /***********************************************************************************************
  208. **
  209. ** WheeledVehicleDefClass Implementation
  210. **
  211. ***********************************************************************************************/
  212. SimplePersistFactoryClass<WheeledVehicleDefClass,PHYSICS_CHUNKID_WHEELEDVEHICLEDEF> _WheeledVehicleDefFactory;
  213. DECLARE_DEFINITION_FACTORY(WheeledVehicleDefClass, CLASSID_WHEELEDVEHICLEDEF, "WheeledVehicle") _WheeledVehicleDefDefFactory;
  214. /*
  215. ** Chunk ID's used by WheeledVehicleDefClass
  216. */
  217. enum
  218. {
  219. WHEELEDVEHICLEDEF_CHUNK_MOTORVEHICLEDEF = 0x00990066, // (parent class)
  220. WHEELEDVEHICLEDEF_CHUNK_VARIABLES,
  221. WHEELEDVEHICLEDEF_VARIABLE_MAXSTEERINGANGLE = 0x00,
  222. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_SPRINGCONSTANT,
  223. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_DAMPINGCONSTANT,
  224. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_SPRINGLENGTH,
  225. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIVEFRICTIONCURVEFILENAME,
  226. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_LATERALFRICTIONCURVEFILENAME,
  227. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIONMULTIPLIER,
  228. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_LATERALMOMENTARM,
  229. OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIVEMOMENTARM
  230. };
  231. WheeledVehicleDefClass::WheeledVehicleDefClass(void) :
  232. MaxSteeringAngle(DEFAULT_MAX_STEER_ANGLE)
  233. {
  234. // make our parameters editable!
  235. ANGLE_EDITABLE_PARAM(WheeledVehicleDefClass, MaxSteeringAngle, DEG_TO_RADF(0.0f), DEG_TO_RADF(90.0f));
  236. }
  237. uint32 WheeledVehicleDefClass::Get_Class_ID (void) const
  238. {
  239. return CLASSID_WHEELEDVEHICLEDEF;
  240. }
  241. const PersistFactoryClass & WheeledVehicleDefClass::Get_Factory (void) const
  242. {
  243. return _WheeledVehicleDefFactory;
  244. }
  245. PersistClass * WheeledVehicleDefClass::Create(void) const
  246. {
  247. WheeledVehicleClass * obj = NEW_REF(WheeledVehicleClass,());
  248. obj->Init(*this);
  249. return obj;
  250. }
  251. bool WheeledVehicleDefClass::Save(ChunkSaveClass &csave)
  252. {
  253. csave.Begin_Chunk(WHEELEDVEHICLEDEF_CHUNK_MOTORVEHICLEDEF);
  254. MotorVehicleDefClass::Save(csave);
  255. csave.End_Chunk();
  256. csave.Begin_Chunk(WHEELEDVEHICLEDEF_CHUNK_VARIABLES);
  257. WRITE_MICRO_CHUNK(csave,WHEELEDVEHICLEDEF_VARIABLE_MAXSTEERINGANGLE,MaxSteeringAngle);
  258. csave.End_Chunk();
  259. return true;
  260. }
  261. bool WheeledVehicleDefClass::Load(ChunkLoadClass &cload)
  262. {
  263. while (cload.Open_Chunk()) {
  264. switch(cload.Cur_Chunk_ID()) {
  265. case WHEELEDVEHICLEDEF_CHUNK_MOTORVEHICLEDEF:
  266. MotorVehicleDefClass::Load(cload);
  267. break;
  268. case WHEELEDVEHICLEDEF_CHUNK_VARIABLES:
  269. while (cload.Open_Micro_Chunk()) {
  270. switch(cload.Cur_Micro_Chunk_ID()) {
  271. READ_MICRO_CHUNK(cload,WHEELEDVEHICLEDEF_VARIABLE_MAXSTEERINGANGLE,MaxSteeringAngle);
  272. // NOTE: these variables are now in VehiclePhysDefClass...
  273. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_SPRINGCONSTANT,SpringConstant);
  274. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_DAMPINGCONSTANT,DampingConstant);
  275. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_SPRINGLENGTH,SpringLength);
  276. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIONMULTIPLIER,TractionMultiplier);
  277. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_LATERALMOMENTARM,LateralMomentArm);
  278. READ_MICRO_CHUNK(cload,OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIVEMOMENTARM,TractiveMomentArm);
  279. OBSOLETE_MICRO_CHUNK(OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_TRACTIVEFRICTIONCURVEFILENAME);
  280. OBSOLETE_MICRO_CHUNK(OBSOLETE_WHEELEDVEHICLEDEF_VARIABLE_LATERALFRICTIONCURVEFILENAME);
  281. }
  282. cload.Close_Micro_Chunk();
  283. }
  284. break;
  285. default:
  286. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  287. break;
  288. }
  289. cload.Close_Chunk();
  290. }
  291. return true;
  292. }
  293. bool WheeledVehicleDefClass::Is_Type(const char * type_name)
  294. {
  295. if (stricmp(type_name,WheeledVehicleDefClass::Get_Type_Name()) == 0) {
  296. return true;
  297. } else {
  298. return MotorVehicleDefClass::Is_Type(type_name);
  299. }
  300. }