GLDCEMisc.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLDCEMisc;
  5. (* Miscelaneous functions used by DCE (Dynamic Collision Engine) *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. System.Classes,
  10. GLScene,
  11. GLCoordinates,
  12. GLVectorFileObjects,
  13. GLEllipseCollision,
  14. GLVectorGeometry,
  15. GLVectorLists,
  16. GLTerrainRenderer,
  17. GLProxyObjects,
  18. GLMultiProxy,
  19. GLVectorTypes;
  20. //Calculate and set the collision range
  21. procedure ECSetCollisionRange(var MovePack: TECMovePack);
  22. //Set the collider lists to null
  23. procedure ECResetColliders(var MovePack: TECMovePack);
  24. //Add freeform's octree data
  25. procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
  26. Solid: Boolean; ObjectID: Integer);
  27. //Add a TriMesh box
  28. procedure ECAddBox(var MovePack: TECMovePack;
  29. BoxObj: TGLBaseSceneObject; BoxSize: TAffineVector;
  30. Solid: Boolean; ObjectID: Integer);
  31. //Add the terrain as a TriMesh
  32. procedure ECAddTerrain(var MovePack: TECMovePack;
  33. TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
  34. Solid: Boolean; ObjectID: Integer);
  35. //Add a static ellipsoid
  36. procedure ECAddEllipsoid(var MovePack: TECMovePack;
  37. ePos, eRadius: TAffineVector;
  38. Solid: Boolean; ObjectID: Integer);
  39. const
  40. DCEBox: array [0..35] of TAffineVector = (
  41. (X: 1; Y:-1; Z:-1), (X: 1; Y: 1; Z:-1), (X: 1; Y:-1; Z: 1),
  42. (X: 1; Y: 1; Z:-1), (X: 1; Y: 1; Z: 1), (X: 1; Y:-1; Z: 1),
  43. (X: 1; Y: 1; Z:-1), (X:-1; Y: 1; Z:-1), (X:-1; Y: 1; Z: 1),
  44. (X: 1; Y: 1; Z: 1), (X: 1; Y: 1; Z:-1), (X:-1; Y: 1; Z: 1),
  45. (X:-1; Y: 1; Z: 1), (X:-1; Y:-1; Z: 1), (X: 1; Y:-1; Z: 1),
  46. (X: 1; Y: 1; Z: 1), (X:-1; Y: 1; Z: 1), (X: 1; Y:-1; Z: 1),
  47. (X:-1; Y:-1; Z: 1), (X:-1; Y: 1; Z: 1), (X:-1; Y: 1; Z:-1),
  48. (X:-1; Y:-1; Z:-1), (X:-1; Y:-1; Z: 1), (X:-1; Y: 1; Z:-1),
  49. (X: 1; Y:-1; Z: 1), (X:-1; Y:-1; Z: 1), (X: 1; Y:-1; Z:-1),
  50. (X:-1; Y:-1; Z: 1), (X:-1; Y:-1; Z:-1), (X: 1; Y:-1; Z:-1),
  51. (X: 1; Y: 1; Z:-1), (X: 1; Y:-1; Z:-1), (X:-1; Y: 1; Z:-1),
  52. (X: 1; Y:-1; Z:-1), (X:-1; Y:-1; Z:-1), (X:-1; Y: 1; Z:-1)
  53. );
  54. //--------------------------------------------------
  55. implementation
  56. //--------------------------------------------------
  57. procedure ECSetCollisionRange(var MovePack: TECMovePack);
  58. var N: TAffineVector;
  59. begin
  60. N.X := Abs(MovePack.Velocity.X) + Abs(MovePack.Gravity.X) + (MovePack.Radius.X);
  61. N.Y := Abs(MovePack.Velocity.Y) + Abs(MovePack.Gravity.Y) + (MovePack.Radius.Y);
  62. N.Z := Abs(MovePack.Velocity.Z) + Abs(MovePack.Gravity.Z) + (MovePack.Radius.Z);
  63. MovePack.CollisionRange := MaxXYZComponent(N);
  64. end;
  65. procedure ECResetColliders(var MovePack: TECMovePack);
  66. begin
  67. SetLength(MovePack.TriMeshes,0);
  68. SetLength(MovePack.Freeforms,0);
  69. SetLength(MovePack.Colliders,0);
  70. end;
  71. procedure ECAddFreeForm(var MovePack: TECMovePack; FreeForm: TGLBaseSceneObject;
  72. Solid: Boolean; ObjectID: Integer);
  73. var
  74. i, count : Integer;
  75. Pos: TVector;
  76. Master: TGLBaseSceneObject;
  77. d1,d2: Single;
  78. begin
  79. Master := FreeForm;
  80. if Master is TGLFreeFormProxy then
  81. Master := TGLFreeFormProxy(Master).MasterObject;
  82. if Master is TGLMultiProxy then
  83. if TGLMultiProxy(Master).MasterObjects.Count > 0 then
  84. Master := TGLMultiProxy(Master).MasterObjects[0].MasterObject;
  85. Assert((Master is TGLFreeForm), 'Object must be freeform, freeformproxy or freeformbased Multiproxy.');
  86. Assert(Assigned(TGLFreeForm(Master).Octree), 'Octree must have been prepared and setup before use.');
  87. SetVector(Pos, FreeForm.AbsoluteToLocal(MovePack.Position));
  88. //Is in boundingsphere?
  89. d1 := VectorDistance2(MovePack.Position,AffineVectorMake(FreeForm.AbsolutePosition));
  90. d2 := sqr(MovePack.CollisionRange + Freeform.BoundingSphereRadius);
  91. if d1 > d2 then exit;
  92. count := Length(MovePack.Freeforms);
  93. with TGLFreeForm(Master).Octree do
  94. begin
  95. WalkSphereToLeaf(RootNode, Pos, MovePack.CollisionRange);
  96. if not Assigned(resultarray) then exit;
  97. //Copy the result array
  98. SetLength(MovePack.Freeforms,count+1);
  99. SetLength(MovePack.Freeforms[count].OctreeNodes, Length(resultarray));
  100. for i := 0 to High(resultarray) do
  101. MovePack.Freeforms[count].OctreeNodes[i] := resultarray[i];
  102. //Reference to this octree
  103. MovePack.Freeforms[count].triangleFiler := @triangleFiler;
  104. MovePack.Freeforms[count].ObjectInfo.AbsoluteMatrix := Freeform.AbsoluteMatrix;
  105. MovePack.Freeforms[count].ObjectInfo.Solid := Solid;
  106. MovePack.Freeforms[count].ObjectInfo.ObjectID := ObjectID;
  107. MovePack.Freeforms[count].InvertedNormals := TGLFreeForm(Master).NormalsOrientation = mnoInvert;
  108. end;
  109. end;
  110. procedure ECAddBox(var MovePack: TECMovePack;
  111. BoxObj: TGLBaseSceneObject; BoxSize: TAffineVector;
  112. Solid: Boolean; ObjectID: Integer);
  113. var t,count,i : Integer;
  114. p1, p2, p3: TAffineVector;
  115. BoxRadius,d1,d2: Single;
  116. begin
  117. BoxRadius := MaxXYZComponent(BoxSize)*MaxXYZComponent(BoxObj.Scale.AsAffineVector);
  118. d1 := VectorDistance2(MovePack.Position,AffineVectorMake(BoxObj.AbsolutePosition));
  119. d2 := sqr(MovePack.CollisionRange + BoxRadius);
  120. if d1 > d2 then exit;
  121. //Add the box to the triangle list
  122. t := Length(MovePack.TriMeshes);
  123. SetLength(MovePack.TriMeshes,t+1);
  124. ScaleVector(BoxSize,0.5);
  125. count := 0;
  126. i := 0;
  127. while i < 36 do
  128. begin
  129. count := count + 1;
  130. SetLength(MovePack.TriMeshes[t].Triangles,count);
  131. with MovePack.TriMeshes[t] do
  132. begin
  133. p1 := DCEBox[i]; ScaleVector(p1,BoxSize); p1 := BoxObj.LocalToAbsolute(p1);
  134. p2 := DCEBox[i+1]; ScaleVector(p2,BoxSize); p2 := BoxObj.LocalToAbsolute(p2);
  135. p3 := DCEBox[i+2]; ScaleVector(p3,BoxSize); p3 := BoxObj.LocalToAbsolute(p3);
  136. i := i + 3;
  137. SetVector(Triangles[count-1].p1, p1);
  138. SetVector(Triangles[count-1].p2, p2);
  139. SetVector(Triangles[count-1].p3, p3);
  140. ObjectInfo.Solid := Solid;
  141. ObjectInfo.ObjectID := ObjectID;
  142. end;
  143. end;
  144. end;
  145. procedure ECAddTerrain(var MovePack: TECMovePack;
  146. TerrainRenderer: TGLTerrainRenderer; Resolution: Single;
  147. Solid: Boolean; ObjectID: Integer);
  148. function intvec(x,z: Single): TAffineVector;
  149. begin
  150. result.X := x + MovePack.Position.X;
  151. result.Y := 0 + MovePack.Position.Y;
  152. result.Z := z + MovePack.Position.Z;
  153. end;
  154. function locabs(x,y,z: Single): TAffineVector;
  155. begin
  156. //result := TerrainRenderer.LocalToAbsolute(AffineVectorMake(x,y,z));
  157. //result := AffineVectorMake(x,y,z);
  158. result.X := x + MovePack.Position.X;
  159. result.Y := y + TerrainRenderer.AbsolutePosition.Y;
  160. result.Z := z + MovePack.Position.Z;
  161. end;
  162. var count,t : Integer;
  163. x,y,z: Single;
  164. begin
  165. //Add the terrain to the list
  166. count := Length(MovePack.TriMeshes);
  167. SetLength(MovePack.TriMeshes,count+1);
  168. with MovePack.TriMeshes[count] do
  169. begin
  170. ObjectInfo.Solid := Solid;
  171. ObjectInfo.ObjectID := ObjectID;
  172. t := 0;
  173. x := - MovePack.CollisionRange;
  174. while x < MovePack.CollisionRange do
  175. begin
  176. z := - MovePack.CollisionRange;
  177. while z < MovePack.CollisionRange do
  178. begin
  179. //Add 2 triangles
  180. t := t + 2;
  181. SetLength(Triangles, t);
  182. //Tri 1
  183. y := TerrainRenderer.InterpolatedHeight(intvec(x,z));
  184. Triangles[t-2].p1 := locabs(x,y,z);
  185. y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
  186. Triangles[t-2].p2 := locabs(x,y,z+Resolution);
  187. y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
  188. Triangles[t-2].p3 := locabs(x+Resolution,y,z);
  189. //Tri 2
  190. y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z+Resolution));
  191. Triangles[t-1].p1 := locabs(x+Resolution,y,z+Resolution);
  192. y := TerrainRenderer.InterpolatedHeight(intvec(x+Resolution,z));
  193. Triangles[t-1].p2 := locabs(x+Resolution,y,z);
  194. y := TerrainRenderer.InterpolatedHeight(intvec(x,z+Resolution));
  195. Triangles[t-1].p3 := locabs(x,y,z+Resolution);
  196. z := z + Resolution;
  197. end;
  198. x := x + Resolution;
  199. end;
  200. end;
  201. end;
  202. procedure ECAddEllipsoid(var MovePack: TECMovePack; ePos, eRadius: TAffineVector;
  203. Solid: Boolean; ObjectID: Integer);
  204. var count : Integer;
  205. d1, d2, r: single;
  206. begin
  207. r := MaxXYZComponent(eRadius);
  208. d1 := VectorDistance2(MovePack.Position,ePos);
  209. d2 := sqr(MovePack.CollisionRange + r);
  210. if d1 > d2 then exit;
  211. //Add possible collider
  212. count := Length(MovePack.Colliders);
  213. SetLength(MovePack.Colliders,count+1);
  214. with MovePack.Colliders[count] do
  215. begin
  216. Position := ePos;
  217. Radius := eRadius;
  218. ObjectInfo.Solid := Solid;
  219. ObjectInfo.ObjectID := ObjectID;
  220. end;
  221. end;
  222. end.