Physics.ODEUtils.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit Physics.ODEUtils;
  5. (* Open Dynamic Engine Utils
  6. Here is the collection of random functions and procedures that useful when
  7. integrating ODE into GLScene. If you don't use GLS.Scene, this unit won't be
  8. very useful to you. The unit is not intended as a sorted toolbox, but more
  9. as a place to put stuff until we figure out how to organize the integration.
  10. *)
  11. interface
  12. uses
  13. Winapi.OpenGL,
  14. System.SysUtils,
  15. System.Classes,
  16. Physics.ODEImport,
  17. GLS.OpenGLTokens,
  18. GLS.Context,
  19. GLS.VectorGeometry,
  20. GLS.Scene,
  21. GLS.PersistentClasses,
  22. GLS.VectorTypes,
  23. GLS.VectorLists,
  24. GLS.Coordinates,
  25. GLS.Objects,
  26. GLS.VerletClothify,
  27. GLS.VectorFileObjects;
  28. procedure DrawBox(Sides: TdVector3);
  29. procedure setTransform(pos: TdVector3; R: TdMatrix3);
  30. procedure dsDrawBox(pos: PdVector3; R: PdMatrix3; Sides: TdVector3); overload;
  31. procedure dsDrawBox(pos: TdVector3; R: TdMatrix3; Sides: TdVector3); overload;
  32. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: TdMatrix3; pos: TdVector3); overload;
  33. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: PdMatrix3; pos: PdVector3); overload;
  34. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: TdMatrix3_As3x4; pos: TdVector3); overload;
  35. function GLSceneMatrixToODER(m: TGLMatrix): TdMatrix3;
  36. // Converting between ODE and GLScene formats
  37. function ConvertdVector3ToVector3f(R: TdVector3): TVector3f; overload;
  38. function ConvertdVector3ToVector3f(R: PdVector3): TVector3f; overload;
  39. function ConvertdVector3ToVector4f(R: TdVector3): TVector4f; overload;
  40. function ConvertdVector3ToVector4f(R: PdVector3): TVector4f; overload;
  41. function ConvertdVector3ToAffineVector(R: PdVector3): TAffineVector; overload;
  42. function ConvertdVector3ToAffineVector(R: TdVector3): TAffineVector; overload;
  43. function GetBodyPositionAsAffineVector(Body: PdxBody): TAffineVector;
  44. // Converting between GLScene and ODE formats
  45. function ConvertVector3fTodVector3(R: TVector3f): TdVector3;
  46. function ConvertVector3fToPdVector3(R: TVector3f): PdVector3;
  47. function ConvertVector4fTodVector3(R: TVector4f): TdVector3;
  48. function ConvertVector4fToPdVector3(R: TVector4f): PdVector3;
  49. function dVector3Length(R: TdVector3): single; overload;
  50. function dVector3Length(R: PdVector3): single; overload;
  51. function dBodyToBodyDistance(Body1, Body2: PdxBody): TdReal;
  52. procedure CopyPosFromGeomToGL(Geom: PdxGeom; GLBaseSceneObject: TGLBaseSceneObject);
  53. procedure PositionSceneObject(GLBaseSceneObject: TGLBaseSceneObject; Geom: PdxGeom);
  54. procedure PositionSceneObjectForGeom(Geom: PdxGeom);
  55. procedure CopyCubeSizeFromBox(Cube: TGLCube; Geom: PdxGeom);
  56. procedure CopyBodyFromCube(Body: PdxBody; var Geom: PdxGeom; Cube: TGLCube; Space: PdxSpace);
  57. function CreateGeomFromCube(Cube: TGLCube; Space: PdxSpace): PdxGeom;
  58. function CreateBodyFromCube(var Geom: PdxGeom; Cube: TGLCube; World: PdxWorld; Space: PdxSpace): PdxBody;
  59. (* This method requires you to manually deallocate vertices and
  60. indices when you're done with the trimesh *)
  61. function CreateTriMeshFromBaseMesh(
  62. GLBaseMesh: TGLBaseMesh;
  63. Space: PdxSpace;
  64. var Vertices: PdVector3Array;
  65. var Indices: PdIntegerArray): PdxGeom;
  66. function GLMatrixFromGeom(Geom: PdxGeom): TGLMatrix;
  67. function GLDirectionFromGeom(Geom: PdxGeom): TGLVector;
  68. function CreateODEPlaneFromGLPlane(Plane: TGLPlane; Space: PdxSpace): PdxGeom;
  69. procedure RenderGeomList(GeomList: TGeomList);
  70. function RandomColorVector: TGLVector;
  71. {.$ EXTERNALSYM GL_ZERO}
  72. //---------------------------------------------------------------------------
  73. implementation
  74. //---------------------------------------------------------------------------
  75. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: TdMatrix3_As3x4; pos: TdVector3); overload;
  76. begin
  77. m.X.X := r[0][0];
  78. m.X.Y := r[0][1];
  79. m.X.Z := r[0][2];
  80. m.X.W := 0;
  81. m.Y.X := r[1][0];
  82. m.Y.Y := r[1][1];
  83. m.Y.Z := r[1][2];
  84. m.Y.W := 0;
  85. m.Z.X := r[2][0];
  86. m.Z.Y := r[2][1];
  87. m.Z.Z := r[2][2];
  88. m.Z.W := 0;
  89. m.W := NullHmgPoint;
  90. TransposeMatrix(m);
  91. m.W.X := pos[0];
  92. m.W.Y := pos[1];
  93. m.W.Z := pos[2];
  94. m.W.W := 1; //}
  95. end;
  96. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: PdMatrix3; pos: PdVector3);
  97. begin
  98. ODERToGLSceneMatrix(m, TdMatrix3_As3x4(R^), pos^);
  99. end;
  100. procedure ODERToGLSceneMatrix(var m: TGLMatrix; R: TdMatrix3; pos: TdVector3);
  101. begin
  102. ODERToGLSceneMatrix(m, TdMatrix3_As3x4(R), pos);
  103. end;
  104. procedure DrawBox(Sides: TdVector3);
  105. var
  106. lx, ly, lz: single;
  107. begin
  108. lx := Sides[0] * 0.5;
  109. ly := Sides[1] * 0.5;
  110. lz := Sides[2] * 0.5;
  111. // sides
  112. gl.Begin_(GL_TRIANGLE_STRIP);
  113. gl.Normal3f(-1, 0, 0);
  114. gl.Vertex3f(-lx, -ly, -lz);
  115. gl.Vertex3f(-lx, -ly, lz);
  116. gl.Vertex3f(-lx, ly, -lz);
  117. gl.Vertex3f(-lx, ly, lz);
  118. gl.Normal3f(0, 1, 0);
  119. gl.Vertex3f(lx, ly, -lz);
  120. gl.Vertex3f(lx, ly, lz);
  121. gl.Normal3f(1, 0, 0);
  122. gl.Vertex3f(lx, -ly, -lz);
  123. gl.Vertex3f(lx, -ly, lz);
  124. gl.Normal3f(0, -1, 0);
  125. gl.Vertex3f(-lx, -ly, -lz);
  126. gl.Vertex3f(-lx, -ly, lz);
  127. gl.End_();
  128. // top face
  129. gl.Begin_(GL_TRIANGLE_FAN);
  130. gl.Normal3f(0, 0, 1);
  131. gl.Vertex3f(-lx, -ly, lz);
  132. gl.Vertex3f(lx, -ly, lz);
  133. gl.Vertex3f(lx, ly, lz);
  134. gl.Vertex3f(-lx, ly, lz);
  135. gl.End_();
  136. // bottom face
  137. gl.Begin_(GL_TRIANGLE_FAN);
  138. gl.Normal3f(0, 0, -1);
  139. gl.Vertex3f(-lx, -ly, -lz);
  140. gl.Vertex3f(-lx, ly, -lz);
  141. gl.Vertex3f(lx, ly, -lz);
  142. gl.Vertex3f(lx, -ly, -lz);
  143. gl.End_();
  144. end;
  145. function GLSceneMatrixToODER(m: TGLMatrix): TdMatrix3;
  146. begin
  147. TransposeMatrix(m);
  148. Result[0] := m.X.X;
  149. Result[1] := m.X.Y;
  150. Result[2] := m.X.Z;
  151. Result[4] := m.Y.X;
  152. Result[5] := m.Y.Y;
  153. Result[6] := m.Y.Z;
  154. Result[8] := m.Z.X;
  155. Result[9] := m.Z.Y;
  156. Result[10] := m.Z.Z;
  157. end;
  158. procedure dsDrawBox(pos: PdVector3; R: PdMatrix3; Sides: TdVector3);
  159. begin
  160. dsDrawBox(pos^, r^, Sides);
  161. end;
  162. procedure dsDrawBox(pos: TdVector3; R: TdMatrix3; Sides: TdVector3);
  163. begin
  164. setTransform(pos, R);
  165. drawBox(sides);
  166. gl.PopMatrix();
  167. end;
  168. procedure setTransform(pos: TdVector3; R: TdMatrix3);
  169. var
  170. matrix: array[0..15] of Single;
  171. begin
  172. matrix[0] := R[0];
  173. matrix[1] := R[4];
  174. matrix[2] := R[8];
  175. matrix[3] := 0;
  176. matrix[4] := R[1];
  177. matrix[5] := R[5];
  178. matrix[6] := R[9];
  179. matrix[7] := 0;
  180. matrix[8] := R[2];
  181. matrix[9] := R[6];
  182. matrix[10] := R[10];
  183. matrix[11] := 0;
  184. matrix[12] := pos[0];
  185. matrix[13] := pos[1];
  186. matrix[14] := pos[2];
  187. matrix[15] := 1;
  188. gl.PushMatrix();
  189. gl.MultMatrixf(@matrix);
  190. end;
  191. (*$WARNINGS OFF*)
  192. function ConvertdVector3ToVector3f(R: TdVector3): TVector3f;
  193. begin
  194. result.X := R[0];
  195. result.Y := R[1];
  196. result.Z := R[2];
  197. end;
  198. function ConvertdVector3ToVector3f(R: PdVector3): TVector3f;
  199. begin
  200. result.X := R[0];
  201. result.Y := R[1];
  202. result.Z := R[2];
  203. end;
  204. function ConvertdVector3ToVector4f(R: TdVector3): TVector4f; overload;
  205. begin
  206. result.X := R[0];
  207. result.Y := R[1];
  208. result.Z := R[2];
  209. result.W := 0;
  210. end;
  211. function ConvertdVector3ToVector4f(R: PdVector3): TVector4f; overload;
  212. begin
  213. result.X := R[0];
  214. result.Y := R[1];
  215. result.Z := R[2];
  216. result.W := 0;
  217. end;
  218. function ConvertdVector3ToAffineVector(R: PdVector3): TAffineVector; overload;
  219. begin
  220. result.X := R[0];
  221. result.Y := R[1];
  222. result.Z := R[2];
  223. end;
  224. function ConvertdVector3ToAffineVector(R: TdVector3): TAffineVector; overload;
  225. begin
  226. result.X := R[0];
  227. result.Y := R[1];
  228. result.Z := R[2];
  229. end;
  230. function ConvertVector3fTodVector3(R: TVector3f): TdVector3;
  231. begin
  232. result[0] := R.X;
  233. result[1] := R.Y;
  234. result[2] := R.Z;
  235. end;
  236. function ConvertVector3fToPdVector3(R: TVector3f): PdVector3;
  237. begin
  238. result[0] := R.X;
  239. result[1] := R.Y;
  240. result[2] := R.Z;
  241. end;
  242. function ConvertVector4fTodVector3(R: TVector4f): TdVector3;
  243. begin
  244. result[0] := R.X;
  245. result[1] := R.Y;
  246. result[2] := R.Z;
  247. result[3] := 0;
  248. end;
  249. function ConvertVector4fToPdVector3(R: TVector4f): PdVector3;
  250. begin
  251. result[0] := R.X;
  252. result[1] := R.Y;
  253. result[2] := R.Z;
  254. result[3] := 0;
  255. end;
  256. (*$WARNINGS ON*)
  257. function GetBodyPositionAsAffineVector(Body: PdxBody): TAffineVector;
  258. begin
  259. result := ConvertdVector3ToVector3f(dBodyGetPosition(Body));
  260. end;
  261. procedure PositionSceneObjectForGeom(Geom: PdxGeom);
  262. begin
  263. if Assigned(Geom.Data) then
  264. PositionSceneObject(TGLBaseSceneObject(Geom.Data), Geom);
  265. end;
  266. function GLMatrixFromGeom(Geom: PdxGeom): TGLMatrix;
  267. var
  268. pos, Pos2: PdVector3;
  269. R, R2: PdMatrix3;
  270. actual_pos: TdVector3;
  271. actual_R: TdMatrix3;
  272. TransformedGeom: PdxGeom;
  273. GeomClass: integer;
  274. begin
  275. // Retrieve the position and rotation of the geom
  276. pos := dGeomGetPosition(geom);
  277. R := dGeomGetRotation(geom);
  278. // if the geom is a transform geom, it should be treated differently
  279. GeomClass := dGeomGetClass(Geom);
  280. if GeomClass = dGeomTransformClass then
  281. begin
  282. TransformedGeom := dGeomTransformGetGeom(Geom);
  283. // No transformed geom!?
  284. if TransformedGeom = nil then
  285. exit;
  286. // Retrieve the position and rotation of the transformed geom
  287. pos2 := dGeomGetPosition(TransformedGeom);
  288. R2 := dGeomGetRotation(TransformedGeom);
  289. dMULTIPLY0_331(actual_pos, R^, pos2^);
  290. actual_pos := Vector3ADD(actual_pos, pos^);
  291. dMULTIPLY0_333(actual_R, R^, R2^);
  292. ODERToGLSceneMatrix(result, actual_R, actual_pos);
  293. end
  294. else
  295. begin
  296. ODERToGLSceneMatrix(result, R, pos);
  297. end;
  298. end;
  299. function GLDirectionFromGeom(Geom: PdxGeom): TGLVector;
  300. var
  301. m: TGLMatrix;
  302. begin
  303. m := GLMatrixFromGeom(Geom);
  304. result := VectorNormalize(m.Z);
  305. end;
  306. procedure PositionSceneObject(GLBaseSceneObject: TGLBaseSceneObject; Geom: PdxGeom);
  307. var
  308. Scale: TAffineVector;
  309. begin
  310. Scale := GLBaseSceneObject.Scale.AsAffineVector;
  311. GLBaseSceneObject.SetMatrix(GLMatrixFromGeom(Geom));
  312. GLBaseSceneObject.Scale.AsAffineVector := Scale;
  313. end;
  314. procedure CopyCubeSizeFromBox(Cube: TGLCube; Geom: PdxGeom);
  315. var
  316. Sides: TdVector3;
  317. begin
  318. dGeomBoxGetLengths(Geom, Sides);
  319. Cube.CubeWidth := Sides[0]; // 0
  320. Cube.CubeHeight := Sides[1]; // 1
  321. Cube.CubeDepth := Sides[2]; // 2
  322. end;
  323. procedure CopyPosFromGeomToGL(Geom: PdxGeom; GLBaseSceneObject: TGLBaseSceneObject);
  324. var
  325. v: TGLVector;
  326. m: TGLMatrix;
  327. R: PdMatrix3;
  328. pos: PdVector3;
  329. begin
  330. v := GLBaseSceneObject.AbsolutePosition;
  331. dGeomSetPosition(Geom, v.X, v.Y, v.Z);
  332. R := dGeomGetRotation(Geom);
  333. pos := dgeomGetPosition(Geom);
  334. m := GLBaseSceneObject.AbsoluteMatrix;
  335. R[0] := m.X.X;
  336. R[4] := m.X.Y;
  337. R[8] := m.X.Z;
  338. R[1] := m.Y.X;
  339. R[5] := m.Y.Y;
  340. R[9] := m.Y.Z;
  341. R[2] := m.Z.X;
  342. R[6] := m.Z.Y;
  343. R[10] := m.Z.Z;
  344. pos[0] := m.W.X;
  345. pos[1] := m.W.Y;
  346. pos[2] := m.W.Z; //}
  347. dGeomSetRotation(Geom, R^);
  348. end;
  349. function CreateGeomFromCube(Cube: TGLCube; Space: PdxSpace): PdxGeom;
  350. var
  351. Geom: PdxGeom;
  352. begin
  353. Geom := dCreateBox(Space, Cube.CubeWidth, Cube.CubeHeight, Cube.CubeDepth);
  354. CopyPosFromGeomToGL(Geom, Cube);
  355. result := Geom;
  356. end;
  357. function CreateBodyFromCube(var Geom: PdxGeom; Cube: TGLCube; World: PdxWorld; Space: PdxSpace): PdxBody;
  358. var
  359. Body: PdxBody;
  360. begin
  361. Body := dBodyCreate(World);
  362. try
  363. dBodySetLinearVel(Body, 0, 0, 0);
  364. CopyBodyFromCube(Body, Geom, Cube, Space);
  365. finally
  366. result := Body;
  367. end;
  368. end;
  369. function CreateTriMeshFromBaseMesh(
  370. GLBaseMesh: TGLBaseMesh;
  371. Space: PdxSpace;
  372. var Vertices: PdVector3Array;
  373. var Indices: PdIntegerArray): PdxGeom;
  374. var
  375. i, j, p: integer;
  376. FaceExtractor: TGLFaceExtractor;
  377. VertexCount: integer;
  378. Vertex: TAffineVector;
  379. OffsetList: TGLIntegerList;
  380. Face: TGLFace;
  381. iMO: integer;
  382. TriMeshData: PdxTriMeshData;
  383. begin
  384. OffsetList := nil;
  385. FaceExtractor := TGLFaceExtractor.Create(GLBaseMesh);
  386. try
  387. OffsetList := TGLIntegerList.Create;
  388. FaceExtractor.ProcessMesh;
  389. VertexCount := 0;
  390. for i := 0 to GLBaseMesh.MeshObjects.Count - 1 do
  391. VertexCount := VertexCount + GLBaseMesh.MeshObjects[i].Vertices.Count;
  392. Vertices := AllocMem(sizeOf(TdVector3) * VertexCount);
  393. Indices := AllocMem(sizeOf(integer) * FaceExtractor.FaceList.Count * 3);
  394. // Copy all vertices
  395. p := 0;
  396. for i := 0 to GLBaseMesh.MeshObjects.Count - 1 do
  397. begin
  398. OffsetList.Add(p);
  399. for j := 0 to GLBaseMesh.MeshObjects[i].Vertices.Count - 1 do
  400. begin
  401. Vertex :=
  402. GLBaseMesh.LocalToAbsolute(GLBaseMesh.MeshObjects[i].Vertices[j]);
  403. Vertices^[p, 0] := Vertex.X;
  404. Vertices^[p, 1] := Vertex.Y;
  405. Vertices^[p, 2] := Vertex.Z;
  406. Vertices^[p, 3] := 0;
  407. inc(p);
  408. end;
  409. end;
  410. // Copy all triangles
  411. p := 0;
  412. for i := 0 to FaceExtractor.FaceList.Count - 1 do
  413. begin
  414. Face := FaceExtractor.FaceList[i];
  415. iMO := GLBaseMesh.MeshObjects.IndexOf(Face.MeshObject);
  416. Indices^[p] := Face.Vertices[0] + OffsetList[iMO];
  417. inc(p);
  418. Indices^[p] := Face.Vertices[1] + OffsetList[iMO];
  419. inc(p);
  420. Indices^[p] := Face.Vertices[2] + OffsetList[iMO];
  421. inc(p);
  422. end;
  423. TriMeshData := dGeomTriMeshDataCreate;
  424. dGeomTriMeshDataBuildSimple(
  425. TriMeshData,
  426. Vertices, VertexCount,
  427. Indices, FaceExtractor.FaceList.Count * 3);
  428. result := dCreateTriMesh(space, TriMeshData, nil, nil, nil);
  429. finally
  430. FaceExtractor.Free;
  431. if OffsetList <> nil then
  432. OffsetList.Free;
  433. end;
  434. end;
  435. procedure CopyBodyFromCube(Body: PdxBody; var Geom: PdxGeom; Cube: TGLCube;
  436. Space: PdxSpace);
  437. var
  438. m: TdMass;
  439. begin
  440. // Stup the body
  441. dMassSetBox(m, 1, Cube.CubeWidth, Cube.CubeHeight, Cube.CubeDepth);
  442. if m.mass>0 then dBodySetMass(Body, @m);
  443. // Setup the geom
  444. Geom := CreateGeomFromCube(Cube, Space);
  445. dGeomSetBody(Geom, Body);
  446. CopyPosFromGeomToGL(Geom, Cube);
  447. Geom.data := Cube;
  448. end;
  449. function dBodyToBodyDistance(Body1, Body2: PdxBody): TdReal;
  450. begin
  451. result := dVector3Length(Vector3SUB(Body1.posr.pos, Body2.posr.pos));
  452. end;
  453. function dVector3Length(R: TdVector3): single;
  454. begin
  455. result := Sqrt(sqr(R[0]) + sqr(R[1]) + sqr(R[2]));
  456. end;
  457. function dVector3Length(R: PdVector3): single;
  458. begin
  459. result := Sqrt(sqr(R[0]) + sqr(R[1]) + sqr(R[2]));
  460. end;
  461. procedure RenderGeomList(GeomList: TGeomList);
  462. var
  463. i: integer;
  464. begin
  465. for i := 0 to GeomList.Count - 1 do
  466. if Assigned(GeomList[i].data) then
  467. PositionSceneObject(TGLBaseSceneObject(GeomList[i].data), GeomList[i]);
  468. end;
  469. function CreateODEPlaneFromGLPlane(Plane: TGLPlane; Space: PdxSpace): PdxGeom;
  470. var
  471. Pos, Direction: TGLVector;
  472. d: single;
  473. begin
  474. Direction := Plane.AbsoluteDirection;
  475. Pos := Plane.AbsolutePosition;
  476. d := (Direction.X * Pos.X +
  477. Direction.Y * Pos.Y +
  478. Direction.Z * Pos.Z);
  479. result := dCreatePlane(space, Direction.X, Direction.Y, Direction.Z, d);
  480. end;
  481. function RandomColorVector: TGLVector;
  482. begin
  483. result := VectorMake(Random, Random, Random, 1);
  484. end;
  485. end.