fNGDWalkShootD.pas 9.1 KB

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