fdWalkShoot.pas 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. unit fdWalkShoot;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. System.SysUtils,
  6. System.Variants,
  7. System.Classes,
  8. Vcl.Graphics,
  9. Vcl.Controls,
  10. Vcl.Forms,
  11. Vcl.Dialogs,
  12. Stage.VectorTypes,
  13. Stage.VectorGeometry,
  14. Stage.Keyboard,
  15. Stage.Utils,
  16. GLS.Scene,
  17. GLS.VectorLists,
  18. GLS.PersistentClasses,
  19. GLS.Objects,
  20. GLS.Coordinates,
  21. GLS.Cadencer,
  22. GLS.NGDManager,
  23. GLS.SimpleNavigation,
  24. GLS.SceneViewer,
  25. GLS.BaseClasses,
  26. GLS.VectorFileObjects,
  27. GLS.GeomObjects,
  28. GLS.HUDObjects,
  29. GLS.File3DS,
  30. GLS.Material,
  31. GLS.XCollection;
  32. type
  33. TFormNewtonWalkShoot = class(TForm)
  34. GLScene1: TGLScene;
  35. GLSceneViewer1: TGLSceneViewer;
  36. GLSimpleNavigation1: TGLSimpleNavigation;
  37. GLNGDManager1: TGLNGDManager;
  38. GLCadencer1: TGLCadencer;
  39. GLCamera1: TGLCamera;
  40. GLLightSource1: TGLLightSource;
  41. GLDummyCube1: TGLDummyCube;
  42. World: TGLDummyCube;
  43. GLLines1: TGLLines;
  44. Beer: TGLFreeForm;
  45. Mushroom: TGLFreeForm;
  46. Chair: TGLFreeForm;
  47. Teapot: TGLFreeForm;
  48. Map: TGLFreeForm;
  49. GLHUDCross: TGLHUDSprite;
  50. Body: TGLTorus;
  51. procedure GLCadencer1Progress(Sender: TObject;
  52. const deltaTime, newTime: Double);
  53. procedure FormCreate(Sender: TObject);
  54. procedure FormKeyPress(Sender: TObject; var Key: Char);
  55. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  56. Shift: TShiftState; X, Y: Integer);
  57. procedure GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
  58. Shift: TShiftState; X, Y: Integer);
  59. private
  60. Path: TFileName;
  61. procedure ScaleMesh(freeform: TGLFreeForm; val: Single);
  62. procedure MoveCam(const deltaTime, newTime: Double);
  63. procedure MoveGrab;
  64. public
  65. grabJoint: TGLNGDJoint;
  66. end;
  67. var
  68. FormNewtonWalkShoot: TFormNewtonWalkShoot;
  69. implementation //============================================================
  70. {$R *.dfm}
  71. procedure TFormNewtonWalkShoot.FormCreate(Sender: TObject);
  72. begin
  73. Path := GetCurrentAssetPath();
  74. SetCurrentDir(Path + '\model');
  75. // Set Mesh and scale their vertice position
  76. // because matrix scale is not supported in newton
  77. Map.LoadFromFile('ngdmap1.3ds');
  78. Map.Direction.SetVector(0, 1, 0);
  79. Map.Translate(0, -3, 0);
  80. Beer.LoadFromFile('beer.3ds');
  81. ScaleMesh(Beer, 0.25);
  82. Beer.Translate(-5, 10, 10);
  83. Mushroom.LoadFromFile('mushroom.3ds');
  84. ScaleMesh(Mushroom, 0.1);
  85. Mushroom.Direction.SetVector(0, 1, 0);
  86. Mushroom.Translate(0, 0, -10);
  87. Mushroom.Material.FaceCulling := fcNoCull;
  88. Mushroom.Material.FrontProperties.Emission.SetColor(1, 0.5, 0.5, 0.5);
  89. Chair.LoadFromFile('ngdchair.3ds');
  90. Chair.Direction.SetVector(0, 1, 0);
  91. Chair.Translate(0, 0, -5);
  92. Teapot.LoadFromFile('teapot.3ds');
  93. ScaleMesh(Teapot, 0.05);
  94. Teapot.Direction.SetVector(0, 1, 0);
  95. Teapot.Translate(0, 0, 10);
  96. // Create Physic behavior
  97. GetOrCreateNGDStatic(Map).NGDNewtonCollisions := nc_Tree;
  98. GetNGDStatic(Map).Manager := GLNGDManager1;
  99. // nc_Convex use ConvexCollisionTolerance at creation wich is the resolution
  100. // for collision shape. Bigger the value, lower the collision match,
  101. // but give higher performance (use mdShowGeometry to see the difference at runtime)
  102. GetOrCreateNGDDynamic(Chair).NGDNewtonCollisions := nc_Convex;
  103. GetNGDDynamic(Chair).Manager := GLNGDManager1;
  104. GetOrCreateNGDDynamic(Beer).NGDNewtonCollisions := nc_Convex;
  105. GetNGDDynamic(Beer).Manager := GLNGDManager1;
  106. GetOrCreateNGDDynamic(Teapot).NGDNewtonCollisions := nc_Convex;
  107. GetNGDDynamic(Teapot).Manager := GLNGDManager1;
  108. GetOrCreateNGDDynamic(Mushroom).NGDNewtonCollisions := nc_Convex;
  109. GetNGDDynamic(Mushroom).Manager := GLNGDManager1;
  110. // Move camera in target
  111. GLCamera1.Parent := GLCamera1.TargetObject;
  112. // Create the PickJoint
  113. grabJoint := TGLNGDJoint.Create(GLNGDManager1.NewtonJoint);
  114. grabJoint.JointType := nj_KinematicController;
  115. grabJoint.KinematicControllerOptions.PickModeLinear := True;
  116. grabJoint.KinematicControllerOptions.LinearFriction := 100;
  117. // Set some parameters
  118. GetNGDDynamic(Body).AutoSleep := False;
  119. GLHUDCross.Height := 2;
  120. GLHUDCross.Width := 2;
  121. GLCamera1.NearPlaneBias := 0.1;
  122. GLCamera1.DepthOfView := 1E15;
  123. end;
  124. procedure TFormNewtonWalkShoot.FormKeyPress(Sender: TObject; var Key: Char);
  125. var
  126. newFreeform: TGLFreeForm;
  127. I, rand: Integer;
  128. begin
  129. if Key = 'x' then
  130. begin
  131. newFreeform := TGLFreeForm.CreateAsChild(GLDummyCube1);
  132. newFreeform.LoadFromFile('HighPolyObject.3ds');
  133. ScaleMesh(newFreeform, 0.05);
  134. // Keep only one mesh in this newFreeform
  135. for I := 0 to newFreeform.MeshObjects.Count - 2 do
  136. begin
  137. rand := Random(newFreeform.MeshObjects.Count);
  138. newFreeform.MeshObjects.Delete(rand);
  139. end;
  140. GetOrCreateNGDDynamic(newFreeform).NGDNewtonCollisions := nc_Convex;
  141. GetNGDDynamic(newFreeform).Manager := GLNGDManager1;
  142. end;
  143. if Key = 'c' then
  144. GetNGDDynamic(Body).NewtonBodyMatrix := IdentityHmgMatrix;
  145. end;
  146. procedure TFormNewtonWalkShoot.GLCadencer1Progress(Sender: TObject;
  147. const deltaTime, newTime: Double);
  148. begin
  149. GLNGDManager1.Step(deltaTime);
  150. MoveCam(deltaTime, newTime);
  151. MoveGrab;
  152. // Set a point on screen to see where you shoot or grab
  153. GLHUDCross.Position.X := GLSceneViewer1.Width div 2;
  154. GLHUDCross.Position.Y := GLSceneViewer1.Height div 2;
  155. end;
  156. procedure TFormNewtonWalkShoot.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  157. Shift: TShiftState; X, Y: Integer);
  158. var
  159. Ball: TGLSphere;
  160. delta: TGLVector;
  161. PickedSceneObject: TGLBaseSceneObject;
  162. point3d: TGLVector;
  163. MyX, MyY: Integer;
  164. begin
  165. // Shoot a Bullet
  166. if Button = TMouseButton(mbLeft) then
  167. begin
  168. Ball := TGLSphere.CreateAsChild(GLDummyCube1);
  169. Ball.Radius := 0.1;
  170. Ball.AbsolutePosition := GLCamera1.TargetObject.AbsolutePosition;
  171. delta := VectorScale(GLCamera1.AbsoluteVectorToTarget, 2);
  172. Ball.Translate(delta.X, delta.Y, delta.Z);
  173. GetOrCreateNGDDynamic(Ball);
  174. GetNGDDynamic(Ball).Manager := GLNGDManager1;
  175. GetNGDDynamic(Ball).Density := 100;
  176. GetNGDDynamic(Ball).LinearDamping := 0.5;
  177. // Add impulse in the camera direction
  178. GetNGDDynamic(Ball).AddImpulse
  179. (VectorScale(GLCamera1.AbsoluteVectorToTarget, 100),
  180. Ball.AbsolutePosition);
  181. end;
  182. // Start Grab
  183. if Button = TMouseButton(mbMiddle) then
  184. begin
  185. MyX := GLSceneViewer1.Width div 2;
  186. MyY := GLSceneViewer1.Height div 2;
  187. PickedSceneObject := GLSceneViewer1.Buffer.GetPickedObject(MyX, MyY);
  188. if Assigned(PickedSceneObject) and Assigned
  189. (GetNGDDynamic(PickedSceneObject)) then
  190. grabJoint.ParentObject := PickedSceneObject
  191. else
  192. exit;
  193. point3d := PickedSceneObject.AbsolutePosition;
  194. // Attach the body
  195. grabJoint.KinematicControllerPick(point3d, paAttach);
  196. end;
  197. end;
  198. procedure TFormNewtonWalkShoot.GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
  199. Shift: TShiftState; X, Y: Integer);
  200. begin
  201. // Detach the body
  202. if Button = TMouseButton(mbMiddle) then
  203. grabJoint.KinematicControllerPick(NullHmgVector, paDetach);
  204. end;
  205. procedure TFormNewtonWalkShoot.ScaleMesh(freeform: TGLFreeForm; val: Single);
  206. var
  207. I, J: Integer;
  208. begin
  209. for J := 0 to freeform.MeshObjects.Count - 1 do
  210. for I := 0 to freeform.MeshObjects[J].Vertices.Count - 1 do
  211. begin
  212. freeform.MeshObjects[J].Vertices[I] := VectorScale
  213. (freeform.MeshObjects[J].Vertices[I], val);
  214. end;
  215. end;
  216. procedure TFormNewtonWalkShoot.MoveCam(const deltaTime, newTime: Double);
  217. var
  218. f: TGLVector;
  219. fup, fdn, flf, frg: TGLVector;
  220. Bup, Bdn, Blf, Brg: Boolean;
  221. NGDDyn: TGLNGDDynamic;
  222. begin
  223. Bup := IsKeyDown('w') or IsKeyDown('z') or IsKeyDown(VK_UP);
  224. Bdn := IsKeyDown('s') or IsKeyDown(VK_DOWN);
  225. Blf := IsKeyDown('d') or IsKeyDown(VK_LEFT);
  226. Brg := IsKeyDown('a') or IsKeyDown('q') or IsKeyDown(VK_RIGHT);
  227. if Bup then
  228. fup := GLCamera1.AbsoluteVectorToTarget
  229. else
  230. fup := VectorMake(0, 0, 0, 0);
  231. if Bdn then
  232. fdn := VectorNegate(GLCamera1.AbsoluteVectorToTarget)
  233. else
  234. fdn := VectorMake(0, 0, 0, 0);
  235. if Blf then
  236. frg := GLCamera1.AbsoluteRightVectorToTarget
  237. else
  238. frg := VectorMake(0, 0, 0, 0);
  239. if Brg then
  240. flf := VectorNegate(GLCamera1.AbsoluteRightVectorToTarget)
  241. else
  242. flf := VectorMake(0, 0, 0, 0);
  243. NGDDyn := GetNGDDynamic(GLCamera1.TargetObject);
  244. if Bup or Bdn or Blf or Brg then
  245. begin
  246. // Add every vector
  247. f := VectorAdd(fup, fdn);
  248. f := VectorAdd(f, frg);
  249. f := VectorAdd(f, flf);
  250. f.Y := 0; // Do not allow the body to go up or down
  251. NormalizeVector(f);
  252. // Move the body
  253. if NGDDyn.Force.VectorLength < 5 then //before - AppliedVelocity
  254. NGDDyn.AddImpulse(f, GLCamera1.TargetObject.AbsolutePosition);
  255. end
  256. else
  257. begin
  258. // Slow down the body if the user stop pushing keys
  259. if NGDDyn.Force.VectorLength > 3 then //before - AppliedVelocity
  260. NGDDyn.AddImpulse(VectorScale(NGDDyn.AppliedForce.AsVector, 0.5), f); //before - SetVector
  261. end;
  262. end;
  263. procedure TFormNewtonWalkShoot.MoveGrab;
  264. var
  265. point3d: TGLVector;
  266. delta: TGLVector;
  267. begin
  268. // Move the object in 3 unit front of GLCamera1.TargetObject
  269. if IsKeyDown(VK_MBUTTON) then
  270. begin
  271. point3d := GLCamera1.TargetObject.AbsolutePosition;
  272. delta := GLCamera1.AbsoluteVectorToTarget;
  273. while VectorLength(delta) < 3 do
  274. delta := VectorScale(delta, 2);
  275. point3d := VectorAdd(point3d, delta);
  276. grabJoint.KinematicControllerPick(point3d, paMove);
  277. end;
  278. end;
  279. end.