fNewtonDensity.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. unit fNewtonDensity;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Variants,
  7. System.Classes,
  8. Vcl.Graphics,
  9. Vcl.Controls,
  10. Vcl.Forms,
  11. Vcl.Dialogs,
  12. Vcl.StdCtrls,
  13. Vcl.Samples.Spin,
  14. GLS.Scene,
  15. GLS.VectorTypes,
  16. Physics.NGDManager,
  17. GLS.Objects,
  18. GLS.PersistentClasses,
  19. GLS.Coordinates,
  20. GLS.SimpleNavigation,
  21. GLS.Cadencer,
  22. GLS.SceneViewer,
  23. GLS.BaseClasses,
  24. GLS.VectorGeometry,
  25. GLS.HUDObjects,
  26. GLS.BitmapFont,
  27. GLS.WindowsFont,
  28. Imports.NGD,
  29. GLS.GeomObjects;
  30. type
  31. TFormNewtonDensity = class(TForm)
  32. GLScene1: TGLScene;
  33. GLSceneViewer1: TGLSceneViewer;
  34. GLCadencer1: TGLCadencer;
  35. GLSimpleNavigation1: TGLSimpleNavigation;
  36. GLCamera1: TGLCamera;
  37. GLLightSource1: TGLLightSource;
  38. GLPlane1: TGLPlane;
  39. Mag: TGLDummyCube;
  40. SubMarine: TGLCube;
  41. GLPaperSphere: TGLSphere;
  42. GLLeadSphere: TGLSphere;
  43. GLCube1: TGLCube;
  44. SpinEdit1: TSpinEdit;
  45. HTLiquidDensity: TGLHUDText;
  46. GLNGDManager1: TGLNGDManager;
  47. SpinEdit2: TSpinEdit;
  48. HTLinearViscosity: TGLHUDText;
  49. HTAngularViscosity: TGLHUDText;
  50. SpinEdit3: TSpinEdit;
  51. GLCube2: TGLCube;
  52. GLCone1: TGLCone;
  53. GLCylinder1: TGLCylinder;
  54. obj: TGLDummyCube;
  55. GLCapsule1: TGLCapsule;
  56. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  57. procedure GLCadencer1Progress(Sender: TObject;
  58. const deltaTime, newTime: Double);
  59. procedure FormCreate(Sender: TObject);
  60. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  61. Shift: TShiftState; X, Y: Integer);
  62. private
  63. public
  64. procedure MyForceAndTorqueDensity(const cbody: PNewtonBody;
  65. timestep: NGDFloat; threadIndex: Integer);
  66. procedure Shoot;
  67. end;
  68. var
  69. FormNewtonDensity: TFormNewtonDensity;
  70. implementation
  71. {$R *.dfm}
  72. function BuoyancyPlaneCallback(const collisionID: Integer; context: Pointer;
  73. const globalSpaceMatrix: PNGDFloat; globalSpacePlane: PNGDFloat): Integer;
  74. cdecl;
  75. var
  76. BodyMatrix: TGLMatrix;
  77. PlaneEquation: TGLVector;
  78. pv: PGLVector;
  79. MyForm: TFormNewtonDensity;
  80. begin
  81. // Get the matrix of the actual body
  82. BodyMatrix := PGLMatrix(globalSpaceMatrix)^;
  83. MyForm := TFormNewtonDensity(context);
  84. // this is the 4-value vector that represents the plane equation for
  85. // the buoyancy surface
  86. // This can be used to simulate boats and lighter than air vehicles etc..
  87. PlaneEquation := MyForm.GLPlane1.Direction.AsVector;
  88. // the distance along this normal, to the origin.
  89. PlaneEquation.W := MyForm.GLPlane1.Position.Y;
  90. PGLVector(globalSpacePlane)^ := PlaneEquation;
  91. Result := 1;
  92. end;
  93. procedure TFormNewtonDensity.Shoot;
  94. var
  95. Ball: TGLCube;
  96. NGDDyn: TGLNGDDynamic;
  97. begin
  98. Ball := TGLCube.CreateAsChild(Mag);
  99. Ball.CubeWidth := 0.5;
  100. Ball.CubeHeight := 0.5;
  101. Ball.CubeDepth := 0.5;
  102. Ball.AbsolutePosition := GLCamera1.AbsolutePosition;
  103. NGDDyn := GetOrCreateNGDDynamic(Ball);
  104. NGDDyn.Manager := GLNGDManager1;
  105. NGDDyn.Density := 10;
  106. NGDDyn.UseGravity := false;
  107. NGDDyn.LinearDamping := 0;
  108. // Add impulse in the camera direction
  109. NGDDyn.AddImpulse(VectorScale(GLCamera1.AbsoluteVectorToTarget, 100),
  110. Ball.AbsolutePosition);
  111. end;
  112. procedure TFormNewtonDensity.FormCreate(Sender: TObject);
  113. var
  114. I: Integer;
  115. begin
  116. // To use Buoyancy effect, set a custom forceAndTorqueEvent were you can call
  117. // NewtonBodyAddBuoyancyForce API function
  118. for I := 0 to obj.Count - 1 do
  119. GetNGDDynamic(obj[I]).CustomForceAndTorqueEvent := MyForceAndTorqueDensity;
  120. end;
  121. procedure TFormNewtonDensity.GLCadencer1Progress(Sender: TObject;
  122. const deltaTime, newTime: Double);
  123. begin
  124. GLNGDManager1.Step(deltaTime);
  125. end;
  126. procedure TFormNewtonDensity.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  127. Shift: TShiftState; X, Y: Integer);
  128. begin
  129. if Button = TMouseButton(mbMiddle) then
  130. Shoot;
  131. end;
  132. procedure TFormNewtonDensity.MyForceAndTorqueDensity(const cbody: PNewtonBody;
  133. timestep: NGDFloat; threadIndex: Integer);
  134. var
  135. worldGravity: TGLVector;
  136. NGDDyn: TGLNGDDynamic;
  137. fluidDensity, fluidLinearViscosity, fluidAngularViscosity: Single;
  138. begin
  139. worldGravity := GLNGDManager1.Gravity.AsVector;
  140. NGDDyn := TGLNGDDynamic(NewtonBodyGetUserData(cbody));
  141. // Add gravity to body: Weight= mass*gravity
  142. ScaleVector(worldGravity, NGDDyn.mass);
  143. NewtonBodyAddForce(cbody, @worldGravity);
  144. fluidDensity := SpinEdit1.Value;
  145. fluidLinearViscosity := SpinEdit2.Value / 10;
  146. fluidAngularViscosity := SpinEdit3.Value / 10;
  147. // We send Self as context for the callback
  148. NewtonBodyAddBuoyancyForce(cbody, fluidDensity / NGDDyn.mass,
  149. fluidLinearViscosity, fluidAngularViscosity, @worldGravity,
  150. @BuoyancyPlaneCallback, self);
  151. end;
  152. end.