2
0

GLS.ODESkeletonColliders.pas 8.5 KB

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