GLS.ODESkeletonColliders.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.ODESkeletonColliders;
  5. (* Skeleton colliders for defining and controlling ODE geoms. *)
  6. interface
  7. uses
  8. System.Classes,
  9. Stage.VectorTypes,
  10. GLS.PersistentClasses,
  11. Stage.VectorGeometry,
  12. GLS.VectorFileObjects,
  13. ODE.Import;
  14. type
  15. // Base ODE skeleton collider class
  16. TSCODEBase = class(TGLSkeletonCollider)
  17. private
  18. FGeom: PdxGeom;
  19. public
  20. procedure WriteToFiler(writer: TGLVirtualWriter); override;
  21. procedure ReadFromFiler(reader: TGLVirtualReader); 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: TGLVirtualWriter); override;
  36. procedure ReadFromFiler(reader: TGLVirtualReader); 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: TGLVirtualWriter); override;
  50. procedure ReadFromFiler(reader: TGLVirtualReader); 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: TGLVirtualWriter); override;
  66. procedure ReadFromFiler(reader: TGLVirtualReader); 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 skeleton collider list to a given ODE space
  73. procedure AddSCODEGeomsToODESpace(colliders: TGLSkeletonColliderList; Space: PdxSpace);
  74. // ------------------------------------------------------------------
  75. implementation
  76. // ------------------------------------------------------------------
  77. // ------------------
  78. // ------------------ Global methods ------------------
  79. // ------------------
  80. procedure AddSCODEGeomsToODESpace(colliders: TGLSkeletonColliderList; Space: PdxSpace);
  81. var
  82. i: Integer;
  83. begin
  84. for i := 0 to colliders.Count - 1 do
  85. if colliders[i] is TSCODEBase then
  86. TSCODEBase(colliders[i]).AddToSpace(Space);
  87. end;
  88. // ------------------
  89. // ------------------ TSCODEBase ------------------
  90. // ------------------
  91. procedure TSCODEBase.WriteToFiler(writer: TGLVirtualWriter);
  92. begin
  93. inherited WriteToFiler(writer);
  94. with writer do
  95. begin
  96. WriteInteger(0); // Archive Version 0
  97. end;
  98. end;
  99. procedure TSCODEBase.ReadFromFiler(reader: TGLVirtualReader);
  100. var
  101. archiveVersion: Integer;
  102. begin
  103. inherited ReadFromFiler(reader);
  104. archiveVersion := reader.ReadInteger;
  105. if archiveVersion = 0 then
  106. with reader do
  107. // Nothing yet
  108. else
  109. RaiseFilerException(archiveVersion);
  110. end;
  111. procedure TSCODEBase.AddToSpace(Space: PdxSpace);
  112. begin
  113. AlignCollider;
  114. end;
  115. procedure TSCODEBase.AlignCollider;
  116. var
  117. R: TdMatrix3;
  118. Mat: TGLMatrix;
  119. begin
  120. inherited;
  121. if Assigned(FGeom) then
  122. begin
  123. Mat := GlobalMatrix;
  124. dGeomSetPosition(FGeom, Mat.V[3].X, Mat.V[3].Y, Mat.V[3].Z);
  125. R[0] := Mat.V[0].X;
  126. R[1] := Mat.V[1].X;
  127. R[2] := Mat.V[2].X;
  128. R[3] := 0;
  129. R[4] := Mat.V[0].Y;
  130. R[5] := Mat.V[1].Y;
  131. R[6] := Mat.V[2].Y;
  132. R[7] := 0;
  133. R[8] := Mat.V[0].Z;
  134. R[9] := Mat.V[1].Z;
  135. R[10] := Mat.V[2].Z;
  136. R[11] := 0;
  137. dGeomSetRotation(FGeom, R);
  138. end;
  139. end;
  140. // ------------------
  141. // ------------------ TSCODESphere ------------------
  142. // ------------------
  143. constructor TSCODESphere.Create;
  144. begin
  145. inherited;
  146. FRadius := 0.5;
  147. AlignCollider;
  148. end;
  149. procedure TSCODESphere.WriteToFiler(writer: TGLVirtualWriter);
  150. begin
  151. inherited WriteToFiler(writer);
  152. with writer do
  153. begin
  154. WriteInteger(0); // Archive Version 0
  155. WriteFloat(FRadius);
  156. end;
  157. end;
  158. procedure TSCODESphere.ReadFromFiler(reader: TGLVirtualReader);
  159. var
  160. archiveVersion: Integer;
  161. begin
  162. inherited ReadFromFiler(reader);
  163. archiveVersion := reader.ReadInteger;
  164. if archiveVersion = 0 then
  165. with reader do
  166. Radius := ReadFloat
  167. else
  168. RaiseFilerException(archiveVersion);
  169. end;
  170. procedure TSCODESphere.AddToSpace(Space: PdxSpace);
  171. begin
  172. FGeom := dCreateSphere(Space, FRadius);
  173. inherited;
  174. end;
  175. procedure TSCODESphere.SetRadius(const val: TdReal);
  176. begin
  177. if val <> FRadius then
  178. begin
  179. FRadius := val;
  180. if Assigned(FGeom) then
  181. dGeomSphereSetRadius(Geom, TdReal(FRadius));
  182. end;
  183. end;
  184. // ------------------
  185. // ------------------ TSCODECCylinder ------------------
  186. // ------------------
  187. constructor TSCODECCylinder.Create;
  188. begin
  189. inherited;
  190. FRadius := 0.5;
  191. FLength := 1;
  192. AlignCollider;
  193. end;
  194. procedure TSCODECCylinder.WriteToFiler(writer: TGLVirtualWriter);
  195. begin
  196. inherited WriteToFiler(writer);
  197. with writer do
  198. begin
  199. WriteInteger(0); // Archive Version 0
  200. WriteFloat(FRadius);
  201. WriteFloat(FLength);
  202. end;
  203. end;
  204. procedure TSCODECCylinder.ReadFromFiler(reader: TGLVirtualReader);
  205. var
  206. archiveVersion: Integer;
  207. begin
  208. inherited ReadFromFiler(reader);
  209. archiveVersion := reader.ReadInteger;
  210. if archiveVersion = 0 then
  211. with reader do
  212. begin
  213. Radius := ReadFloat;
  214. Length := ReadFloat;
  215. end
  216. else
  217. RaiseFilerException(archiveVersion);
  218. end;
  219. procedure TSCODECCylinder.AddToSpace(Space: PdxSpace);
  220. begin
  221. FGeom := dCreateCapsule(Space, FRadius, FLength);
  222. inherited;
  223. end;
  224. procedure TSCODECCylinder.SetRadius(const val: Single);
  225. begin
  226. if val <> FRadius then
  227. begin
  228. FRadius := val;
  229. if Assigned(FGeom) then
  230. dGeomCapsuleSetParams(FGeom, FRadius, FLength);
  231. end;
  232. end;
  233. procedure TSCODECCylinder.SetLength(const val: Single);
  234. begin
  235. if val <> FLength then
  236. begin
  237. FLength := val;
  238. if Assigned(FGeom) then
  239. dGeomCapsuleSetParams(FGeom, FRadius, FLength);
  240. end;
  241. end;
  242. // ------------------
  243. // ------------------ TSCODEBox ------------------
  244. // ------------------
  245. constructor TSCODEBox.Create;
  246. begin
  247. inherited;
  248. FBoxWidth := 1;
  249. FBoxHeight := 1;
  250. FBoxDepth := 1;
  251. AlignCollider;
  252. end;
  253. procedure TSCODEBox.WriteToFiler(writer: TGLVirtualWriter);
  254. begin
  255. inherited WriteToFiler(writer);
  256. with writer do
  257. begin
  258. WriteInteger(0); // Archive Version 0
  259. WriteFloat(FBoxWidth);
  260. WriteFloat(FBoxHeight);
  261. WriteFloat(FBoxDepth);
  262. end;
  263. end;
  264. procedure TSCODEBox.ReadFromFiler(reader: TGLVirtualReader);
  265. var
  266. archiveVersion: Integer;
  267. begin
  268. inherited ReadFromFiler(reader);
  269. archiveVersion := reader.ReadInteger;
  270. if archiveVersion = 0 then
  271. with reader do
  272. begin
  273. BoxWidth := ReadFloat;
  274. BoxHeight := ReadFloat;
  275. BoxDepth := ReadFloat;
  276. end
  277. else
  278. RaiseFilerException(archiveVersion);
  279. end;
  280. procedure TSCODEBox.AddToSpace(Space: PdxSpace);
  281. begin
  282. FGeom := dCreateBox(Space, FBoxWidth, FBoxHeight, FBoxDepth);
  283. inherited;
  284. end;
  285. procedure TSCODEBox.SetBoxWidth(const val: TdReal);
  286. begin
  287. if val <> FBoxWidth then
  288. begin
  289. FBoxWidth := val;
  290. if Assigned(FGeom) then
  291. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight), TdReal(FBoxDepth));
  292. end;
  293. end;
  294. procedure TSCODEBox.SetBoxHeight(const val: TdReal);
  295. begin
  296. if val <> FBoxHeight then
  297. begin
  298. FBoxHeight := val;
  299. if Assigned(FGeom) then
  300. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight), TdReal(FBoxDepth));
  301. end;
  302. end;
  303. procedure TSCODEBox.SetBoxDepth(const val: TdReal);
  304. begin
  305. if val <> FBoxDepth then
  306. begin
  307. FBoxDepth := val;
  308. if Assigned(FGeom) then
  309. dGeomBoxSetLengths(Geom, TdReal(FBoxWidth), TdReal(FBoxHeight), TdReal(FBoxDepth));
  310. end;
  311. end;
  312. // ------------------------------------------------------------------
  313. initialization
  314. // ------------------------------------------------------------------
  315. RegisterClasses([TSCODEBase,TSCODESphere,TSCODECCylinder,TSCODEBox]);
  316. end.