GXS.ODESkeletonColliders.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.ODESkeletonColliders;
  5. (* Skeleton colliders for defining and controlling ODE geoms *)
  6. interface
  7. uses
  8. System.Classes,
  9. ODE.Import,
  10. Stage.VectorTypes,
  11. GXS.PersistentClasses,
  12. Stage.VectorGeometry,
  13. GXS.VectorFileObjects;
  14. type
  15. // Base ODE skeleton collider class.
  16. TSCODEBase = class(TgxSkeletonCollider)
  17. private
  18. FGeom: PdxGeom;
  19. public
  20. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  21. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  22. procedure AddToSpace(Space: PdxSpace); virtual;
  23. procedure AlignCollider; override;
  24. // The geoms are created through the AddToSpace procedure
  25. property Geom: PdxGeom read FGeom;
  26. end;
  27. // Sphere shaped ODE geom in a skeleton collider.
  28. TSCODESphere = class(TSCODEBase)
  29. private
  30. FRadius: TdReal;
  31. protected
  32. procedure SetRadius(const val: TdReal);
  33. public
  34. constructor Create; override;
  35. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  36. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  37. procedure AddToSpace(Space: PdxSpace); override;
  38. property Radius: TdReal read FRadius write SetRadius;
  39. end;
  40. // Capsule (sphere capped cylinder) shaped ODE geom in a skeleton collider.
  41. TSCODECCylinder = class(TSCODEBase)
  42. private
  43. FRadius, FLength: Single;
  44. protected
  45. procedure SetRadius(const val: Single);
  46. procedure SetLength(const val: Single);
  47. public
  48. constructor Create; override;
  49. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  50. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  51. procedure AddToSpace(Space: PdxSpace); override;
  52. property Radius: Single read FRadius write SetRadius;
  53. property Length: Single read FLength write SetLength;
  54. end;
  55. // Box shaped ODE geom in a skeleton collider.
  56. TSCODEBox = class(TSCODEBase)
  57. private
  58. FBoxWidth, FBoxHeight, FBoxDepth: TdReal;
  59. protected
  60. procedure SetBoxWidth(const val: TdReal);
  61. procedure SetBoxHeight(const val: TdReal);
  62. procedure SetBoxDepth(const val: TdReal);
  63. public
  64. constructor Create; override;
  65. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  66. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  67. procedure AddToSpace(Space: PdxSpace); override;
  68. property BoxWidth: TdReal read FBoxWidth write SetBoxWidth;
  69. property BoxHeight: TdReal read FBoxHeight write SetBoxHeight;
  70. property BoxDepth: TdReal read FBoxDepth write SetBoxDepth;
  71. end;
  72. (* After loading call this function to add all the geoms in a
  73. skeleton collider list to a given ODE space. *)
  74. procedure AddSCODEGeomsToODESpace(colliders: TgxSkeletonColliderList;
  75. Space: PdxSpace);
  76. // ------------------------------------------------------------------
  77. implementation
  78. // ------------------------------------------------------------------
  79. // ------------------
  80. // ------------------ Global methods ------------------
  81. // ------------------
  82. procedure AddSCODEGeomsToODESpace(colliders: TgxSkeletonColliderList;
  83. Space: PdxSpace);
  84. var
  85. i: Integer;
  86. begin
  87. for i := 0 to colliders.Count - 1 do
  88. if colliders[i] is TSCODEBase then
  89. TSCODEBase(colliders[i]).AddToSpace(Space);
  90. end;
  91. // ------------------
  92. // ------------------ TSCODEBase ------------------
  93. // ------------------
  94. procedure TSCODEBase.WriteToFiler(writer: TgxVirtualWriter);
  95. begin
  96. inherited WriteToFiler(writer);
  97. with writer do
  98. begin
  99. WriteInteger(0); // Archive Version 0
  100. end;
  101. end;
  102. procedure TSCODEBase.ReadFromFiler(reader: TgxVirtualReader);
  103. var
  104. archiveVersion: Integer;
  105. begin
  106. inherited ReadFromFiler(reader);
  107. archiveVersion := reader.ReadInteger;
  108. if archiveVersion = 0 then
  109. with reader do
  110. // Nothing yet
  111. else
  112. RaiseFilerException(archiveVersion);
  113. end;
  114. procedure TSCODEBase.AddToSpace(Space: PdxSpace);
  115. begin
  116. AlignCollider;
  117. end;
  118. procedure TSCODEBase.AlignCollider;
  119. var
  120. R: TdMatrix3;
  121. Mat: TMatrix4f;
  122. begin
  123. inherited;
  124. if Assigned(FGeom) then
  125. begin
  126. Mat := GlobalMatrix;
  127. dGeomSetPosition(FGeom, Mat.W.X, Mat.W.Y, Mat.W.Z);
  128. R[0] := Mat.X.X;
  129. R[1] := Mat.Y.X;
  130. R[2] := Mat.Z.X;
  131. R[3] := 0;
  132. R[4] := Mat.X.Y;
  133. R[5] := Mat.Y.Y;
  134. R[6] := Mat.Z.Y;
  135. R[7] := 0;
  136. R[8] := Mat.X.Z;
  137. R[9] := Mat.Y.Z;
  138. R[10] := Mat.Z.Z;
  139. R[11] := 0;
  140. dGeomSetRotation(FGeom, R);
  141. end;
  142. end;
  143. // ------------------
  144. // ------------------ TSCODESphere ------------------
  145. // ------------------
  146. constructor TSCODESphere.Create;
  147. begin
  148. inherited;
  149. FRadius := 0.5;
  150. AlignCollider;
  151. end;
  152. procedure TSCODESphere.WriteToFiler(writer: TgxVirtualWriter);
  153. begin
  154. inherited WriteToFiler(writer);
  155. with writer do
  156. begin
  157. WriteInteger(0); // Archive Version 0
  158. WriteFloat(FRadius);
  159. end;
  160. end;
  161. procedure TSCODESphere.ReadFromFiler(reader: TgxVirtualReader);
  162. var
  163. archiveVersion: Integer;
  164. begin
  165. inherited ReadFromFiler(reader);
  166. archiveVersion := reader.ReadInteger;
  167. if archiveVersion = 0 then
  168. with reader do
  169. Radius := ReadFloat
  170. else
  171. RaiseFilerException(archiveVersion);
  172. end;
  173. procedure TSCODESphere.AddToSpace(Space: PdxSpace);
  174. begin
  175. FGeom := dCreateSphere(Space, FRadius);
  176. inherited;
  177. end;
  178. procedure TSCODESphere.SetRadius(const val: TdReal);
  179. begin
  180. if val <> FRadius then
  181. begin
  182. FRadius := val;
  183. if Assigned(FGeom) then
  184. dGeomSphereSetRadius(Geom, TdReal(FRadius));
  185. end;
  186. end;
  187. // ------------------
  188. // ------------------ TSCODECCylinder ------------------
  189. // ------------------
  190. constructor TSCODECCylinder.Create;
  191. begin
  192. inherited;
  193. FRadius := 0.5;
  194. FLength := 1;
  195. AlignCollider;
  196. end;
  197. procedure TSCODECCylinder.WriteToFiler(writer: TgxVirtualWriter);
  198. begin
  199. inherited WriteToFiler(writer);
  200. with writer do
  201. begin
  202. WriteInteger(0); // Archive Version 0
  203. WriteFloat(FRadius);
  204. WriteFloat(FLength);
  205. end;
  206. end;
  207. procedure TSCODECCylinder.ReadFromFiler(reader: TgxVirtualReader);
  208. var
  209. archiveVersion: Integer;
  210. begin
  211. inherited ReadFromFiler(reader);
  212. archiveVersion := reader.ReadInteger;
  213. if archiveVersion = 0 then
  214. with reader do
  215. begin
  216. Radius := ReadFloat;
  217. Length := ReadFloat;
  218. end
  219. else
  220. RaiseFilerException(archiveVersion);
  221. end;
  222. procedure TSCODECCylinder.AddToSpace(Space: PdxSpace);
  223. begin
  224. FGeom := dCreateCapsule(Space, FRadius, FLength);
  225. inherited;
  226. end;
  227. procedure TSCODECCylinder.SetRadius(const val: Single);
  228. begin
  229. if val <> FRadius then
  230. begin
  231. FRadius := val;
  232. if Assigned(FGeom) then
  233. dGeomCapsuleSetParams(FGeom, FRadius, FLength);
  234. end;
  235. end;
  236. procedure TSCODECCylinder.SetLength(const val: Single);
  237. begin
  238. if val <> FLength then
  239. begin
  240. FLength := val;
  241. if Assigned(FGeom) then
  242. dGeomCapsuleSetParams(FGeom, FRadius, FLength);
  243. end;
  244. end;
  245. // ------------------
  246. // ------------------ TSCODEBox ------------------
  247. // ------------------
  248. constructor TSCODEBox.Create;
  249. begin
  250. inherited;
  251. FBoxWidth := 1;
  252. FBoxHeight := 1;
  253. FBoxDepth := 1;
  254. AlignCollider;
  255. end;
  256. procedure TSCODEBox.WriteToFiler(writer: TgxVirtualWriter);
  257. begin
  258. inherited WriteToFiler(writer);
  259. with writer do
  260. begin
  261. WriteInteger(0); // Archive Version 0
  262. WriteFloat(FBoxWidth);
  263. WriteFloat(FBoxHeight);
  264. WriteFloat(FBoxDepth);
  265. end;
  266. end;
  267. procedure TSCODEBox.ReadFromFiler(reader: TgxVirtualReader);
  268. var
  269. archiveVersion: Integer;
  270. begin
  271. inherited ReadFromFiler(reader);
  272. archiveVersion := reader.ReadInteger;
  273. if archiveVersion = 0 then
  274. with reader do
  275. begin
  276. BoxWidth := ReadFloat;
  277. BoxHeight := ReadFloat;
  278. BoxDepth := ReadFloat;
  279. end
  280. else
  281. RaiseFilerException(archiveVersion);
  282. end;
  283. procedure TSCODEBox.AddToSpace(Space: PdxSpace);
  284. begin
  285. FGeom := dCreateBox(Space, FBoxWidth, FBoxHeight, FBoxDepth);
  286. inherited;
  287. end;
  288. procedure TSCODEBox.SetBoxWidth(const val: TdReal);
  289. begin
  290. if val <> FBoxWidth then
  291. begin
  292. FBoxWidth := val;
  293. if Assigned(FGeom) then
  294. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight),
  295. TdReal(FBoxDepth));
  296. end;
  297. end;
  298. procedure TSCODEBox.SetBoxHeight(const val: TdReal);
  299. begin
  300. if val <> FBoxHeight then
  301. begin
  302. FBoxHeight := val;
  303. if Assigned(FGeom) then
  304. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight),
  305. TdReal(FBoxDepth));
  306. end;
  307. end;
  308. procedure TSCODEBox.SetBoxDepth(const val: TdReal);
  309. begin
  310. if val <> FBoxDepth then
  311. begin
  312. FBoxDepth := val;
  313. if Assigned(FGeom) then
  314. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight),
  315. TdReal(FBoxDepth));
  316. end;
  317. end;
  318. // ------------------------------------------------------------------
  319. initialization
  320. // ------------------------------------------------------------------
  321. RegisterClasses([TSCODEBase, TSCODESphere, TSCODECCylinder, TSCODEBox]);
  322. end.