fNewtonDensityD.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. unit fNewtonDensityD;
  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. NGD.Import,
  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. GLSimpleNavigation2: TGLSimpleNavigation;
  58. procedure GLCadencer1Progress(Sender: TObject;
  59. const deltaTime, newTime: Double);
  60. procedure FormCreate(Sender: TObject);
  61. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  62. Shift: TShiftState; X, Y: Integer);
  63. private
  64. public
  65. procedure MyForceAndTorqueDensity(const cbody: PNewtonBody;
  66. timestep: dFloat; threadIndex: Integer);
  67. procedure Shoot;
  68. end;
  69. var
  70. FormNewtonDensity: TFormNewtonDensity;
  71. implementation
  72. {$R *.dfm}
  73. function BuoyancyPlaneCallback(const collisionID: Integer; context: Pointer;
  74. const globalSpaceMatrix: PdFloat; globalSpacePlane: PdFloat): Integer;
  75. cdecl;
  76. var
  77. BodyMatrix: TGLMatrix;
  78. PlaneEquation: TGLVector;
  79. pv: PGLVector;
  80. MyForm: TFormNewtonDensity;
  81. begin
  82. // Get the matrix of the actual body
  83. BodyMatrix := PGLMatrix(globalSpaceMatrix)^;
  84. MyForm := TFormNewtonDensity(context);
  85. // this is the 4-value vector that represents the plane equation for
  86. // the buoyancy surface
  87. // This can be used to simulate boats and lighter than air vehicles etc..
  88. PlaneEquation := MyForm.GLPlane1.Direction.AsVector;
  89. // the distance along this normal, to the origin.
  90. PlaneEquation.W := MyForm.GLPlane1.Position.Y;
  91. PGLVector(globalSpacePlane)^ := PlaneEquation;
  92. Result := 1;
  93. end;
  94. procedure TFormNewtonDensity.Shoot;
  95. var
  96. Ball: TGLCube;
  97. NGDDyn: TGLNGDDynamic;
  98. begin
  99. Ball := TGLCube.CreateAsChild(Mag);
  100. Ball.CubeWidth := 0.5;
  101. Ball.CubeHeight := 0.5;
  102. Ball.CubeDepth := 0.5;
  103. Ball.AbsolutePosition := GLCamera1.AbsolutePosition;
  104. NGDDyn := GetOrCreateNGDDynamic(Ball);
  105. NGDDyn.Manager := GLNGDManager1;
  106. NGDDyn.Density := 10;
  107. NGDDyn.UseGravity := false;
  108. NGDDyn.LinearDamping := 0;
  109. // Add impulse in the camera direction
  110. NGDDyn.AddImpulse(VectorScale(GLCamera1.AbsoluteVectorToTarget, 100),
  111. Ball.AbsolutePosition);
  112. end;
  113. procedure TFormNewtonDensity.FormCreate(Sender: TObject);
  114. var
  115. I: Integer;
  116. begin
  117. // To use Buoyancy effect, set a custom forceAndTorqueEvent were you can call
  118. // NewtonBodyAddBuoyancyForce API function
  119. for I := 0 to obj.Count - 1 do
  120. GetNGDDynamic(obj[I]).CustomForceAndTorqueEvent := MyForceAndTorqueDensity;
  121. end;
  122. procedure TFormNewtonDensity.GLCadencer1Progress(Sender: TObject;
  123. const deltaTime, newTime: Double);
  124. begin
  125. GLNGDManager1.Step(deltaTime);
  126. end;
  127. procedure TFormNewtonDensity.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  128. Shift: TShiftState; X, Y: Integer);
  129. begin
  130. if Button = TMouseButton(mbMiddle) then
  131. Shoot;
  132. end;
  133. procedure TFormNewtonDensity.MyForceAndTorqueDensity(const cbody: PNewtonBody;
  134. timestep: dFloat; threadIndex: Integer);
  135. var
  136. worldGravity: TGLVector;
  137. NGDDyn: TGLNGDDynamic;
  138. fluidDensity, fluidLinearViscosity, fluidAngularViscosity: Single;
  139. begin
  140. worldGravity := GLNGDManager1.Gravity.AsVector;
  141. NGDDyn := TGLNGDDynamic(NewtonBodyGetUserData(cbody));
  142. // Add gravity to body: Weight= mass*gravity
  143. ScaleVector(worldGravity, NGDDyn.mass);
  144. NewtonBodyAddForce(cbody, @worldGravity);
  145. fluidDensity := SpinEdit1.Value;
  146. fluidLinearViscosity := SpinEdit2.Value / 10;
  147. fluidAngularViscosity := SpinEdit3.Value / 10;
  148. // We send Self as context for the callback
  149. NewtonBodyAddBuoyancyForce(cbody, fluidDensity / NGDDyn.mass,
  150. fluidLinearViscosity, fluidAngularViscosity, @worldGravity,
  151. @BuoyancyPlaneCallback, self);
  152. end;
  153. end.