GXS.ODEUtils.pas 14 KB

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