rbody_obsolete.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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. **
  20. ** OBSOLETE CODE!!!!!
  21. **
  22. ** THIS CODE IS JUST HERE IN CASE THERE IS SOME USEFUL IDEA IN IT THAT I MAY HAVE
  23. ** FORGOTTEN. PROBABLY NOT!
  24. **
  25. ***************************************************************************************/
  26. /*
  27. ** This is a timestep function for RigidBodyClass that tried to do orientation and
  28. ** position updates independently when a collision occured
  29. */
  30. #if 0
  31. void RigidBodyClass::Timestep(float dt)
  32. {
  33. const int MAX_BUMPS = 5;
  34. Assert_State_Valid();
  35. LastTimestep = dt;
  36. /*
  37. ** Repeat until we eat all of the time
  38. */
  39. float remaining_time = dt;
  40. float timestep;
  41. int bumps = 0;
  42. Inc_Ignore_Counter();
  43. while ((remaining_time > 0.0f) && (bumps < MAX_BUMPS)) {
  44. timestep = remaining_time;
  45. bumps++;
  46. CastResultStruct result;
  47. OBBoxClass obbox;
  48. /*
  49. ** Integrate the state of the object
  50. */
  51. Assert_State_Valid();
  52. RigidBodyStateStruct oldstate = State;
  53. Integrate(timestep);
  54. Assert_State_Valid();
  55. /*
  56. ** sample the start and end positions and orientations
  57. */
  58. Vector3 p0 = oldstate.Position;
  59. Vector3 p1 = State.Position;
  60. Quaternion q0 = oldstate.Orientation;
  61. Quaternion q1 = State.Orientation;
  62. /*
  63. ** rotate in place
  64. */
  65. Matrix3D rotate_in_place(q1,p0);
  66. Model->Set_Transform(rotate_in_place);
  67. obbox = Box->Get_Box();
  68. result.Reset();
  69. PhysOBBoxCollisionTestClass boxrotate( obbox,
  70. Vector3(0,0,0),
  71. &result,
  72. Get_Collision_Group(),
  73. COLLISION_TYPE_PHYSICAL);
  74. PhysicsSceneClass::Get_Instance()->Cast_OBBox(boxrotate);
  75. if (result.StartBad) {
  76. q1 = q0;
  77. State.Orientation = q0;
  78. State.AMomentum /= 4.0f;
  79. StickCount++;
  80. } else {
  81. StickCount = 0;
  82. }
  83. /*
  84. ** now translate
  85. */
  86. Matrix3D initial_position(q1,p0);
  87. Vector3 move(p1 - p0);
  88. Model->Set_Transform(initial_position);
  89. obbox = Box->Get_Box();
  90. result.Reset();
  91. result.ComputePoint = true;
  92. PhysOBBoxCollisionTestClass boxmove( obbox,
  93. move,
  94. &result,
  95. Get_Collision_Group(),
  96. COLLISION_TYPE_PHYSICAL);
  97. PhysicsSceneClass::Get_Instance()->Cast_OBBox(boxmove);
  98. if (result.StartBad) {
  99. remaining_time = 0;
  100. State = oldstate;
  101. //goto do_it_again;
  102. } else {
  103. if (result.Fraction == 1.0f) {
  104. // accepting the entire move
  105. remaining_time -= timestep;
  106. State.Position = p0 + 0.99f * move;
  107. } else {
  108. // IMPACT!
  109. // only take the fraction of time
  110. remaining_time -= result.Fraction * timestep;
  111. // only move up to the collision point, minus a padding amount
  112. #if 0
  113. float len = (result.Fraction * move).Length();
  114. len -= MOVE_BUFFER;
  115. if (len > 0.0f) {
  116. move.Normalize();
  117. move *= len;
  118. State.Position = p0 + move;
  119. } else {
  120. State.Position = p0;
  121. }
  122. #else
  123. State.Position = p0 + 0.99f * result.Fraction * move;
  124. #endif
  125. // interpolate the momenta to approximate their state at time of impact
  126. Assert_State_Valid();
  127. State.LMomentum = oldstate.LMomentum + (State.LMomentum - oldstate.LMomentum) * result.Fraction;
  128. State.AMomentum = oldstate.AMomentum + (State.AMomentum - oldstate.AMomentum) * result.Fraction;
  129. Assert_State_Valid();
  130. // TODO: support multiple contact points!
  131. ContactCount = 1;
  132. ContactPoint[0] = result.Point;
  133. Vector3 impulse;
  134. Compute_Impact(result,&impulse);
  135. Vector3 padot0,padot1;
  136. Compute_Point_Velocity(result.Point,&padot0);
  137. Assert_State_Valid();
  138. Apply_Impulse(impulse,result.Point);
  139. Assert_State_Valid();
  140. Assert_State_Valid();
  141. // E3Demo!!!
  142. if (StickCount > 3) {
  143. State.AMomentum *= 0.5f;
  144. State.Position.Z += 0.1f;
  145. Update_Auxiliary_State();
  146. Apply_Impulse(result.Normal * 0.25f * Get_Weight());
  147. }
  148. Assert_State_Valid();
  149. }
  150. }
  151. Update_Auxiliary_State();
  152. }
  153. Dec_Ignore_Counter();
  154. WWASSERT(Model);
  155. Model->Set_Transform(Matrix3D(Rotation,State.Position));
  156. Update_Cull_Box();
  157. Assert_State_Valid();
  158. if (ContactBox != NULL) {
  159. ContactBox->Compute_Forces();
  160. }
  161. #ifdef WWDEBUG
  162. if(Is_Debug_Display_Enabled()) {
  163. Add_Debug_Vector(State.Position,Velocity,LMOMENTUM_COLOR);
  164. Add_Debug_Vector(State.Position,AngularVelocity,AMOMENTUM_COLOR);
  165. }
  166. #endif
  167. }
  168. #endif
  169. /*
  170. ** This was a version of Timestep which used a binary search through time to try
  171. ** and find the "exact" time of collision. What a collosal waste of time!
  172. */
  173. #if 0
  174. void RigidBodyClass::Timestep(float dt)
  175. {
  176. if ( Is_Immovable() ) {
  177. return;
  178. }
  179. WWASSERT(Model);
  180. WWASSERT(ContactBox);
  181. Inc_Ignore_Counter();
  182. #ifdef RBODY_DEBUGGING
  183. WWDEBUG_SAY(("------------------------------\r\n"));
  184. WWDEBUG_SAY(("RigidBody Timestep Begin.\r\n"));
  185. WWASSERT(!ContactBox->Is_Intersecting());
  186. #endif
  187. /*
  188. ** Repeat until we eat all of the time
  189. */
  190. const int MAX_COLLISIONS = 100;
  191. int collisions = 0;
  192. float remaining_time = dt;
  193. float timestep;
  194. #ifdef RBODY_DEBUGGING
  195. WWDEBUG_SAY(("clock counter begin:\r\n"));
  196. #endif
  197. while ((remaining_time > 0.0f) && (collisions < MAX_COLLISIONS)) {
  198. timestep = remaining_time;
  199. /*
  200. ** Integrate the state of the object
  201. */
  202. #ifdef RBODY_DEBUGGING
  203. WWDEBUG_SAY(("Computing new state, delta_t = %f:\r\n",timestep));
  204. #endif
  205. RigidBodyStateStruct oldstate = State;
  206. Integrate(timestep);
  207. #ifdef RBODY_DEBUGGING
  208. WWDEBUG_SAY(("Done.\r\n\r\n"));
  209. #endif
  210. /*
  211. ** Check the final state of the object for collision.
  212. */
  213. if (!ContactBox->Is_Intersecting()) {
  214. /*
  215. ** Not intersecting so we're accepting the entire move
  216. */
  217. remaining_time -= timestep;
  218. StickCount = 0;
  219. #ifdef RBODY_DEBUGGING
  220. WWDEBUG_SAY(("No Collision\r\n"));
  221. #endif
  222. } else {
  223. #ifdef RBODY_DEBUGGING
  224. WWDEBUG_SAY(("Collision! Searching for TOC.\r\n"));
  225. #endif
  226. /*
  227. ** Sample the start and end positions and orientations.
  228. */
  229. Vector3 p0 = oldstate.Position;
  230. Vector3 p1 = State.Position;
  231. Quaternion q0 = oldstate.Orientation;
  232. Quaternion q1 = State.Orientation;
  233. /*
  234. ** Assert that our start point was not intersecting.
  235. */
  236. #ifdef WWDEBUG
  237. #ifdef RBODY_DEBUGGING
  238. WWDEBUG_SAY(("Prev Position: %f %f %f\r\n",oldstate.Position.X,oldstate.Position.Y,oldstate.Position.Z));
  239. WWDEBUG_SAY(("New Position: %f %f %f\r\n",State.Position.X,State.Position.Y,State.Position.Z));
  240. WWDEBUG_SAY(("Prev Orientation: %f %f %f %f\r\n",oldstate.Orientation.X,oldstate.Orientation.Y,oldstate.Orientation.Z,oldstate.Orientation.W));
  241. WWDEBUG_SAY(("New Orientation: %f %f %f %f\r\n",State.Orientation.X,State.Orientation.Y,State.Orientation.Z,State.Orientation.W));
  242. ContactBox->Set_Transform(q0,p0);
  243. WWASSERT(!ContactBox->Is_Intersecting());
  244. #endif
  245. #endif
  246. /*
  247. ** Binary search to find the time of collision
  248. */
  249. float t = 0.0f;
  250. float t0 = 0.0f;
  251. float t1 = 1.0f;
  252. const float COLLISION_EPSILON = 0.01f;//(float)WWMATH_EPSILON;
  253. Vector3 p;
  254. Quaternion q;
  255. SlerpInfoStruct slerpinfo;
  256. Slerp_Setup(q0,q1,&slerpinfo);
  257. while (t1 - t0 > COLLISION_EPSILON) {
  258. t = (t1 + t0) / 2.0f;
  259. /*
  260. ** Compute interpolated orientation and position
  261. */
  262. Lerp(p0,p1,t,&p);
  263. Cached_Slerp(q0,q1,t,&slerpinfo,&q);
  264. ContactBox->Set_Transform(q,p);
  265. /*
  266. ** Test for collision here
  267. */
  268. #ifdef RBODY_DEBUGGING
  269. bool intersecting = ContactBox->Is_Intersecting();
  270. WWDEBUG_SAY((" t0 = %f t1 = %f t=%f %s\r\n",t0,t1,t,(intersecting ? "colliding" : "not-colliding")));
  271. #endif
  272. /*
  273. ** Zero in on the TOC
  274. */
  275. if (intersecting) {
  276. t1 = t;
  277. } else {
  278. t0 = t;
  279. }
  280. }
  281. /*
  282. ** t0 is guaranteed to be non-intersecting so use it for TOC
  283. */
  284. t = t0;
  285. remaining_time -= t * timestep;
  286. if (t == 0.0f) {
  287. remaining_time -= 0.001f;
  288. }
  289. #ifdef RBODY_DEBUGGING
  290. WWDEBUG_SAY(("Found collision at fraction: %f\r\n",t));
  291. #endif
  292. /*
  293. ** Compute the state right before the collision
  294. */
  295. Cached_Slerp(q0,q1,t,&slerpinfo,&State.Orientation);
  296. Lerp(p0,p1,t,&State.Position);
  297. Lerp(oldstate.LMomentum,State.LMomentum,t,&State.LMomentum);
  298. Lerp(oldstate.AMomentum,State.AMomentum,t,&State.AMomentum);
  299. Update_Auxiliary_State();
  300. //ContactBox->Set_Transform(Matrix3D(State.Orientation,State.Position));
  301. #ifdef RBODY_DEBUGGING
  302. // WWDEBUG_SAY(("Position: %f %f %f\r\n",State.Position.X,State.Position.Y,State.Position.Z));
  303. // WWDEBUG_SAY(("Orientation: %f %f %f %f\r\n",State.Orientation.X,State.Orientation.Y,State.Orientation.Z,State.Orientation.W));
  304. WWASSERT(!ContactBox->Is_Intersecting());
  305. #endif
  306. /*
  307. ** Find the collision point and normal and apply an impulse to the object.
  308. */
  309. ContactBox->Compute_Contacts();
  310. #if 0 // Compute an impulse for the worst contact
  311. Vector3 point;
  312. Vector3 normal;
  313. for (int i=0; i<ContactBox->Get_Contact_Count(); i++) {
  314. if (ContactBox->Get_Contact(i).Fraction < frac) {
  315. point = ContactBox->Get_Contact(i).Point;
  316. normal = ContactBox->Get_Contact(i).Normal;
  317. };
  318. }
  319. Vector3 impulse;
  320. // Compute_Impact(point,normal,&impulse);
  321. // DEBUG DEBUG apply impulse only at CM!
  322. Compute_Impact(State.Position,normal,&impulse);
  323. Apply_Impulse(impulse,point);
  324. #ifdef RBODY_DEBUGGING
  325. DEBUG_RENDER_POINT(point,Vector3(1,0,0));
  326. WWDEBUG_SAY(("Applied Impulse: %f %f %f\r\n",impulse.X,impulse.Y,impulse.Z));
  327. #endif
  328. #endif
  329. #if 1 // Simultaneously compute impulses for all contacts
  330. if (ContactBox->Get_Contact_Count() > 0) {
  331. int i;
  332. Vector3 * impulses = new Vector3[ContactBox->Get_Contact_Count()];
  333. for (i=0; i<ContactBox->Get_Contact_Count(); i++) {
  334. Vector3 point;
  335. Vector3 normal;
  336. point = ContactBox->Get_Contact(i).Point;
  337. normal = ContactBox->Get_Contact(i).Normal;
  338. Compute_Impact(point,normal,&(impulses[i]));
  339. }
  340. for (i=0; i<ContactBox->Get_Contact_Count(); i++) {
  341. Vector3 point;
  342. point = ContactBox->Get_Contact(i).Point;
  343. impulses[i] /= ContactBox->Get_Contact_Count();
  344. Apply_Impulse(impulses[i],point);
  345. Assert_State_Valid();
  346. }
  347. }
  348. #endif
  349. #if 0 // Repeatedly compute impulses until the object is happy.
  350. int cur_contact = 0;
  351. int impact_count = 0;
  352. bool done = false;
  353. while (!done && (impact_count < 100)) {
  354. Vector3 impulse;
  355. const Vector3 & point = ContactBox->Get_Contact(cur_contact).Point;
  356. const Vector3 & normal = ContactBox->Get_Contact(cur_contact).Normal;
  357. if (Is_Colliding(point,normal)) {
  358. Compute_Impact(point,normal,&impulse);
  359. Apply_Impulse(impulse,point);
  360. }
  361. done = true;
  362. for (int i=0; i<ContactBox->Get_Contact_Count(); i++) {
  363. if (Is_Colliding(ContactBox->Get_Contact(i).Point,ContactBox->Get_Contact(i).Normal)) {
  364. done = false;
  365. }
  366. }
  367. cur_contact = (cur_contact + 1) % ContactBox->Get_Contact_Count();
  368. impact_count++;
  369. }
  370. #ifdef RBODY_DEBUGGING
  371. WWDEBUG_SAY(("Number of impacts to resolve collision: %d\r\n",impact_count));
  372. #endif
  373. #endif
  374. #ifdef RBODY_DEBUGGING
  375. WWDEBUG_SAY(("\r\n"));
  376. WWDEBUG_SAY(("Position: %f %f %f\r\n",State.Position.X,State.Position.Y,State.Position.Z));
  377. WWDEBUG_SAY(("Orientation: %f %f %f %f\r\n",State.Orientation.X,State.Orientation.Y,State.Orientation.Z,State.Orientation.W));
  378. #endif
  379. }
  380. collisions++;
  381. }
  382. #ifdef RBODY_DEBUGGING
  383. WWASSERT(!ContactBox->Is_Intersecting());
  384. WWDEBUG_SAY(("RigidBody Timestep End.\r\n"));
  385. WWDEBUG_SAY(("\r\n"));
  386. #endif
  387. #ifdef WWDEBUG
  388. if(Is_Debug_Display_Enabled()) {
  389. Add_Debug_Vector(State.Position,Velocity,LMOMENTUM_COLOR);
  390. Add_Debug_Vector(State.Position,AngularVelocity,AMOMENTUM_COLOR);
  391. }
  392. #endif
  393. Dec_Ignore_Counter();
  394. Model->Set_Transform(Matrix3D(Rotation,State.Position));
  395. Update_Cull_Box();
  396. }
  397. #endif //0