Selaa lähdekoodia

Included randomlib unit

GLScene 2 vuotta sitten
vanhempi
commit
134aa33c7b

+ 0 - 0
Assets/Data/Constellations.dat → Assets/Data/ConstellationLines.dat


BIN
Assets/Map/land_ocean_ice_4096.jpg


BIN
Assets/Map/land_ocean_ice_lights_4096.jpg


BIN
Assets/Map/moon_2048.jpg


+ 1 - 2
Examples/AdvDemos/Earth/EarthD.dpr

@@ -13,8 +13,7 @@ program EarthD;
 
 uses
   Forms,
-  fEarthD in 'fEarthD.pas' {FormEarth},
-  GLS.SolarSystem in 'GLS.SolarSystem.pas';
+  fEarthD in 'fEarthD.pas' {FormEarth};
 
 {$R *.res}
 

+ 0 - 1
Examples/AdvDemos/Earth/EarthD.dproj

@@ -121,7 +121,6 @@
         <DCCReference Include="fEarthD.pas">
             <Form>FormEarth</Form>
         </DCCReference>
-        <DCCReference Include="USolarSystem.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 1 - 4
Examples/AdvDemos/Earth/fEarthD.dfm

@@ -37,6 +37,7 @@ object FormEarth: TFormEarth
     Left = 16
     Top = 16
     object SkyDome: TGLSkyDome
+      Up.Coordinates = {0000803F000000000000000000000000}
       Bands = <
         item
           StartColor.Color = {0000803F0000803F0000803F0000803F}
@@ -65,10 +66,6 @@ object FormEarth: TFormEarth
         SplineMode = lsmSegments
         Options = []
       end
-      object ConstellationBorders: TGLLines
-        Nodes = <>
-        Options = []
-      end
     end
     object dcEarth: TGLDummyCube
       ObjectsSorting = osNone

+ 12 - 10
Examples/AdvDemos/Earth/fEarthD.pas

@@ -54,7 +54,6 @@ type
     Cameracontroller: TGLCamera;
     SkyDome: TGLSkyDome;
     ConstellationLines: TGLLines;
-    ConstellationBorders: TGLLines;
     procedure FormCreate(Sender: TObject);
     procedure DirectOpenGLRender(Sender: TObject; var rci: TGLRenderContextInfo);
     procedure Timer1Timer(Sender: TObject);
@@ -104,10 +103,6 @@ implementation
 
 {$R *.dfm}
 
-uses
-  // accurate movements left for later... or the astute reader
-  GLS.SolarSystem;
-
 procedure TFormEarth.FormCreate(Sender: TObject);
 var
   FileName: TFileName;
@@ -303,6 +298,8 @@ begin
   FreeMem(pColor);
 end;
 
+//--------------------------------------------------------------------------------
+
 function TFormEarth.LonLatToPos(lon, lat: Single): TAffineVector;
 var
   f: Single;
@@ -317,13 +314,12 @@ procedure TFormEarth.LoadConstellationLines;
 var
   sl, line: TStrings;
   pos1, pos2: TAffineVector;
-
-var
   i: Integer;
+
 begin
   sl := TStringList.Create;
   line := TStringList.Create;
-  sl.LoadFromFile('Constellations.dat');
+  sl.LoadFromFile('ConstellationLines.dat');
   for i := 0 to sl.Count - 1 do
   begin
     line.CommaText := sl[i];
@@ -336,6 +332,8 @@ begin
   line.Free;
 end;
 
+//--------------------------------------------------------------------------------
+
 procedure TFormEarth.Timer1Timer(Sender: TObject);
 begin
   Caption := Format('Earth ' + '%.1f FPS', [GLSceneViewer.FramesPerSecond]);
@@ -411,6 +409,8 @@ begin
   my := Y;
 end;
 
+//--------------------------------------------------------------------------------
+
 procedure TFormEarth.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
   MousePos: TPoint; var Handled: Boolean);
 var
@@ -424,6 +424,8 @@ begin
   Handled := True;
 end;
 
+//--------------------------------------------------------------------------------
+
 procedure TFormEarth.GLSceneViewerDblClick(Sender: TObject);
 begin
   GLSceneViewer.OnMouseMove := nil;
@@ -479,8 +481,8 @@ begin
           SetCurrentDir(Path + '\map');
           with GLMatLib do
           begin
-            LoadHighResTexture(Materials[0], 'earth_ocean_ice_4096.jpg');
-            LoadHighResTexture(Materials[1], 'earth_ocean_ice_lights_4096.jpg');
+            LoadHighResTexture(Materials[0], 'land_ocean_ice_4096.jpg');
+            LoadHighResTexture(Materials[1], 'land_ocean_ice_lights_4096.jpg');
             LoadHighResTexture(Materials[2], 'moon_2048.jpg');
           end;
           GLSceneViewer.Buffer.AntiAliasing := aa2x;

+ 64 - 115
Examples/Demos/graph/heightfield/fHeightFieldD.dfm

@@ -3,161 +3,121 @@ object FormHeightField: TFormHeightField
   Top = 94
   BorderWidth = 4
   Caption = 'Height Field'
-  ClientHeight = 455
-  ClientWidth = 753
+  ClientHeight = 440
+  ClientWidth = 653
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText
-  Font.Height = -14
+  Font.Height = -11
   Font.Name = 'MS Sans Serif'
   Font.Style = []
+  Position = poScreenCenter
   OnCreate = FormCreate
   OnMouseWheel = FormMouseWheel
-  PixelsPerInch = 120
-  TextHeight = 16
+  TextHeight = 13
   object GLSceneViewer1: TGLSceneViewer
     Left = 0
     Top = 0
-    Width = 544
-    Height = 455
-    Margins.Left = 4
-    Margins.Top = 4
-    Margins.Right = 4
-    Margins.Bottom = 4
+    Width = 486
+    Height = 440
     Camera = GLCamera1
     Buffer.BackgroundColor = clBackground
-    FieldOfView = 132.543212890625000000
+    FieldOfView = 131.112091064453100000
     PenAsTouch = False
     Align = alClient
     OnMouseDown = GLSceneViewer1MouseDown
     OnMouseMove = GLSceneViewer1MouseMove
     TabOrder = 0
+    ExplicitWidth = 435
+    ExplicitHeight = 366
   end
   object Panel1: TPanel
-    Left = 544
+    Left = 486
     Top = 0
-    Width = 209
-    Height = 455
-    Margins.Left = 4
-    Margins.Top = 4
-    Margins.Right = 4
-    Margins.Bottom = 4
+    Width = 167
+    Height = 440
     Align = alRight
     TabOrder = 1
+    ExplicitLeft = 435
+    ExplicitHeight = 364
     object Label1: TLabel
-      Left = 60
-      Top = 10
-      Width = 53
-      Height = 16
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 48
+      Top = 8
+      Width = 44
+      Height = 13
       Caption = 'X extents'
     end
     object Label2: TLabel
-      Left = 60
-      Top = 73
-      Width = 54
-      Height = 16
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 48
+      Top = 58
+      Width = 44
+      Height = 13
       Caption = 'Y extents'
     end
     object Label3: TLabel
-      Left = 70
-      Top = 135
-      Width = 28
-      Height = 16
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 56
+      Top = 108
+      Width = 22
+      Height = 13
       Caption = 'Step'
     end
     object Label4: TLabel
-      Left = 24
-      Top = 346
-      Width = 70
-      Height = 16
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 19
+      Top = 277
+      Width = 54
+      Height = 13
       Caption = 'Color Mode'
     end
     object LabelFPS: TLabel
-      Left = 18
-      Top = 450
-      Width = 26
-      Height = 16
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 14
+      Top = 408
+      Width = 20
+      Height = 17
       Caption = 'FPS'
     end
     object TrackBar1: TTrackBar
       Left = 0
-      Top = 24
-      Width = 161
-      Height = 41
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Top = 19
+      Width = 129
+      Height = 33
       Max = 50
       Position = 10
       TabOrder = 0
-      ThumbLength = 13
+      ThumbLength = 10
       TickMarks = tmBoth
       OnChange = TrackBar1Change
     end
     object TrackBar2: TTrackBar
       Left = 0
-      Top = 86
-      Width = 161
-      Height = 42
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Top = 69
+      Width = 129
+      Height = 33
       Max = 50
       Position = 10
       TabOrder = 1
-      ThumbLength = 13
+      ThumbLength = 10
       TickMarks = tmBoth
       OnChange = TrackBar2Change
     end
     object TrackBar3: TTrackBar
       Left = 0
-      Top = 150
-      Width = 161
-      Height = 41
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Top = 120
+      Width = 129
+      Height = 33
       Max = 160
       Min = 10
       Frequency = 10
       Position = 80
       TabOrder = 2
-      ThumbLength = 13
+      ThumbLength = 10
       TickMarks = tmBoth
       OnChange = TrackBar3Change
     end
     object RadioGroup1: TRadioGroup
-      Left = 40
-      Top = 199
-      Width = 101
-      Height = 111
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 32
+      Top = 159
+      Width = 81
+      Height = 89
       Caption = 'Formula'
       ItemIndex = 0
       Items.Strings = (
@@ -168,14 +128,10 @@ object FormHeightField: TFormHeightField
       OnClick = RadioGroup1Click
     end
     object CheckBox1: TCheckBox
-      Left = 20
-      Top = 318
-      Width = 91
-      Height = 21
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 16
+      Top = 254
+      Width = 73
+      Height = 17
       Caption = 'Two-sided'
       Checked = True
       State = cbChecked
@@ -183,14 +139,10 @@ object FormHeightField: TFormHeightField
       OnClick = CheckBox1Click
     end
     object ComboBox1: TComboBox
-      Left = 20
-      Top = 370
-      Width = 101
-      Height = 24
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 16
+      Top = 296
+      Width = 81
+      Height = 21
       Style = csDropDownList
       TabOrder = 5
       OnChange = ComboBox1Change
@@ -200,14 +152,10 @@ object FormHeightField: TFormHeightField
         'diffuse')
     end
     object CheckBox2: TCheckBox
-      Left = 20
-      Top = 404
-      Width = 81
-      Height = 21
-      Margins.Left = 4
-      Margins.Top = 4
-      Margins.Right = 4
-      Margins.Bottom = 4
+      Left = 16
+      Top = 323
+      Width = 65
+      Height = 17
       Caption = 'Lighting'
       Checked = True
       State = cbChecked
@@ -219,6 +167,7 @@ object FormHeightField: TFormHeightField
     Left = 40
     Top = 24
     object HeightField1: TGLHeightField
+      Material.BlendingMode = bmTransparency
       Direction.Coordinates = {000000000000803F2EBD3BB300000000}
       Scale.Coordinates = {00004040000040400000404000000000}
       Up.Coordinates = {000000002EBD3BB3000080BF00000000}

+ 0 - 3
Examples/Demos/graph/splines/fSplinesC.dfm

@@ -30,8 +30,6 @@ object Form1: TForm1
     OnMouseDown = GLSceneViewer1MouseDown
     OnMouseMove = GLSceneViewer1MouseMove
     TabOrder = 0
-    ExplicitWidth = 460
-    ExplicitHeight = 363
   end
   object GLScene1: TGLScene
     Left = 16
@@ -53,7 +51,6 @@ object Form1: TForm1
         end>
       NodesAspect = lnaCube
       NodeSize = 0.500000000000000000
-      SplineMode = lsmBezierSpline
       Options = [loUseNodeColorForLines]
     end
     object GLCamera1: TGLCamera

BIN
Installation.pdf


+ 36 - 36
Packages/GLScene.groupproj

@@ -7,31 +7,31 @@
             <Dependencies/>
         </Projects>
         <Projects Include="GLScene_DT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Sounds_RT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Sounds_DT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_Sounds_RT.dproj;GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Physics_RT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Physics_DT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_Physics_RT.dproj;GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Cg_RT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_Cg_DT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_Cg_RT.dproj;GLScene_DT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_GPU_RT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_Cg_RT.dproj</Dependencies>
         </Projects>
         <Projects Include="GLScene_GPU_DT.dproj">
-            <Dependencies/>
+            <Dependencies>GLScene_GPU_RT.dproj;GLScene_DT.dproj</Dependencies>
         </Projects>
     </ItemGroup>
     <ProjectExtensions>
@@ -50,85 +50,85 @@
     <Target Name="GLScene_RT:Make">
         <MSBuild Projects="GLScene_RT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_DT">
+    <Target Name="GLScene_DT" DependsOnTargets="GLScene_RT">
         <MSBuild Projects="GLScene_DT.dproj"/>
     </Target>
-    <Target Name="GLScene_DT:Clean">
+    <Target Name="GLScene_DT:Clean" DependsOnTargets="GLScene_RT:Clean">
         <MSBuild Projects="GLScene_DT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_DT:Make">
+    <Target Name="GLScene_DT:Make" DependsOnTargets="GLScene_RT:Make">
         <MSBuild Projects="GLScene_DT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Sounds_RT">
+    <Target Name="GLScene_Sounds_RT" DependsOnTargets="GLScene_RT">
         <MSBuild Projects="GLScene_Sounds_RT.dproj"/>
     </Target>
-    <Target Name="GLScene_Sounds_RT:Clean">
+    <Target Name="GLScene_Sounds_RT:Clean" DependsOnTargets="GLScene_RT:Clean">
         <MSBuild Projects="GLScene_Sounds_RT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Sounds_RT:Make">
+    <Target Name="GLScene_Sounds_RT:Make" DependsOnTargets="GLScene_RT:Make">
         <MSBuild Projects="GLScene_Sounds_RT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Sounds_DT">
+    <Target Name="GLScene_Sounds_DT" DependsOnTargets="GLScene_Sounds_RT;GLScene_RT">
         <MSBuild Projects="GLScene_Sounds_DT.dproj"/>
     </Target>
-    <Target Name="GLScene_Sounds_DT:Clean">
+    <Target Name="GLScene_Sounds_DT:Clean" DependsOnTargets="GLScene_Sounds_RT:Clean;GLScene_RT:Clean">
         <MSBuild Projects="GLScene_Sounds_DT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Sounds_DT:Make">
+    <Target Name="GLScene_Sounds_DT:Make" DependsOnTargets="GLScene_Sounds_RT:Make;GLScene_RT:Make">
         <MSBuild Projects="GLScene_Sounds_DT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Physics_RT">
+    <Target Name="GLScene_Physics_RT" DependsOnTargets="GLScene_RT">
         <MSBuild Projects="GLScene_Physics_RT.dproj"/>
     </Target>
-    <Target Name="GLScene_Physics_RT:Clean">
+    <Target Name="GLScene_Physics_RT:Clean" DependsOnTargets="GLScene_RT:Clean">
         <MSBuild Projects="GLScene_Physics_RT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Physics_RT:Make">
+    <Target Name="GLScene_Physics_RT:Make" DependsOnTargets="GLScene_RT:Make">
         <MSBuild Projects="GLScene_Physics_RT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Physics_DT">
+    <Target Name="GLScene_Physics_DT" DependsOnTargets="GLScene_Physics_RT;GLScene_RT">
         <MSBuild Projects="GLScene_Physics_DT.dproj"/>
     </Target>
-    <Target Name="GLScene_Physics_DT:Clean">
+    <Target Name="GLScene_Physics_DT:Clean" DependsOnTargets="GLScene_Physics_RT:Clean;GLScene_RT:Clean">
         <MSBuild Projects="GLScene_Physics_DT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Physics_DT:Make">
+    <Target Name="GLScene_Physics_DT:Make" DependsOnTargets="GLScene_Physics_RT:Make;GLScene_RT:Make">
         <MSBuild Projects="GLScene_Physics_DT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Cg_RT">
+    <Target Name="GLScene_Cg_RT" DependsOnTargets="GLScene_RT">
         <MSBuild Projects="GLScene_Cg_RT.dproj"/>
     </Target>
-    <Target Name="GLScene_Cg_RT:Clean">
+    <Target Name="GLScene_Cg_RT:Clean" DependsOnTargets="GLScene_RT:Clean">
         <MSBuild Projects="GLScene_Cg_RT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Cg_RT:Make">
+    <Target Name="GLScene_Cg_RT:Make" DependsOnTargets="GLScene_RT:Make">
         <MSBuild Projects="GLScene_Cg_RT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_Cg_DT">
+    <Target Name="GLScene_Cg_DT" DependsOnTargets="GLScene_Cg_RT;GLScene_DT">
         <MSBuild Projects="GLScene_Cg_DT.dproj"/>
     </Target>
-    <Target Name="GLScene_Cg_DT:Clean">
+    <Target Name="GLScene_Cg_DT:Clean" DependsOnTargets="GLScene_Cg_RT:Clean;GLScene_DT:Clean">
         <MSBuild Projects="GLScene_Cg_DT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_Cg_DT:Make">
+    <Target Name="GLScene_Cg_DT:Make" DependsOnTargets="GLScene_Cg_RT:Make;GLScene_DT:Make">
         <MSBuild Projects="GLScene_Cg_DT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_GPU_RT">
+    <Target Name="GLScene_GPU_RT" DependsOnTargets="GLScene_Cg_RT">
         <MSBuild Projects="GLScene_GPU_RT.dproj"/>
     </Target>
-    <Target Name="GLScene_GPU_RT:Clean">
+    <Target Name="GLScene_GPU_RT:Clean" DependsOnTargets="GLScene_Cg_RT:Clean">
         <MSBuild Projects="GLScene_GPU_RT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_GPU_RT:Make">
+    <Target Name="GLScene_GPU_RT:Make" DependsOnTargets="GLScene_Cg_RT:Make">
         <MSBuild Projects="GLScene_GPU_RT.dproj" Targets="Make"/>
     </Target>
-    <Target Name="GLScene_GPU_DT">
+    <Target Name="GLScene_GPU_DT" DependsOnTargets="GLScene_GPU_RT;GLScene_DT">
         <MSBuild Projects="GLScene_GPU_DT.dproj"/>
     </Target>
-    <Target Name="GLScene_GPU_DT:Clean">
+    <Target Name="GLScene_GPU_DT:Clean" DependsOnTargets="GLScene_GPU_RT:Clean;GLScene_DT:Clean">
         <MSBuild Projects="GLScene_GPU_DT.dproj" Targets="Clean"/>
     </Target>
-    <Target Name="GLScene_GPU_DT:Make">
+    <Target Name="GLScene_GPU_DT:Make" DependsOnTargets="GLScene_GPU_RT:Make;GLScene_DT:Make">
         <MSBuild Projects="GLScene_GPU_DT.dproj" Targets="Make"/>
     </Target>
     <Target Name="Build">

+ 15 - 15
Packages/GLScene_RT.dpk

@@ -62,6 +62,7 @@ contains
   GLS.AsyncTimer in '..\Source\GLS.AsyncTimer.pas',
   GLS.Atmosphere in '..\Source\GLS.Atmosphere.pas',
   GLS.ArchiveManager in '..\Source\GLS.ArchiveManager.pas',
+  GLS.AnimationUtils in '..\Source\GLS.AnimationUtils.pas',
   GLS.BaseClasses in '..\Source\GLS.BaseClasses.pas',
   GLS.BaseMeshSilhouette in '..\Source\GLS.BaseMeshSilhouette.pas',
   GLS.Behaviours in '..\Source\GLS.Behaviours.pas',
@@ -77,6 +78,7 @@ contains
   GLS.Console in '..\Source\GLS.Console.pas',
   GLS.Context in '..\Source\GLS.Context.pas',
   GLS.Coordinates in '..\Source\GLS.Coordinates.pas',
+  GLS.CrossXML in '..\Source\GLS.CrossXML.pas',
   GLS.CurvesAndSurfaces in '..\Source\GLS.CurvesAndSurfaces.pas',
   GLS.DCE in '..\Source\GLS.DCE.pas',
   GLS.DynamicTexture in '..\Source\GLS.DynamicTexture.pas',
@@ -148,13 +150,16 @@ contains
   GLS.Isolines in '..\Source\GLS.Isolines.pas',
   GLS.Isosurface in '..\Source\GLS.Isosurface.pas',
   GLS.Joystick in '..\Source\GLS.Joystick.pas',
+  GLS.Language in '..\Source\GLS.Language.pas',
   GLS.LensFlare in '..\Source\GLS.LensFlare.pas',
   GLS.LinePFX in '..\Source\GLS.LinePFX.pas',
+  GLS.Logger in '..\Source\GLS.Logger.pas',
   GLS.Manager in '..\Source\GLS.Manager.pas',
   GLS.Material in '..\Source\GLS.Material.pas',
   GLS.MaterialEx in '..\Source\GLS.MaterialEx.pas',
   GLS.MaterialMultiProxy in '..\Source\GLS.MaterialMultiProxy.pas',
   GLS.MaterialScript in '..\Source\GLS.MaterialScript.pas',
+  GLS.Memo in '..\Source\GLS.Memo.pas',
   GLS.Mesh in '..\Source\GLS.Mesh.pas',
   GLS.MeshBSP in '..\Source\GLS.MeshBSP.pas',
   GLS.MeshBuilder in '..\Source\GLS.MeshBuilder.pas',
@@ -201,11 +206,10 @@ contains
   GLSL.ShapeShaders in '..\Source\GLSL.ShapeShaders.pas',
   GLSL.ShaderParameter in '..\Source\GLSL.ShaderParameter.pas',
   GLSL.Shader in '..\Source\GLSL.Shader.pas',
-  GLS.Language in '..\Source\GLS.Language.pas',
-  GLS.Memo in '..\Source\GLS.Memo.pas',
   GLS.PAKArchive in '..\Source\GLS.PAKArchive.pas',
   GLS.ProjectedTextures in '..\Source\GLS.ProjectedTextures.pas',
   GLS.PersistentClasses in '..\Source\GLS.PersistentClasses.pas',
+  GLS.RandomLib in '..\Source\GLS.RandomLib.pas',
   GLS.Scene in '..\Source\GLS.Scene.pas',
   GLS.SceneForm in '..\Source\GLS.SceneForm.pas',
   GLS.Screen in '..\Source\GLS.Screen.pas',
@@ -237,37 +241,33 @@ contains
   GLS.Tree in '..\Source\GLS.Tree.pas',
   GLS.Triangulation in '..\Source\GLS.Triangulation.pas',
   GLS.Utils in '..\Source\GLS.Utils.pas',
-  GLS.VectorFileObjects in '..\Source\GLS.VectorFileObjects.pas',
-  GLS.VerletTypes in '..\Source\GLS.VerletTypes.pas',
-  GLS.VerletClothify in '..\Source\GLS.VerletClothify.pas',
   GLS.WaterPlane in '..\Source\GLS.WaterPlane.pas',
   GLS.Windows in '..\Source\GLS.Windows.pas',
   GLS.WindowsContext in '..\Source\GLS.WindowsContext.pas',
   GLS.WindowsFont in '..\Source\GLS.WindowsFont.pas',
   GLS.zBuffer in '..\Source\GLS.zBuffer.pas',
   GLS.Silhouette in '..\Source\GLS.Silhouette.pas',
-  GLS.VectorLists in '..\Source\GLS.VectorLists.pas',
   GLS.ScriptBase in '..\Source\GLS.ScriptBase.pas',
   GLS.XCollection in '..\Source\GLS.XCollection.pas',
   GLS.XOpenGL in '..\Source\GLS.XOpenGL.pas',
   GLS.InitOpenGL in '..\Source\GLS.InitOpenGL.pas',
-  PasGLTF in '..\Source\PasGLTF.pas',
-  PasJSON in '..\Source\PasJSON.pas',
-  PasDblStrUtils in '..\Source\PasDblStrUtils.pas',
-  GLS.AnimationUtils in '..\Source\GLS.AnimationUtils.pas',
   GLS.OpenGLAdapter in '..\Source\GLS.OpenGLAdapter.pas',
+  GLS.OpenGLTokens in '..\Source\GLS.OpenGLTokens.pas',
   GLS.PipelineTransformation in '..\Source\GLS.PipelineTransformation.pas',
   GLS.Polynomials in '..\Source\GLS.Polynomials.pas',
-  GLS.CrossXML in '..\Source\GLS.CrossXML.pas',
-  GLS.OpenGLTokens in '..\Source\GLS.OpenGLTokens.pas',
+  PasGLTF in '..\Source\PasGLTF.pas',
+  PasJSON in '..\Source\PasJSON.pas',
+  PasDblStrUtils in '..\Source\PasDblStrUtils.pas',
   GLS.Spline in '..\Source\GLS.Spline.pas',
   GLS.Strings in '..\Source\GLS.Strings.pas',
   GLS.TextureFormat in '..\Source\GLS.TextureFormat.pas',
+  GLS.VectorLists in '..\Source\GLS.VectorLists.pas',
   GLS.VectorGeometry in '..\Source\GLS.VectorGeometry.pas',
   GLS.VectorTypes in '..\Source\GLS.VectorTypes.pas',
-  GLS.VectorTypesExt in '..\Source\GLS.VectorTypesExt.pas',
-  GLS.Logger in '..\Source\GLS.Logger.pas',
-  GLS.SolarSystem in '..\Source\GLS.SolarSystem.pas';
+  GLS.VectorFileObjects in '..\Source\GLS.VectorFileObjects.pas',
+  GLS.VerletTypes in '..\Source\GLS.VerletTypes.pas',
+  GLS.VerletClothify in '..\Source\GLS.VerletClothify.pas',
+  GLS.VectorTypesExt in '..\Source\GLS.VectorTypesExt.pas';
 
 end.
 

+ 14 - 14
Packages/GLScene_RT.dproj

@@ -166,6 +166,7 @@
         <DCCReference Include="..\Source\GLS.AsyncTimer.pas"/>
         <DCCReference Include="..\Source\GLS.Atmosphere.pas"/>
         <DCCReference Include="..\Source\GLS.ArchiveManager.pas"/>
+        <DCCReference Include="..\Source\GLS.AnimationUtils.pas"/>
         <DCCReference Include="..\Source\GLS.BaseClasses.pas"/>
         <DCCReference Include="..\Source\GLS.BaseMeshSilhouette.pas"/>
         <DCCReference Include="..\Source\GLS.Behaviours.pas"/>
@@ -181,6 +182,7 @@
         <DCCReference Include="..\Source\GLS.Console.pas"/>
         <DCCReference Include="..\Source\GLS.Context.pas"/>
         <DCCReference Include="..\Source\GLS.Coordinates.pas"/>
+        <DCCReference Include="..\Source\GLS.CrossXML.pas"/>
         <DCCReference Include="..\Source\GLS.CurvesAndSurfaces.pas"/>
         <DCCReference Include="..\Source\GLS.DCE.pas"/>
         <DCCReference Include="..\Source\GLS.DynamicTexture.pas"/>
@@ -252,13 +254,16 @@
         <DCCReference Include="..\Source\GLS.Isolines.pas"/>
         <DCCReference Include="..\Source\GLS.Isosurface.pas"/>
         <DCCReference Include="..\Source\GLS.Joystick.pas"/>
+        <DCCReference Include="..\Source\GLS.Language.pas"/>
         <DCCReference Include="..\Source\GLS.LensFlare.pas"/>
         <DCCReference Include="..\Source\GLS.LinePFX.pas"/>
+        <DCCReference Include="..\Source\GLS.Logger.pas"/>
         <DCCReference Include="..\Source\GLS.Manager.pas"/>
         <DCCReference Include="..\Source\GLS.Material.pas"/>
         <DCCReference Include="..\Source\GLS.MaterialEx.pas"/>
         <DCCReference Include="..\Source\GLS.MaterialMultiProxy.pas"/>
         <DCCReference Include="..\Source\GLS.MaterialScript.pas"/>
+        <DCCReference Include="..\Source\GLS.Memo.pas"/>
         <DCCReference Include="..\Source\GLS.Mesh.pas"/>
         <DCCReference Include="..\Source\GLS.MeshBSP.pas"/>
         <DCCReference Include="..\Source\GLS.MeshBuilder.pas"/>
@@ -305,11 +310,10 @@
         <DCCReference Include="..\Source\GLSL.ShapeShaders.pas"/>
         <DCCReference Include="..\Source\GLSL.ShaderParameter.pas"/>
         <DCCReference Include="..\Source\GLSL.Shader.pas"/>
-        <DCCReference Include="..\Source\GLS.Language.pas"/>
-        <DCCReference Include="..\Source\GLS.Memo.pas"/>
         <DCCReference Include="..\Source\GLS.PAKArchive.pas"/>
         <DCCReference Include="..\Source\GLS.ProjectedTextures.pas"/>
         <DCCReference Include="..\Source\GLS.PersistentClasses.pas"/>
+        <DCCReference Include="..\Source\GLS.RandomLib.pas"/>
         <DCCReference Include="..\Source\GLS.Scene.pas"/>
         <DCCReference Include="..\Source\GLS.SceneForm.pas"/>
         <DCCReference Include="..\Source\GLS.Screen.pas"/>
@@ -341,37 +345,33 @@
         <DCCReference Include="..\Source\GLS.Tree.pas"/>
         <DCCReference Include="..\Source\GLS.Triangulation.pas"/>
         <DCCReference Include="..\Source\GLS.Utils.pas"/>
-        <DCCReference Include="..\Source\GLS.VectorFileObjects.pas"/>
-        <DCCReference Include="..\Source\GLS.VerletTypes.pas"/>
-        <DCCReference Include="..\Source\GLS.VerletClothify.pas"/>
         <DCCReference Include="..\Source\GLS.WaterPlane.pas"/>
         <DCCReference Include="..\Source\GLS.Windows.pas"/>
         <DCCReference Include="..\Source\GLS.WindowsContext.pas"/>
         <DCCReference Include="..\Source\GLS.WindowsFont.pas"/>
         <DCCReference Include="..\Source\GLS.zBuffer.pas"/>
         <DCCReference Include="..\Source\GLS.Silhouette.pas"/>
-        <DCCReference Include="..\Source\GLS.VectorLists.pas"/>
         <DCCReference Include="..\Source\GLS.ScriptBase.pas"/>
         <DCCReference Include="..\Source\GLS.XCollection.pas"/>
         <DCCReference Include="..\Source\GLS.XOpenGL.pas"/>
         <DCCReference Include="..\Source\GLS.InitOpenGL.pas"/>
-        <DCCReference Include="..\Source\PasGLTF.pas"/>
-        <DCCReference Include="..\Source\PasJSON.pas"/>
-        <DCCReference Include="..\Source\PasDblStrUtils.pas"/>
-        <DCCReference Include="..\Source\GLS.AnimationUtils.pas"/>
         <DCCReference Include="..\Source\GLS.OpenGLAdapter.pas"/>
+        <DCCReference Include="..\Source\GLS.OpenGLTokens.pas"/>
         <DCCReference Include="..\Source\GLS.PipelineTransformation.pas"/>
         <DCCReference Include="..\Source\GLS.Polynomials.pas"/>
-        <DCCReference Include="..\Source\GLS.CrossXML.pas"/>
-        <DCCReference Include="..\Source\GLS.OpenGLTokens.pas"/>
+        <DCCReference Include="..\Source\PasGLTF.pas"/>
+        <DCCReference Include="..\Source\PasJSON.pas"/>
+        <DCCReference Include="..\Source\PasDblStrUtils.pas"/>
         <DCCReference Include="..\Source\GLS.Spline.pas"/>
         <DCCReference Include="..\Source\GLS.Strings.pas"/>
         <DCCReference Include="..\Source\GLS.TextureFormat.pas"/>
+        <DCCReference Include="..\Source\GLS.VectorLists.pas"/>
         <DCCReference Include="..\Source\GLS.VectorGeometry.pas"/>
         <DCCReference Include="..\Source\GLS.VectorTypes.pas"/>
+        <DCCReference Include="..\Source\GLS.VectorFileObjects.pas"/>
+        <DCCReference Include="..\Source\GLS.VerletTypes.pas"/>
+        <DCCReference Include="..\Source\GLS.VerletClothify.pas"/>
         <DCCReference Include="..\Source\GLS.VectorTypesExt.pas"/>
-        <DCCReference Include="..\Source\GLS.Logger.pas"/>
-        <DCCReference Include="..\Source\GLS.SolarSystem.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 2 - 2
README.md

@@ -2,5 +2,5 @@
 GLScene is a graphics engine based on OpenGL and VCL components for Delphi & C++ Builder. 
 It provides the class library and tools for rendering 3D scenes 
 with spatial objects and virtual smart actors for Win32/Win64 applications. 
-Added additional support of components for shaders, sounds, physics and
-GPU computing.
+Added additional support of components for shaders, sounds, physics and GPU computing.
+GLS Team

+ 1 - 1
Readme.txt

@@ -8,4 +8,4 @@ Includes improvements in GPU parallel computing using CUDA/OpenCL components
 for developing OpenGL applications for Win32/Win64.
 The hierarchy of spatial objects with smart properties has been expanded. 
 -----------------------------------------------------------
-GLS Team
+GLS Team

+ 1630 - 0
Source/GLS.RandomLib.pas

@@ -0,0 +1,1630 @@
+//
+// The graphics engine GLScene https://github.com/glscene
+//
+unit GLS.RandomLib;
+(*
+  Some of the code is translated from:
+  RANLIB - Library of Fortran Routines for Random Number Generation
+  OR
+  Adapted from Fortran 77 code from the book:
+  Dagpunar, J. 'Principles of random variate generation' Clarendon Press,
+  Oxford, 1988. ISBN 0-19-852202-9.
+  First Delphi Version prepared by Glenn Crouch of ESB Consultancy
+  In most of Dagpunar's routines, there is a test to see
+  whether the value of one or two floating&#45;point parameters
+  has changed since the last call. These tests have been
+  replaced by using a logical variable FIRST. This should be
+  set to .TRUE. on the first call using new values of the
+  parameters, and .FALSE. if the parameter values are the same
+  as for the previous call.
+
+  Generate a random ordering of the integers 1 .. N
+  Random_Order Initialize (seed) the uniform random number
+  generator for ANY compiler Seed_Rrandom_Number
+
+  * Two functions are provided for the binomial distribution.
+  If the parameter values remain constant, it is recommended
+  that the first function is used (random_binomial1). If one or
+  both of the parameters change, use the second function
+  (random_binomial2).
+
+  Delphi's own random number generator, Random, is used to
+  provide a source of uniformly distributed random numbers.
+  At this stage, only one random number is generated at
+  each call to one of the functions above.
+
+  The unit uses the following functions which are included
+  here: bin_prob to calculate a single binomial probability
+  lngamma to calculate the logarithm to base e of the gamma
+  function
+*)
+
+interface
+
+uses
+  System.Math,
+  System.SysUtils;
+
+type
+  // Used as a Dynamic Vector
+  TAMFloatVector = array of Extended;
+
+type
+  // Used for passing Random Number Generators
+  TRandomGenFunction = function: Extended;
+
+(*
+  Used to call Random Number Generator.
+  Remember to use Randomize if you don't want repeatable sequences.
+*)
+function GenRandom: Extended;
+(*
+Common random distributions  TEST :
+                           Unif.      Expo.    Norm.
+Total Numbers             100000     100000   100000
+Given Mean                    50         25       25
+Computed Mean               49.9       24.9     24.9
+Expect.Strd_Dev               29         25        1
+*)
+// Uniform Random single numbers in RLow..RHigh range
+function RandUniform(RLow, RHigh: Single): Single; overload;
+function RandUniform(RLow, RHigh: Integer): Integer; overload;
+function RandExponent(Mean: Single): single;
+function RandNorm(Mean, StDev: single): single;
+function RandLogNorm(Mean, StDev: single): single;
+//  Marsaglia-Bray algorithm
+function RandGauss(Mean, StdDev: single): single;
+(*
+  Random Number for Empiricle Distribution
+  X[I]  - middle of I-interval
+  Fx[I] - cummulative empiricle distribution with values in [0..1]
+*)
+function RandEmpiric(X: array of single; Fx: array of single; NClass: integer): single;
+
+(*
+  Adapted from the following Fortran 77 code
+  ALGORITHM 712, COLLECTED ALGORITHMS FROM ACM.
+  THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
+  VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
+  The algorithm uses the ratio of uniforms method of A.J. Kinderman
+  and J.F. Monahan augmented with quadratic bounding curves
+  Returns a normally distributed pseudo-random number with zero mean and unit variance
+*)
+function Random_Normal: Extended; overload;
+(*
+  Adapted from COLLECTED ALGORITHMS FROM ACM.
+  THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
+  VOL. 18, NO. 4, DECEMBER, 1992, PP. 434-435.
+  Returns a normally distributed pseudo-random number with zero mean and unit variance.
+  The algorithm uses the ratio of uniforms method of A.J. Kinderman
+  and J.F. Monahan augmented with quadratic bounding curves
+*)
+function Random_Normal(RandomGenerator: TRandomGenFunction): Extended; overload;
+function Random_Normal(const Mean, StdDev: Extended): Extended; overload;
+function Random_Normal(const Mean, StdDev: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+
+// Adapted from approach suggested by Greg Hood, used with Permission.
+function Random_LogNormal(const Mean, StdDev: Extended): Extended; overload;
+// Adapted from approach suggested by Greg Hood, used with Permission.
+function Random_LogNormal(const Mean, StdDev: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+
+(*
+  GENERATES A RANDOM GAMMA VARIATE.
+  CALLS EITHER random_gamma1 (Shape > 1.0) OR random_exponential (Shape = 1.0)
+  OR random_gamma2 (Shape < 1.0).
+  Shape = Shape PARAMETER OF DISTRIBUTION (0 < REAL).
+*)
+function Random_Gamma(const Shape: Extended): Extended; overload;
+(*
+  GENERATES A RANDOM GAMMA VARIATE.
+  CALLS EITHER random_gamma1 (Shape > 1.0)
+  OR random_exponential (Shape = 1.0)
+  OR random_gamma2 (Shape < 1.0).
+  Shape = Shape PARAMETER OF DISTRIBUTION (0 < REAL)
+*)
+function Random_Gamma(const Shape: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+(*
+  Uses the algorithm in Marsaglia, G. and Tsang, W.W. (2000)
+  'A simple method for generating gamma variables', Trans. om Math.
+  Software (TOMS), vol.26(3), pp.363-372.
+  Generates a random gamma deviate for shape parameter Shape >= 1.
+*)
+function Random_Gamma1(const Shape: Extended;
+  RandomGenerator: TRandomGenFunction): Extended;
+
+(*
+  Generates a random variate from the chi-squared distribution
+  with dff degrees of freedom.
+*)
+function Random_ChiSq(const DF: Integer): Extended; overload;
+function Random_ChiSq(const DF: Integer; RandomGenerator: TRandomGenFunction)
+  : Extended; overload;
+
+(*
+  Generates a random variate in [0,INFINITY) FROM
+  A NEGATIVE EXPONENTIAL DlSTRIBUTION WlTH DENSITY PROPORTIONAL
+  TO EXP(-random_exponential), USING INVERSION.
+*)
+function Random_Exponential: Extended; overload;
+function Random_Exponential(RandomGenerator: TRandomGenFunction)
+  : Extended; overload;
+
+(*
+  Generates a random variate from the Weibull distribution with
+  probability density:
+  a
+  a-1  -x
+  f(x) = a.x    e
+*)
+function Random_Weibull(const a: Extended): Extended; overload;
+function Random_Weibull(const a: Extended; RandomGenerator: TRandomGenFunction)
+  : Extended; overload;
+
+(*
+  Generates a random variate in [0,1]
+  FROM A BETA DISTRIBUTION WITH DENSITY
+  PROPORTIONAL TO BETA**(AA-1) * (1-BETA)**(BB-1).
+  USING CHENG'S LOG LOGISTIC METHOD.
+  AA = Shape PARAMETER FROM DISTRIBUTION (0 < REAL)
+  BB = Shape PARAMETER FROM DISTRIBUTION (0 < REAL)
+*)
+function Random_Beta(const aa, bb: Extended): Extended; overload;
+function Random_Beta(const aa, bb: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+
+(*
+  Generates a random variate FROM A
+  T DISTRIBUTION USING KINDERMAN AND MONAHAN'S RATIO METHOD.
+  DF = DEGREES OF FREEDOM OF DISTRIBUTION (DF >= 1)
+*)
+function Random_T(const DF: Integer): Extended; overload;
+function Random_T(const DF: Integer; RandomGenerator: TRandomGenFunction)
+  : Extended; overload;
+
+(*
+  GENERATES AN N VARIATE RANDOM NORMAL
+  Vector USING A CHOLESKY DECOMPOSITION.
+
+  ARGUMENTS:
+  N = NUMBER OF VARIATES IN Vector (INPUT,INTEGER >= 1)
+  H(J) = J'TH ELEMENT OF Vector OF MEANS (INPUT,REAL)
+  X(J) = J'TH ELEMENT OF DELIVERED Vector (OUTPUT,REAL)
+
+  D(J*(J-1)/2+I) = (I,J)'TH ELEMENT OF VARIANCE MATRIX (J> = I) (INPUT,REAL)
+  F((J-1)*(2*N-J)/2+I) = (I,J)'TH ELEMENT OF LOWER TRIANGULAR
+  DECOMPOSITION OF VARIANCE MATRIX (J <= I) (OUTPUT,REAL)
+  ier = 1 if the input covariance matrix is not +ve definite = 0 otherwise
+*)
+procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
+  var ier: Integer); overload;
+procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
+  var ier: Integer; RandomGenerator: TRandomGenFunction); overload;
+
+(*
+  Generates a random variate in [0,INFINITY] FROM
+  A REPARAMETERISED GENERALISED INVERSE GAUSSIAN (GIG) DISTRIBUTION
+  WITH DENSITY PROPORTIONAL TO  GIG**(H-1) * EXP(-0.5*B*(GIG+1/GIG))
+  USING A RATIO METHOD.
+
+  h = PARAMETER OF DISTRIBUTION (0 <= REAL)
+  b = PARAMETER OF DISTRIBUTION (0 < REAL)
+*)
+function Random_Inv_Gauss(const h, b: Extended): Extended; overload;
+function Random_Inv_Gauss(const h, b: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+
+(*
+  GENERATES A RANDOM BINOMIAL VARIATE USING C.D.Kemp's method.
+  This algorithm is suitable when many random variates are required
+  with the SAME parameter values for n & p.
+  P = Bernoulli SUCCESS PROBABILITY
+  (0 <= REAL <= 1)
+  N = Number of Bernoulli trials
+  (1 <= INTEGER)
+  Reference: Kemp, C.D. (1986). `A modal method for generating binomial
+  variables', Commun. Statist. - Theor. Meth. 15(3), 805-813.
+*)
+function Random_Binomial1(const n: Integer; const p: Extended): Int64; overload;
+function Random_Binomial1(const n: Integer; const p: Extended;
+  RandomGenerator: TRandomGenFunction): Int64; overload;
+
+(*
+  Generates a single random deviate from a binomial
+  distribution whose number of trials is N and whose
+  probability of an event in each trial is P.
+
+  Arguments
+  N  --> The number of trials in the binomial distribution
+  from which a random deviate is to be generated.
+  INTEGER N
+  P  --> The probability of an event in each trial of the
+  binomial distribution from which a random deviate
+  is to be generated.
+  REAL P
+*)
+function Random_Binomial2(const n: Int64; const pp: Extended): Int64; overload;
+(*
+  FIRST --> Set FIRST = .TRUE. for the first call to perform initialization
+  the set FIRST = .FALSE. for further calls using the same pair
+  of parameter values (N, P).
+  LOGICAL FIRST
+  random_binomial2 <-- A random deviate yielding the number of events
+  from N independent trials, each of which has a probability of event P.
+  INTEGER --> random_binomial
+  Method:
+  This is algorithm BTPE from:
+  Kachitvichyanukul, V. and Schmeiser, B. W.
+  Binomial Random Variate Generation.
+  Communications of the ACM, 31, 2 (February, 1988) 216.
+*)
+function Random_Binomial2(const n: Int64; const pp: Extended;
+  RandomGenerator: TRandomGenFunction): Int64; overload;
+(*
+  GENERATES A RANDOM NEGATIVE BINOMIAL VARIATE USING UNSTORED
+  INVERSION AND/OR THE REPRODUCTIVE PROPERTY.
+  SK = NUMBER OF FAILURES REQUIRED (Dagpunar's words!)
+  = the `power' parameter of the negative binomial
+  (0 < REAL)
+  P = BERNOULLI SUCCESS PROBABILITY
+  (0 < REAL < 1)
+  THE PARAMETER H IS SET SO THAT UNSTORED INVERSION ONLY IS USED WHEN P <= H,
+  OTHERWISE A COMBINATION OF UNSTORED INVERSION AND
+  THE REPRODUCTIVE PROPERTY IS USED.
+*)
+function Random_Neg_Binomial(const sk, p: Extended): Int64; overload;
+function Random_Neg_Binomial(const sk, p: Extended;
+  RandomGenerator: TRandomGenFunction): Int64; overload;
+(*
+  Algorithm VMD
+  Arguments:  k (real) -  parameter of the von Mises distribution.
+*)
+function Random_von_Mises(const k: Extended): Extended; overload;
+function Random_von_Mises(const k: Extended;
+  RandomGenerator: TRandomGenFunction): Extended; overload;
+// Generate a random deviate from the standard Cauchy distribution
+function Random_Cauchy: Extended; overload;
+function Random_Cauchy(RandomGenerator: TRandomGenFunction): Extended; overload;
+(*
+  Generates a single random deviate from a Poisson distribution with mean mu.
+  Arguments:
+  mu --> The mean of the Poisson distribution from which
+  a random deviate is to be generated.
+  REAL mu
+  Method: For details see Ahrens, J.H. and Dieter, U.
+  Computer Generation of Poisson Deviates
+  From Modified Normal Distributions. ACM Trans. Math. Software, 8, 2
+  (June 1982),163-179
+
+  TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
+  COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
+*)
+function Random_Poisson(var mu: Extended): Int64; overload;
+function Random_Poisson(var mu: Extended; RandomGenerator: TRandomGenFunction)
+  : Int64; overload;
+
+(*
+  Logarithm to base e of the gamma function.
+  Accurate to about 1.e-14.
+  Programmer: Alan Miller
+  Latest revision of Fortran 77 version - 28 February 1988
+*)
+function LnGamma(const x: Extended): Extended;
+
+// =====================================================================
+implementation
+// =====================================================================
+
+const
+  VSmall = MinDouble;
+  VLarge = MaxDouble;
+
+function GenRandom: Extended;
+begin
+  Result := Random;
+end;
+
+//---------------------------------------------------------------
+
+function RandUniform(RLow, RHigh: Single): Single; overload;
+begin
+  Result := RLow + (RHigh - RLow) * Random();
+end;
+
+
+function RandUniform(RLow, RHigh: Integer): Integer; overload;
+begin
+  Result := RLow + Round((RHigh - RLow) * Random());
+end;
+
+//------------------------------------------------------
+//                  RANDOM EXPONENTIAL
+//------------------------------------------------------
+function RandExponent(Mean: single): single;
+begin
+  RandExponent := -Mean * Ln(Random());
+end;
+
+//------------------------------------------------------
+//                   RANDOM  NORMAL
+//------------------------------------------------------
+function RandNorm(Mean, StDev: single): single;
+var
+  S, Y, U1, U2: single;
+begin
+  repeat
+    U1 := 2 * Random() - 1;
+    U2 := 2 * Random() - 1;
+    S  := U1 * U1 + U2 * U2;
+  until (S < 1);
+  Y := U2 * Sqrt(-2 * Ln(S) / S);
+  RandNorm := Mean + StDev * Y;
+end; // of Normal
+
+//-------------------------------------------------------
+//              RANDOM GAUSSIAN
+//-------------------------------------------------------
+
+function RandGauss(Mean, StdDev: single): single;
+var
+  U1, S2: single;
+begin
+  repeat
+    U1 := 2 * Random - 1;
+    S2 := Sqr(U1) + Sqr(2 * Random - 1);
+  until S2 < 1;
+  RandGauss := Sqrt(-2 * Ln(S2) / S2) * U1 * StdDev + Mean;
+end;
+
+//------------------------------------------------------
+//                RANDOM  LOGNORMAL
+//------------------------------------------------------
+function RandLogNorm(Mean, StDev: single): single;
+var
+  S, Y, U1, U2: single;
+begin
+  S := 0.0;
+  repeat
+    U1 := 2 * Random - 1;
+    U2 := 2 * Random - 1;
+    S  := U1 * U1 + U2 * U2;
+  until (S < 1);
+  Y := Sqrt(-2 * Ln(S) / S) * U2;
+  RandLogNorm := Exp(Y) + Mean;
+end; // of LogNorm
+
+function RandEmpiric(X: array of single; Fx: array of single; NClass: integer): single;
+var
+  I: integer;
+  R: single;
+begin
+  RandEmpiric := 0;
+  R := Random;
+  for I := 1 to NClass do
+  begin
+    if (R <= Fx[I]) then
+      RandEmpiric := X[I];
+  end;
+end;
+
+//---------------------------------------------------------------
+
+function Random_Normal(RandomGenerator: TRandomGenFunction): Extended;
+const
+  s = 0.449871;
+  t = -0.386595;
+  a = 0.19600;
+  b = 0.25472;
+  r1 = 0.27597;
+  r2 = 0.27846;
+var
+  u, v, x, y, q: Extended;
+  Done: Boolean;
+
+begin
+  // Generate P = (u,v) uniform in rectangle enclosing acceptance region
+  Done := False;
+  repeat
+    u := RandomGenerator;
+    v := RandomGenerator;
+    v := 1.7156 * (v - 0.5);
+
+    // Evaluate the quadratic form
+    x := u - s;
+    y := abs(v) - t;
+    q := Sqr(x) + y * (a * y - b * x);
+
+    // Accept P if inside inner ellipse
+    if (q < r1) then
+      Done := True
+    else if (q <= r2) and (Sqr(v) < -4.0 * Ln(u) * Sqr(u)) then
+      Done := True;
+  until Done;
+  // Return ratio of P's coordinates as the normal deviate
+  if u < VSmall then
+    raise EMathError.Create('Divided By Zero');
+
+  Result := v / u;
+end;
+
+//---------------------------------------------------------------
+
+function Random_Normal: Extended;
+begin
+  Result := Random_Normal(GenRandom);
+end;
+
+function Random_Normal(const Mean, StdDev: Extended;
+  RandomGenerator: TRandomGenFunction): Extended;
+begin
+  Result := Random_Normal(RandomGenerator) * StdDev + Mean;
+end;
+
+function Random_Normal(const Mean, StdDev: Extended): Extended;
+begin
+  Result := Random_Normal(Mean, StdDev, GenRandom);
+end;
+
+//---------------------------------------------------------------
+
+function Random_LogNormal(const Mean, StdDev: Extended;
+  RandomGenerator: TRandomGenFunction): Extended;
+var
+  C, M, s: Extended;
+begin
+  if Mean <= 0 then
+    raise EMathError.Create('Invalid Mean');
+  if StdDev <= 0 then
+    raise EMathError.Create('Invalid StdDev');
+
+  C := StdDev / Mean;
+  M := Ln(Mean) - 0.5 * Ln(Sqr(C) + 1);
+  s := Sqrt(Ln(Sqr(C) + 1));
+  Result := Exp(Random_Normal(M, s, RandomGenerator));
+end;
+
+function Random_LogNormal(const Mean, StdDev: Extended): Extended;
+begin
+  Result := Random_LogNormal(Mean, StdDev, GenRandom);
+end;
+
+//---------------------------------------------------------------
+
+function Random_Gamma1(const Shape: Extended;
+  RandomGenerator: TRandomGenFunction): Extended;
+var
+  C, d: Extended;
+  u, v, x: Extended;
+  Done: Boolean;
+begin
+  if (Shape <= 1.0) then
+    raise EMathError.Create('Invalid Shape');
+  d := Shape - 1 / 3;
+  C := 1 / Sqrt(9.0 * d);
+  Result := 0.0;
+  Done := False;
+  repeat
+    // Generate v = (1+cx)^3 where x is random normal; repeat if v <= 0.
+    repeat
+      x := Random_Normal(RandomGenerator);
+      v := Power(1 + C * x, 3);
+    until v > 0;
+    // Generate uniform variable U
+    u := RandomGenerator;
+    if (u < 1.0 - 0.0331 * Sqr(Sqr(x))) then
+    begin
+      Result := d * v;
+      Done := True;
+    end
+    else if Ln(u) < 0.5 * Sqr(x) + d * (1.0 - v + Ln(v)) then
+    begin
+      Result := d * v;
+      Done := True;
+    end
+    until Done;
+  end;
+
+  (*
+    Generates a RANDOM VARIATE in [0,INFINITY) from
+    A GAMMA DISTRIBUTION with DENSITY proportional to
+    GAMMA2**(S-1) * EXP(-GAMMA2),
+    using a switching method.
+    S = Shape PARAMETER of distribution
+    (real < 1.0)
+   *)
+  function Random_Gamma2(const Shape: Extended;
+    RandomGenerator: TRandomGenFunction): Extended;
+  var
+    r, x, w: Extended;
+    a, p, C, uf, vr, d: Extended;
+    Done: Boolean;
+  begin
+    if (Shape <= 0.0) and (Shape >= 1.0) then
+      raise EMathError.Create('Invalid Shape');
+    if (Shape < VSmall) then
+      raise EMathError.Create('Shape Too Small');
+
+    a := 1.0 - Shape;
+    p := a / (a + Shape * Exp(-a));
+    C := 1.0 / Shape;
+    uf := p * Power(VSmall / a, Shape);
+    vr := 1.0 - VSmall;
+    d := a * Ln(a);
+    w := 0;
+    x := 0;
+    Done := False;
+    repeat
+      r := RandomGenerator;
+      if (r >= vr) then
+        Continue;
+      if (r > p) then
+      begin
+        x := a - Ln((1.0 - r) / (1.0 - p));
+        w := a * Ln(x) - d;
+      end
+      else if (r > uf) then
+      begin
+        x := a * Power(r / p, C);
+        w := x;
+      end
+      else
+      begin
+        Result := 0.0;
+        Exit;
+      end;
+      r := RandomGenerator;
+      if (1.0 - r <= w) and (r > 0.0) then
+      begin
+        if (r * (w + 1.0) >= 1.0) then
+          Continue;
+        if (-Ln(r) <= w) then
+          Continue;
+      end;
+      Done := True;
+    until Done;
+    Result := x;
+  end;
+
+//---------------------------------------------------------------
+
+  function Random_Gamma(const Shape: Extended;
+    RandomGenerator: TRandomGenFunction): Extended;
+  begin
+    if (Shape <= 0.0) then
+      raise EMathError.Create('Invalid Shape');
+    if (Shape > 1.0) then
+      Result := Random_Gamma1(Shape, RandomGenerator)
+    else if (Shape < 1.0) then
+      Result := Random_Gamma2(Shape, RandomGenerator)
+    else
+      Result := Random_Exponential(RandomGenerator);
+  end;
+
+  function Random_Gamma(const Shape: Extended): Extended;
+  begin
+    Result := Random_Gamma(Shape, GenRandom);
+  end;
+
+  function Random_ChiSq(const DF: Integer; RandomGenerator: TRandomGenFunction)
+    : Extended;
+  begin
+    Result := 2.0 * Random_Gamma(0.5 * DF, RandomGenerator)
+  end;
+
+  function Random_ChiSq(const DF: Integer): Extended;
+  begin
+    Result := Random_ChiSq(DF, GenRandom);
+  end;
+
+//---------------------------------------------------------------
+
+  function Random_Exponential(RandomGenerator: TRandomGenFunction): Extended;
+  var
+    r: Extended;
+    Done: Boolean;
+  begin
+    Done := False;
+    repeat
+      r := RandomGenerator;
+      if (r > VSmall) then
+        Done := True;
+    until Done;
+    Result := -Ln(r)
+  end;
+
+  function Random_Exponential: Extended;
+  begin
+    Result := Random_Exponential(GenRandom);
+  end;
+
+  function Random_Weibull(const a: Extended;
+    RandomGenerator: TRandomGenFunction): Extended;
+  begin
+    if abs(a) <= VSmall then
+      raise EMathError.Create('Invalid Value');
+
+    Result := Power(Random_Exponential(RandomGenerator), 1.0 / a);
+  end;
+
+ //---------------------------------------------------------------
+
+  function Random_Weibull(const a: Extended): Extended;
+  begin
+    Result := Random_Weibull(a, GenRandom);
+  end;
+
+  function Random_Beta(const aa, bb: Extended;
+    RandomGenerator: TRandomGenFunction): Extended;
+  const
+    aln4 = 1.3862943611198906;
+  var
+    a, b, g, r, s, x, y, z: Extended;
+    d, f, h, t, C: Extended;
+    Swap: Boolean;
+    Done: Boolean;
+  begin
+    if (aa <= 0.0) or (bb <= 0.0) then
+      raise EMathError.Create('Invalid Value');
+    a := aa;
+    b := bb;
+    Swap := b > a;
+    if Swap then
+    begin
+      g := b;
+      b := a;
+      a := g;
+    end;
+    d := a / b;
+    f := a + b;
+    if (b > 1.0) then
+    begin
+      h := Sqrt((2.0 * a * b - f) / (f - 2.0));
+      t := 1.0;
+    end
+    else
+    begin
+      h := b;
+      t := 1.0 / (1.0 + Power(a / (VLarge * b), b));
+    end;
+    C := a + h;
+
+    Done := False;
+    Result := 0.0;
+    repeat
+      r := RandomGenerator;
+      x := RandomGenerator;
+      s := Sqr(r) * x;
+      if (r < VSmall) or (s <= 0.0) then
+        Continue;
+
+      if (r < t) then
+      begin
+        x := Ln(r / (1.0 - r)) / h;
+        y := d * Exp(x);
+        z := C * x + f * Ln((1.0 + d) / (1.0 + y)) - aln4;
+        if (s - 1.0 > z) then
+        begin
+          if (s - s * z > 1.0) then
+            Continue;
+          if (Ln(s) > z) then
+            Continue;
+        end;
+        Result := y / (1.0 + y);
+      end
+      else
+      begin
+        if 4.0 * s > Power(1.0 + 1.0 / d, f) then
+          Continue;
+        Result := 1.0
+      end;
+      Done := True
+    until Done;
+
+    if Swap then
+      Result := 1 - Result;
+  end;
+
+  //---------------------------------------------------------------
+
+  function Random_Beta(const aa, bb: Extended): Extended;
+  begin
+    Result := Random_Beta(aa, bb, GenRandom);
+  end;
+
+  function Random_T(const DF: Integer; RandomGenerator: TRandomGenFunction)
+    : Extended;
+  var
+    s, C, a, f, g: Extended;
+    r, x, v: Extended;
+    Done: Boolean;
+  begin
+    if (DF < 1) then
+      raise EMathError.Create('Invalid Value');
+    s := DF;
+    C := -0.25 * (s + 1.0);
+    a := 4.0 / Power(1.0 + 1.0 / s, C);
+    f := 16.0 / a;
+    if (DF > 1) then
+    begin
+      g := s - 1.0;
+      g := Power((s + 1.0) / g, C) * Sqrt((s + s) / g);
+    end
+    else
+      g := 1.0;
+    Done := False;
+    x := 0;
+    repeat
+      r := RandomGenerator;
+      if (r <= 0.0) then
+        Continue;
+      v := RandomGenerator;
+      x := (2.0 * v - 1.0) * g / r;
+      v := Sqr(x);
+      if (v > 5.0 - a * r) then
+      begin
+        if (DF >= 1) and (r * (v + 3.0) > f) then
+          Continue;
+        if r > Power(1.0 + v / s, C) then
+          Continue;
+      end;
+      Done := True;
+    until Done;
+    Result := x;
+  end;
+
+//---------------------------------------------------------------
+
+  function Random_T(const DF: Integer): Extended;
+  begin
+    Result := Random_T(DF, GenRandom);
+  end;
+
+  procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
+    var ier: Integer; RandomGenerator: TRandomGenFunction);
+  var
+    i, j, M, n, n2, fn: Integer;
+    y, v: Extended;
+  begin
+    n := Length(h);
+    if (n = 0) then
+      raise EMathError.Create('Vector Empty');
+    fn := n * (n + 1) div 2;
+    if (Length(d) < fn) then
+      raise EMathError.Create('Vector Too Small');
+
+    SetLength(f, fn);
+    ier := 0;
+    n2 := 2 * n;
+    if (d[0] <= 0.0) then
+    begin
+      ier := 1;
+      Exit;
+    end;
+    f[0] := Sqrt(d[0]);
+    y := 1.0 / f[0];
+    for j := 2 to n do
+      f[j - 1] := d[j * (j - 1) div 2] * y;
+    for i := 2 to n do
+    begin
+      v := d[i * (i - 1) div 2 + i - 1];
+      for M := 1 to i - 1 do
+        v := v - Sqr(f[(M - 1) * (n2 - M) div 2 + i - 1]);
+
+      if (v <= 0.0) then
+      begin
+        ier := 1;
+        Exit;
+      end;
+      v := Sqrt(v);
+      y := 1.0 / v;
+      f[(i - 1) * (n2 - i) div 2 + i - 1] := v;
+
+      for j := i + 1 to n do
+      begin
+        v := d[j * (j - 1) div 2 + i - 1];
+        for M := 1 to i - 1 do
+        begin
+          v := v - f[(M - 1) * (n2 - M) div 2 + i - 1] *
+            f[(M - 1) * (n2 - M) div 2 + j - 1]
+        end;
+        f[(i - 1) * (n2 - i) div 2 + j - 1] := v * y;
+      end;
+    end;
+    x := Copy(h, 0, n);
+    for j := 1 to n do
+    begin
+      y := Random_Normal(RandomGenerator);
+      for i := j to n do
+        x[i - 1] := x[i - 1] + f[(j - 1) * (n2 - j) div 2 + i - 1] * y;
+    end;
+  end;
+
+  procedure Random_MVNorm(const h, d: TAMFloatVector; var f, x: TAMFloatVector;
+    var ier: Integer);
+  begin
+    Random_MVNorm(h, d, f, x, ier, GenRandom);
+  end;
+
+ //---------------------------------------------------------------
+
+  function Random_Inv_Gauss(const h, b: Extended;
+    RandomGenerator: TRandomGenFunction): Extended;
+  var
+    ym, xm, r, w, r1, r2, x: Extended;
+    a, C, d, e: Extended;
+    Done: Boolean;
+  begin
+    if (h < 0.0) or (b <= 0.0) then
+      raise EMathError.Create('Invalid Value');
+
+    if (h > 0.25 * b * Sqrt(VLarge)) then
+      raise EMathError.Create('Invalid Value');
+
+    e := Sqr(b);
+    d := h + 1.0;
+    ym := (-d + Sqrt(Sqr(d) + e)) / b;
+    if (ym < VSmall) then
+      raise EMathError.Create('Invalid Value');
+
+    d := h - 1.0;
+    xm := (d + Sqrt(Sqr(d) + e)) / b;
+    if (xm < VSmall) then
+      raise EMathError.Create('Invalid Value');
+
+    d := 0.5 * d;
+    e := -0.25 * b;
+    r := xm + 1.0 / xm;
+    w := xm * ym;
+    a := Power(w, -0.5 * h) * Sqrt(xm / ym) * Exp(-e * (r - ym - 1.0 / ym));
+    if (a < VSmall) then
+      raise EMathError.Create('Invalid Value');
+    C := -d * Ln(xm) - e * r;
+    Done := False;
+    x := 0.0;
+    repeat
+      r1 := RandomGenerator;
+      if (r1 > 0.0) then
+      begin
+        r2 := RandomGenerator;
+        x := a * r2 / r1;
+        if (x > 0.0) then
+        begin
+          if (Ln(r1) < d * Ln(x) + e * (x + 1.0 / x) + C) then
+            Done := True
+        end;
+      end
+      until Done;
+      Result := x;
+    end;
+
+    function Random_Inv_Gauss(const h, b: Extended): Extended;
+    begin
+      Result := Random_Inv_Gauss(h, b, GenRandom);
+    end;
+
+//---------------------------------------------------------------
+
+    function LnGamma(const x: Extended): Extended;
+    const
+      a1 = -4.166666666554424E-02;
+      a2 = 2.430554511376954E-03;
+      a3 = -7.685928044064347E-04;
+      a4 = 5.660478426014386E-04;
+      lnrt2pi = 9.189385332046727E-1;
+      pi = 3.141592653589793E0;
+    var
+      temp, arg, product: Extended;
+      reflect: Boolean;
+    begin
+      // lngamma is not defined if x = 0 or a negative integer.
+      if (x = 0.0) or ((x < 0.0) and (abs(x - Int(x)) < VSmall)) then
+        raise EMathError.Create('Invalid Value');
+
+      // If x < 0, use the reflection formula:
+      // gamma(x) * gamma(1-x) = pi * cosec(pi.x)
+
+      reflect := x < 0.0;
+      if reflect then
+        arg := 1.0 - x
+      else
+        arg := x;
+
+      // Increase the argument, if necessary, to make it > 10.
+      product := 1.0;
+      while (arg <= 10.0) do
+      begin
+        product := product * arg;
+        arg := arg + 1.0;
+      end;
+
+      // Use a polynomial approximation to Stirling's formula.
+      // N.B. The real Stirling's formula is used here, not the simpler, but less
+      // accurate formula given by De Moivre in a letter to Stirling, which
+      // is the one usually quoted.
+
+      arg := arg - 0.5;
+      temp := 1.0 / Sqr(arg);
+      Result := lnrt2pi + arg *
+        (Ln(arg) - 1.0 + (((a4 * temp + a3) * temp + a2) * temp + a1) * temp) -
+        Ln(product);
+
+      if reflect then
+      begin
+        temp := Sin(pi * x);
+        Result := Ln(pi / temp) - Result;
+      end;
+    end;
+
+    // Calculate a binomial probability
+
+    function Bin_Prob(const n: Int64; const p: Extended; const r: Int64)
+      : Extended;
+    begin
+      Result := Exp(LnGamma(n + 1.0) - LnGamma(r + 1.0) - LnGamma(n - r + 1.0) +
+        r * Ln(p) + (n - r) * Ln(1.0 - p));
+    end;
+
+   //---------------------------------------------------------------
+
+    function Random_Binomial1(const n: Integer; const p: Extended;
+      RandomGenerator: TRandomGenFunction): Int64;
+    var
+      ru, rd: Int64;
+      r0: Int64;
+      u, pd, pu: Real;
+      odds_ratio, p_r: Real;
+    begin
+      r0 := Trunc((n + 1) * p);
+      p_r := Bin_Prob(n, p, r0);
+      if p < 1 then
+        odds_ratio := p / (1.0 - p)
+      else
+        odds_ratio := VLarge;
+
+      u := RandomGenerator;
+      u := u - p_r;
+      if (u < 0.0) then
+      begin
+        Result := r0;
+        Exit;
+      end;
+
+      pu := p_r;
+      ru := r0;
+      pd := p_r;
+      rd := r0;
+
+      repeat
+        Dec(rd);
+        if (rd >= 0) then
+        begin
+          pd := pd * (rd + 1.0) / (odds_ratio * (n - rd));
+          u := u - pd;
+          if (u < 0.0) then
+          begin
+            Result := rd;
+            Exit;
+          end;
+        end;
+
+        Inc(ru);
+        if (ru <= n) then
+        begin
+          pu := pu * (n - ru + 1.0) * odds_ratio / ru;
+          u := u - pu;
+          if (u < 0.0) then
+          begin
+            Result := ru;
+            Exit;
+          end;
+        end;
+      until False;
+    end;
+
+   //---------------------------------------------------------------
+
+    function Random_Binomial1(const n: Integer; const p: Extended): Int64;
+    begin
+      Result := Random_Binomial1(n, p, GenRandom);
+    end;
+
+    function Random_Binomial2(const n: Int64; const pp: Extended;
+      RandomGenerator: TRandomGenFunction): Int64;
+    var
+      alv, amaxp, f, f1, f2, u, v, w, w2, x, x1, x2, ynorm, z, z2: Extended;
+      i: Integer;
+      ix, ix1, k, mp: Int64;
+      M: Int64;
+      p, q, xnp, ffm, fm, xnpq, p1, xm, xl, xr, C, al, xll, xlr, p2, p3, p4, qn,
+        r, g: Extended;
+      Done: Boolean;
+    begin
+      // SETUP
+      p := Min(pp, 1.0 - pp);
+      q := 1.0 - p;
+      xnp := n * p;
+
+      if (xnp > 30.0) then
+      begin
+        ffm := xnp + p;
+        M := Trunc(ffm);
+        fm := M;
+        xnpq := xnp * q;
+        p1 := Int(2.195 * Sqrt(xnpq) - 4.6 * q) + 0.5;
+        xm := fm + 0.5;
+        xl := xm - p1;
+        xr := xm + p1;
+        C := 0.134 + 20.5 / (15.3 + fm);
+        al := (ffm - xl) / (ffm - xl * p);
+        xll := al * (1.0 + 0.5 * al);
+        al := (xr - ffm) / (xr * q);
+        xlr := al * (1.0 + 0.5 * al);
+        p2 := p1 * (1.0 + C + C);
+        p3 := p2 + C / xll;
+        p4 := p3 + C / xlr;
+
+        // GENERATE VARIATE, Binomial mean at least 30.
+        ix := 0;
+        repeat
+          ;
+          u := RandomGenerator; // 20
+          u := u * p4;
+          v := RandomGenerator;
+
+          // TRIANGULAR REGION
+          if (u <= p1) then
+          begin
+            ix := Trunc(xm - p1 * v + u);
+            Break;
+          end;
+
+          // PARALLELOGRAM REGION
+          if (u <= p2) then
+          begin
+            x := xl + (u - p1) / C;
+            v := v * C + 1.0 - abs(xm - x) / p1;
+            if (v > 1.0) or (v <= 0) then
+              Continue;
+            ix := Trunc(x);
+          end
+          else
+          begin
+            // LEFT TAIL
+            if (u <= p3) then
+            begin
+              ix := Trunc(xl + Ln(v) / xll);
+              if (ix < 0) then
+                Continue;
+              v := v * (u - p2) * xll
+            end
+            // RIGHT TAIL
+            else
+            begin
+              ix := Trunc(xr - Ln(v) / xlr);
+              if (ix > n) then
+                Continue;
+              v := v * (u - p3) * xlr;
+            end;
+          end;
+
+          // DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST
+          k := abs(ix - M);
+          if (k <= 20) or (k >= xnpq / 2 - 1) then
+          begin
+            // EXPLICIT EVALUATION
+            f := 1.0;
+            r := p / q;
+            g := (n + 1) * r;
+            if (M < ix) then
+            begin
+              mp := M + 1;
+              for i := mp to ix do
+                f := f * (g / i - r);
+            end
+            else if (M > ix) then
+            begin
+              ix1 := ix + 1;
+              for i := ix1 to M do
+                f := f / (g / i - r);
+            end;
+
+            if (v > f) then
+              Continue
+            else
+              Break
+          end;
+
+          // SQUEEZING USING UPPER AND LOWER BOUNDS ON LOG(F(X))
+          amaxp := (k / xnpq) * ((k * (k / 3.0 + 0.625) + 0.1666666666666) /
+            xnpq + 0.5);
+          ynorm := -Sqr(k) / (2.0 * xnpq);
+          alv := Ln(v);
+          if (alv < ynorm - amaxp) then
+            Break;
+          if (alv > ynorm + amaxp) then
+            Continue;
+          // STIRLING'S (actually de Moivre's) FORMULA TO MACHINE ACCURACY FOR
+          // THE FINAL ACCEPTANCE/REJECTION TEST
+
+          x1 := ix + 1;
+          f1 := fm + 1.0;
+          z := n + 1 - fm;
+          w := n - ix + 1.0;
+          z2 := Sqr(z);
+          x2 := Sqr(x1);
+          f2 := Sqr(f1);
+          w2 := Sqr(w);
+          if (alv - (xm * Ln(f1 / x1) + (n - M + 0.5) * Ln(z / w) + (ix - M) *
+            Ln(w * p / (x1 * q)) + (13860.0 -
+            (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 /
+            166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) /
+            z2) / z2) / z / 166320.0 +
+            (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) /
+            x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) /
+            w2) / w2) / w2) / w / 166320.0) > 0.0) then
+          begin
+            Continue;
+          end
+          else
+            Break;
+        until False;
+      end
+      else
+      begin
+        // INVERSE CDF LOGIC FOR MEAN LESS THAN 30
+        qn := Power(q, n);
+        r := p / q;
+        g := r * (n + 1);
+
+        Done := False;
+        repeat
+          ix := 0;
+          f := qn;
+          u := RandomGenerator;
+          while (u >= f) do
+          begin
+            if (ix > 110) then
+              Done := False
+            else
+            begin
+              Done := True;
+              u := u - f;
+              ix := ix + 1;
+              f := f * (g / ix - r);
+            end;
+          end;
+        until Done;
+      end;
+      if (pp > 0.5) then
+        ix := n - ix;
+      Result := ix;
+    end;
+
+  //---------------------------------------------------------------
+
+    function Random_Binomial2(const n: Int64; const pp: Extended): Int64;
+    begin
+      Result := Random_Binomial2(n, pp, GenRandom);
+    end;
+
+    function Random_Neg_Binomial(const sk, p: Extended;
+      RandomGenerator: TRandomGenFunction): Int64;
+    const
+      h = 0.7;
+    var
+      q, x, st, uln, v, r, s, y, g: Extended;
+      k, n: Int64;
+      i: Integer;
+    begin
+      if (sk <= 0.0) or (p <= 0.0) or (p >= 1.0) then
+        raise EMathError.Create('Invalid Value');
+
+      q := 1.0 - p;
+      x := 0.0;
+      st := sk;
+      if (p > h) then
+      begin
+        v := 1.0 / Ln(p);
+        k := Trunc(st);
+        for i := 1 to k do
+        begin
+          repeat
+            r := RandomGenerator;
+          until r > 0.0;
+          n := Trunc(v * Ln(r));
+          x := x + n;
+        end;
+        st := st - k;
+      end;
+
+      s := 0.0;
+      uln := -Ln(VSmall);
+      if (st > -uln / Ln(q)) then
+        raise EMathError.Create('Invalid Value');
+
+      y := Power(q, st);
+      g := st;
+      r := RandomGenerator;
+      while (y <= r) do
+      begin
+        r := r - y;
+        s := s + 1.0;
+        y := y * p * g / s;
+        g := g + 1.0;
+      end;
+      Result := Trunc(x + s + 0.5)
+    end;
+
+  //---------------------------------------------------------------
+
+    function Random_Neg_Binomial(const sk, p: Extended): Int64;
+    begin
+      Result := Random_Neg_Binomial(sk, p, GenRandom);
+    end;
+
+    // Gaussian integration of exp(k.cosx) from a to b.
+    procedure Integral(const a, b: Extended; var res: Extended;
+      const dk: Extended);
+    var
+      xmid, range, x1, x2: Extended;
+      x, w: array [1 .. 3] of Extended;
+      i: Integer;
+    begin
+      x[1] := 0.238619186083197;
+      x[2] := 0.661209386466265;
+      x[3] := 0.932469514203152;
+      w[1] := 0.467913934572691;
+      w[2] := 0.360761573048139;
+      w[3] := 0.171324492379170;
+
+      xmid := (a + b) / 2.0;
+      range := (b - a) / 2.0;
+
+      res := 0.0;
+      for i := 1 to 3 do
+      begin
+        x1 := xmid + x[i] * range;
+        x2 := xmid - x[i] * range;
+        res := res + w[i] * (Exp(dk * Cos(x1)) + Exp(dk * Cos(x2)))
+      end;
+
+      res := res * range;
+    end;
+
+    function Random_von_Mises(const k: Extended;
+      RandomGenerator: TRandomGenFunction): Extended;
+    var
+      j, n, jj: Integer;
+      nk: Integer;
+      p: array [1 .. 20] of Extended;
+      theta: array [0 .. 20] of Extended;
+      xx, sump, r, th, lambda, rlast: Extended;
+      dk: Extended;
+    begin
+      if (k < 0.0) then
+        raise EMathError.Create('Invalid Value');
+
+      nk := Trunc(k + k + 1.0);
+      if (nk > 20) then
+        raise EMathError.Create('Invalid Value');
+
+      dk := k;
+      theta[0] := 0.0;
+      if (k > 0.5) then
+      begin
+        // Set up array p of probabilities.
+        sump := 0.0;
+        for j := 1 to nk do
+        begin
+          if (j < nk) then
+            theta[j] := ArcCos(1.0 - j / k)
+          else
+            theta[nk] := pi;
+
+          // Numerical integration of e^[k.cos(x)] from theta(j-1) to theta(j)
+          Integral(theta[j - 1], theta[j], p[j], dk);
+          sump := sump + p[j];
+        end;
+        for j := 1 to nk do
+          p[j] := p[j] / sump;
+      end
+      else
+      begin
+        p[1] := 1.0;
+        theta[1] := pi;
+      end;
+
+      r := RandomGenerator;
+      jj := nk;
+      for j := 1 to nk do
+      begin
+        r := r - p[j];
+        if (r < 0.0) then
+        begin
+          jj := j;
+          Break;
+        end;
+      end;
+      r := -r / p[jj];
+
+      repeat
+        th := theta[jj - 1] + r * (theta[jj] - theta[j - 1]);
+        lambda := k - jj + 1.0 - k * Cos(th);
+        n := 1;
+        rlast := lambda;
+
+        repeat
+          r := RandomGenerator;
+          if r <= rlast then
+          begin
+            Inc(n);
+            rlast := r;
+          end;
+        until (r > rlast);
+
+        if not Odd(n) then
+          r := RandomGenerator until Odd(n);
+
+        th := abs(th);
+        xx := (r - rlast) / (1.0 - rlast) - 0.5;
+        if xx < 0 then
+          Result := -1 * th
+        else
+          Result := th;
+      end;
+
+//---------------------------------------------------------------
+
+      function Random_von_Mises(const k: Extended): Extended;
+      begin
+        Result := Random_von_Mises(k, GenRandom);
+      end;
+
+      function Random_Cauchy(RandomGenerator: TRandomGenFunction): Extended;
+      var
+        V1, V2: Extended;
+      begin
+        repeat
+          V1 := 2.0 * (RandomGenerator - 0.5);
+          V2 := 2.0 * (RandomGenerator - 0.5);
+        until (abs(V2) > VSmall) and (Sqr(V1) + Sqr(V2) < 1.0);
+        Result := V1 / V2;
+      end;
+
+      function Random_Cauchy: Extended;
+      begin
+        Result := Random_Cauchy(GenRandom);
+      end;
+
+//---------------------------------------------------------------
+
+      function Random_Poisson(var mu: Extended;
+        RandomGenerator: TRandomGenFunction): Int64;
+      const
+        a0 = -0.5;
+        a1 = 0.3333333;
+        a2 = -0.2500068;
+        a3 = 0.2000118;
+        a4 = -0.1661269;
+        a5 = 0.1421878;
+        a6 = -0.1384794;
+        a7 = 0.1250060;
+
+      var
+        b1, b2, C, c0, c1, c2, c3, del, difmuk, e, fk, fx, fy, g, omega, px, py,
+          t, u, v, x, xx: Extended;
+        s, d, p, q, p0: Extended;
+        j, k, kflag: Integer;
+        l, M: Integer;
+        pp: array [1 .. 35] of Extended;
+        fact: array [1 .. 10] of Extended;
+        FirstK0: Boolean;
+      begin
+        u := 0;
+        e := 0;
+        fk := 0;
+        difmuk := 0;
+
+        fact[1] := 1; // Factorial 0
+        fact[2] := 1;
+        fact[3] := 2;
+        fact[4] := 6;
+        fact[5] := 24;
+        fact[6] := 120;
+        fact[7] := 720;
+        fact[8] := 5040;
+        fact[9] := 40320;
+        fact[10] := 362880; // Factorial 9
+
+        Result := 0;
+        if (mu > 10.0) then
+        begin
+          // C A S E  A. (RECALCULATION OF S, D, L IF MU HAS CHANGED)
+          FirstK0 := False;
+
+          s := Sqrt(mu);
+          d := 6.0 * Sqr(mu);
+
+          // THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
+          // PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484)
+          // IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
+
+          l := Trunc(mu - 1.1484);
+
+          // STEP N. NORMAL SAMPLE - random_normal() FOR STANDARD NORMAL DEVIATE
+
+          g := mu + s * Random_Normal(RandomGenerator);
+          if (g > 0.0) then
+          begin
+            Result := Trunc(g);
+            // STEP I. IMMEDIATE ACCEPTANCE IF ival IS LARGE ENOUGH
+            if (Result >= l) then
+              Exit;
+            // STEP S. SQUEEZE ACCEPTANCE - SAMPLE U
+            fk := Result;
+            difmuk := mu - fk;
+            u := RandomGenerator;
+            if (d * u >= Sqr(difmuk) * difmuk) then
+              Exit;
+          end;
+
+          // STEP P. PREPARATIONS FOR STEPS Q AND H.
+          // (RECALCULATIONS OF PARAMETERS IF NECESSARY)
+          // .3989423=(2*Pi)**(-.5)  .416667E-1=1./24.  .1428571=1./7.
+          // THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
+          // APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
+          // C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
+
+          omega := 0.3989423 / s;
+          b1 := 0.4166667E-1 / mu;
+          b2 := 0.3 * Sqr(b1);
+          c3 := 0.1428571 * b1 * b2;
+          c2 := b2 - 15.0 * c3;
+          c1 := b1 - 6.0 * b2 + 45.0 * c3;
+          c0 := 1.0 - b1 + 3.0 * b2 - 15.0 * c3;
+          C := 0.1069 / mu;
+
+          kflag := -1;
+          if (g >= 0.0) then
+          begin
+            // 'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
+            kflag := 0;
+            FirstK0 := True;
+          end;
+          // STEP E. EXPONENTIAL SAMPLE - random_exponential() FOR STANDARD EXPONENTIAL
+          // DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
+          // (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
+          repeat // 50
+            if not FirstK0 then
+            begin
+              repeat // 50
+                e := Random_Exponential(RandomGenerator);
+                u := RandomGenerator;
+                u := u + u - 1.0;
+                if u < 0 then
+                  t := 1.8 - abs(e)
+                else
+                  t := 1.8 + abs(e);
+              until t > -0.6744;
+
+              Result := Trunc(mu + s * t);
+              fk := Result;
+              difmuk := mu - fk;
+
+              // 'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
+
+              kflag := 1
+            end
+            else
+              FirstK0 := False;
+
+            // STEP F. 'SUBROUTINE' F. CALCULATION OF PX, PY, FX, FY.
+            // CASE ival < 10 USES FACTORIALS FROM TABLE FACT
+
+            if (Result < 10) then // 70
+            begin
+              px := -mu;
+              py := Power(mu, Result) / fact[Result + 1];
+            end
+            else
+            begin
+              // CASE ival >= 10 USES POLYNOMIAL APPROXIMATION
+              // A0-A7 FOR ACCURACY WHEN ADVISABLE
+              // .8333333E-1=1./12.  .3989423=(2*Pi)**(-.5)
+
+              del := 0.8333333E-1 / fk; // 80
+              del := del - 4.8 * Sqr(del) * del;
+              v := difmuk / fk;
+              if abs(v) > 0.25 then
+                px := fk * Ln(1.0 + v) - difmuk - del
+              else
+                px := fk * Sqr(v) *
+                  (((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) *
+                  v + a1) * v + a0) - del;
+              py := 0.3989423 / Sqrt(fk);
+            end;
+            x := (0.5 - difmuk) / s; // 110
+            xx := Sqr(x);
+            fx := -0.5 * xx;
+            fy := omega * (((c3 * xx + c2) * xx + c1) * xx + c0);
+            if (kflag <= 0) then
+            begin
+              // STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
+
+              if (fy - u * fy <= py * Exp(px - fx)) then // 40
+                Exit;
+            end
+            else
+            begin
+              // STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
+
+              if (C * abs(u) <= py * Exp(px + e) - fy * Exp(fx + e)) then // 60
+                Exit;
+            end;
+          until False;
+        end
+        else
+        begin
+          // C A S E  B.    mu < 10
+          // START NEW TABLE AND CALCULATE P0 IF NECESSARY
+
+          M := MAX(1, Trunc(mu));
+          l := 0;
+          p := Exp(-mu);
+          q := p;
+          p0 := p;
+
+          // STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
+          repeat
+            u := RandomGenerator;
+            Result := 0;
+            if (u <= p0) then
+              Exit;
+            // STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
+            // PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
+            // (0.458=PP(9) FOR MU=10)
+            if l <> 0 then
+            begin
+              j := 1;
+              if (u > 0.458) then
+                j := Min(l, M);
+              for k := j to l do
+                if (u <= pp[k]) then
+                begin
+                  Result := k;
+                  Exit;
+                end;
+
+              if l = 35 then
+                Continue;
+            end;
+
+            // STEP C. CREATION OF NEW POISSON PROBABILITIES P
+            // AND THEIR CUMULATIVES Q = PP(K)
+
+            l := l + 1; // 150
+            for k := l to 35 do
+            begin
+              p := p * mu / k;
+              q := q + p;
+              pp[k] := q;
+              if (u <= q) then
+              begin
+                Result := k;
+                Exit;
+              end;
+            end;
+            l := 35;
+          until False end;
+        end;
+
+//---------------------------------------------------------------
+
+        function Random_Poisson(var mu: Extended): Int64;
+        begin
+          Result := Random_Poisson(mu, GenRandom);
+        end;
+
+end.

+ 392 - 71
Source/GLS.SkyDome.pas

@@ -3,7 +3,7 @@
 //
 unit GLS.SkyDome;
 
-(* Skydome object with celestial grids *)
+(* Skydome classes with celestial grids and routine functions *)
 
 interface
 
@@ -29,10 +29,10 @@ uses
 type
 
    TGLStarRecord = packed record
-      RA : Word;              // x100 builtin factor, degrees
-      DEC : SmallInt;         // x100 builtin factor, degrees
-      BVColorIndex : Byte;    // x100 builtin factor
-      VMagnitude : Byte;      // x10 builtin factor
+      RA : Word;              // Right Ascension, x100 builtin factor, degrees
+      DEC : SmallInt;         // Declination, x100 builtin factor, degrees
+      BVColorIndex : Byte;    // ColorIndex, x100 builtin factor
+      VMagnitude : Byte;      // Magnitude, x10 builtin factor
    end;
    PGLStarRecord = ^TGLStarRecord;
 
@@ -174,7 +174,7 @@ type
     procedure BuildList(var rci: TGLRenderContextInfo; twinkle: Boolean);
     (* Adds nb random stars of the given color.
       Stars are homogenously scattered on the complete sphere, not only the band defined or visible dome. *)
-    procedure AddRandomStars(const nb: Integer; const color: TColor; const limitToTopDome: Boolean = False); overload;
+    procedure AddRandomStars(const nb: Integer; const color: TColor; const LimitToTopDome: Boolean = False); overload;
     procedure AddRandomStars(const nb: Integer; const ColorMin, ColorMax:TVector3b;
 	   const Magnitude_min, Magnitude_max: Single;
 	   const limitToTopDome: Boolean = False); overload;
@@ -251,6 +251,8 @@ type
     procedure SetStacks(const val: Integer);
     procedure OnColorChanged(Sender: TObject);
     procedure PreCalculate;
+    (* Coordinates system note: X is forward, Y is left and Z is up
+       always rendered as sphere of radius 1 *)
     procedure RenderDome;
     function CalculateColor(const theta, cosGamma: Single): TGLColorVector;
   public
@@ -275,21 +277,352 @@ type
     property Stacks: Integer read FStacks write SetStacks default 48;
   end;
 
+
+type
+  TGLStarSysData = record
+    NbStar: byte; // Only 1 allowed so far
+    NbPlanet: byte;
+    NbAsteroid: byte;
+    NbComet: byte;
+    NbDebris: byte;
+  end;
+
+  TGLStarData = record // Also equal to material texture
+    (* ONLY .jpg;  Expected: .bmp  .tif  .tga  .png ignored *)
+    StarName: String[255];
+    Radius: Double;
+    ObjectRotation: Double;
+    AxisTilt: Double;
+    nbS3ds: byte;
+    DocIndex: byte;
+    StarSysScale: Double;
+    StarDistanceScale: Double;
+  end;
+
+  TGLPlanetData = record
+    // Planet.jpg .. Planet_bump.jpg
+    Name: String[255];
+    Radius: Double;
+    ObjectRotation: Double;
+    AxisTilt: Double;
+    nbRings: byte;
+    nbMoons: byte;
+    nbS3ds: byte;
+    DocIndex: byte;
+
+    Albedo, OrbitRotation: Double;
+    aDistance, aDistanceVar: Double; // aConstEdit aVarEdit
+    Inclination, InclinationVar: Double; // iConstEdit iVarEdit
+    Eccentricity, EVar, EMax: Double; // eConstEdit eVarEdit EMaxEdit
+    nLongitude, nLongitudeVar: Double; // NConstEdit NVarEdit
+    wPerihelion, wPerihelionVar: Double; // wConstEdit wVarEdit
+    mAnomaly, mAnomalyVar: Double; // MConstEdit MVarEdit
+
+    Mass, Density: Double;
+    Atmosphere, VelocityType: byte;
+    (* Which way does the wind blow Given a direction
+      0 to 100 or 1 to 100 is that 100 or 101 *)
+    Velocity, VelocityDir: Double;
+  end;
+
+  TGLMoonRingData = record // 3ds files and DebrisAsteroid  too
+    Name: String[255]; // Planet_Moon.jpg
+    Radius: Double;
+    ObjectRotation: Double;
+    AxisTilt: Double;
+    S3dsTex: Boolean;
+    DocIndex: byte;
+    Mass, Density: Double;
+
+    RCDType, RCDCount: Integer;
+    RCDXYSize, RCDZSize, RCDPosition: Double;
+
+    Albedo, OrbitRotation: Double;
+    aDistance, aDistanceVar: Double;
+    Inclination, InclinationVar: Double;
+    Eccentricity, EVar, EMax: Double;
+    nLongitude, nLongitudeVar: Double;
+    wPerihelion, wPerihelionVar: Double;
+    mAnomaly, mAnomalyVar: Double;
+
+    Atmosphere, VelocityType: byte;
+    Velocity, VelocityDir: Double;
+  end;
+
+  TGLAsteroidData = record // Asteroid Comet spheres..NOT DebrisAsteroid
+    Name: String[255];
+    Radius: Double;
+    ObjectRotation: Double;
+    AxisTilt: Double;
+    nbS3ds: byte;
+    DocIndex: byte;
+    RCDType, RCDCount: Integer;
+    RCDXYSize, RCDZSize, RCDPosition: Double;
+    Albedo, OrbitRotation: Double;
+    aDistance, aDistanceVar: Double;
+    Inclination, InclinationVar: Double;
+    Eccentricity, EVar, EMax: Double;
+    nLongitude, nLongitudeVar: Double;
+    wPerihelion, wPerihelionVar: Double;
+    mAnomaly, mAnomalyVar: Double;
+    Mass, Density: Double;
+    Atmosphere, VelocityType: byte;
+    Velocity, VelocityDir: Double;
+  end;
+
+  // For recomputation of TOrbitalElementsData
+  TOrbitalElements = record
+    N: Double; // longitude of the ascending node
+    i: Double; // inclination to the ecliptic (plane of the Earth's orbit)
+    w: Double; // argument of perihelion
+    a: Double; // semi-major axis, or mean distance from Sun
+    e: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
+    M: Double; // mean anomaly (0 at perihelion; increases uniformly with time)
+  end;
+
+  TOrbitalElementsData = record
+    NConst, NVar: Double; // longitude of the ascending node
+    iConst, iVar: Double; // inclination to the ecliptic (plane of the Earth's orbit)
+    wConst, wVar: Double; // argument of perihelion
+    aConst, aVar: Double; // semi-major axis, or mean distance from Sun
+    eConst, eVar: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
+    MConst, MVar: Double; // mean anomaly (0 at perihelion; increases uniformly with time)
+  end;
+
+const
+  // geocentric sun elements
+  cSunOrbitalElements: TOrbitalElementsData = (NConst: 0.0; NVar: 0.0;
+    iConst: 0.0; iVar: 0.0; wConst: 282.9404; wVar: 4.70935E-5;
+    aConst: 1.000000; aVar: 0.0; // (AU)
+    eConst: 0.016709; eVar: - 1.151E-9; MConst: 356.0470; MVar: 0.9856002585);
+
+  // geocentric moon elements
+  cMoonOrbitalElements: TOrbitalElementsData = (NConst: 125.1228;
+    NVar: - 0.0529538083; iConst: 5.1454; iVar: 0.0; wConst: 318.0634;
+    wVar: 0.1643573223; aConst: 60.2666; aVar: 0.0; // (Earth radii)
+    eConst: 0.054900; eVar: 0.0; MConst: 115.3654; MVar: 13.0649929509);
+
+  // heliocentric mercury elements
+  cMercuryOrbitalElements: TOrbitalElementsData = (NConst: 48.3313;
+    NVar: 3.24587E-5; iConst: 7.0047; iVar: 5.00E-8; wConst: 29.1241;
+    wVar: 1.01444E-5; aConst: 0.387098; aVar: 0.0; // (AU)
+    eConst: 0.205635; eVar: 5.59E-10; MConst: 168.6562; MVar: 4.0923344368);
+
+  // heliocentric venus elements
+  cVenusOrbitalElements: TOrbitalElementsData = (NConst: 76.6799;
+    NVar: 2.46590E-5; iConst: 3.3946; iVar: 2.75E-8; wConst: 54.8910;
+    wVar: 1.38374E-5; aConst: 0.723330; aVar: 0.0; // (AU)
+    eConst: 0.006773; eVar: - 1.302E-9; MConst: 48.0052; MVar: 1.6021302244);
+
+  // heliocentric mars elements
+  cMarsOrbitalElements: TOrbitalElementsData = (NConst: 49.5574;
+    NVar: 2.11081E-5; iConst: 1.8497; iVar: - 1.78E-8; wConst: 286.5016;
+    wVar: 2.92961E-5; aConst: 1.523688; aVar: 0.0; // (AU)
+    eConst: 0.093405; eVar: 2.516E-9; MConst: 18.6021; MVar: 0.5240207766);
+
+  // heliocentric jupiter elements
+  cJupiterOrbitalElements: TOrbitalElementsData = (NConst: 100.4542;
+    NVar: 2.76854E-5; iConst: 1.3030; iVar: - 1.557E-7; wConst: 273.8777;
+    wVar: 1.64505E-5; aConst: 5.20256; aVar: 0.0; // (AU)
+    eConst: 0.048498; eVar: 4.469E-9; MConst: 19.8950; MVar: 0.0830853001);
+
+  // heliocentric saturn elements
+  cSaturnOrbitalElements: TOrbitalElementsData = (NConst: 113.6634;
+    NVar: 2.38980E-5; iConst: 2.4886; iVar: - 1.081E-7; wConst: 339.3939;
+    wVar: 2.97661E-5; aConst: 9.55475; aVar: 0.0; // (AU)
+    eConst: 0.055546; eVar: - 9.499E-9; MConst: 316.9670; MVar: 0.0334442282);
+
+  // heliocentric uranus elements
+  cUranusOrbitalElements: TOrbitalElementsData = (NConst: 74.0005;
+    NVar: 1.3978E-5; iConst: 0.7733; iVar: 1.9E-8; wConst: 96.6612;
+    wVar: 3.0565E-5; aConst: 19.18171; aVar: - 1.55E-8; // (AU)
+    eConst: 0.047318; eVar: 7.45E-9; MConst: 142.5905; MVar: 0.011725806);
+
+  // heliocentric neptune elements
+  cNeptuneOrbitalElements: TOrbitalElementsData = (NConst: 131.7806;
+    NVar: 3.0173E-5; iConst: 1.7700; iVar: - 2.55E-7; wConst: 272.8461;
+    wVar: - 6.027E-6; aConst: 30.05826; aVar: 3.313E-8; // (AU)
+    eConst: 0.008606; eVar: 2.15E-9; MConst: 260.2471; MVar: 0.005995147);
+  // heliocentric pluto elements
+  cPlutoOrbitalElements: TOrbitalElementsData = (NConst: 162.7806;
+    NVar: 3.0173E-5; iConst: 1.7700; iVar: - 2.55E-7; wConst: 272.8461;
+    wVar: - 6.027E-6; aConst: 30.05826; aVar: 3.313E-8; // (AU)
+    eConst: 0.008606; EVar: 2.15E-9; MConst: 260.2471; MVar: 0.005995147);
+
+  cAUToKilometers = 149.6E6; // astronomical units to kilometers
+  cEarthRadius = 6371; // average earth radius in kilometers
+
+// Converts a TDateTime (GMT+0) into the Julian day used for computations.
+function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
+// Compute orbital elements for given Julian day.
+function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
+  const d: Double): TOrbitalElements;
+
+// Compute the planet position for given Julian day (in AU).
+function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
+  : TAffineVector; overload;
+
+function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
+  const d: Double): TAffineVector; overload;
+
 // Computes position on the unit sphere of a star record (Z=up)
 function StarRecordPositionZUp(const starRecord: TGLStarRecord): TAffineVector;
+
 // Computes position on the unit sphere of a star record (Y=up)
 function StarRecordPositionYUp(const starRecord: TGLStarRecord): TAffineVector;
+
+// Computes position on the unit sphere of a star using Longitude and Latitude
+function LonLatToPos(Lon, Lat: Single): TAffineVector;
+
 // Computes star color from BV index (RGB) and magnitude (alpha)
 function StarRecordColor(const starRecord: TGLStarRecord; bias: Single): TVector4f;
 
-// ------------------------------------------------------------------
+//----------------------------------------------------------------------
 implementation
-// ------------------------------------------------------------------
+//----------------------------------------------------------------------
 
 uses
   GLS.Context,
   GLS.State;
 
+//--------------------------- Functions --------------------------------
+
+function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
+begin
+  Result := dt - EncodeDate(2000, 1, 1);
+end;
+
+//--------------------------------------------------------------------------------
+
+function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
+  const d: Double): TOrbitalElements;
+begin
+  with Result, oeData do
+  begin
+    N := NConst + NVar * d;
+    i := iConst + iVar * d;
+    w := wConst + wVar * d;
+    a := aConst + aVar * d;
+    e := eConst + eVar * d;
+    M := MConst + MVar * d;
+  end;
+end;
+
+//--------------------------------------------------------------------------------
+
+function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
+  : TAffineVector;
+var
+  eccentricAnomaly, eA0: Double;
+  sm, cm, se, ce, si, ci, cn, sn, cvw, svw: Double;
+  xv, yv, v, r: Double;
+  nn: Integer; // numerical instability bailout
+begin
+  with orbitalElements do
+  begin
+    // E = M + e*(180/pi) * sin(M) * ( 1.0 + e * cos(M) )
+    SinCos(M * cPIdiv180, sm, cm);
+    eccentricAnomaly := M + e * c180divPI * sm * (1.0 + e * cm);
+
+    nn := 0;
+    repeat
+      eA0 := eccentricAnomaly;
+      // E1 = E0 - ( E0 - e*(180/pi) * sin(E0) - M ) / ( 1 - e * cos(E0) )
+      SinCos(eA0 * cPIdiv180, se, ce);
+      eccentricAnomaly := eA0 - (eA0 - e * c180divPI * se - M) / (1 - e * ce);
+      Inc(nn);
+    until (nn > 10) or (Abs(eccentricAnomaly - eA0) < 1E-4);
+
+    SinCos(eccentricAnomaly * cPIdiv180, se, ce);
+    xv := a * (ce - e);
+    yv := a * (Sqrt(1.0 - e * e) * se);
+
+    v := ArcTan2(yv, xv) * c180divPI;
+    r := Sqrt(xv * xv + yv * yv);
+
+    SinCos(i * cPIdiv180, si, ci);
+    SinCos(N * cPIdiv180, sn, cn);
+    SinCos((v + w) * cPIdiv180, svw, cvw);
+  end;
+
+  // xh = r * ( cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i) )
+  Result.X := r * (cn * cvw - sn * svw * ci);
+  // yh = r * ( sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i) )
+  Result.Y := r * (sn * cvw + cn * svw * ci);
+  // zh = r * ( sin(v+w) * sin(i) )
+  Result.Z := r * (svw * si);
+end;
+
+//--------------------------------------------------------------------------------
+
+function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
+  const d: Double): TAffineVector;
+var
+  oe: TOrbitalElements;
+begin
+  oe := ComputeOrbitalElements(orbitalElementsData, d);
+  Result := ComputePlanetPosition(oe);
+end;
+
+//----------------------------------------------------------------------
+function StarRecordPositionYUp(const starRecord: TGLStarRecord): TAffineVector;
+var
+  f: Single;
+begin
+  SinCosine(starRecord.DEC * (0.01 * PI / 180), Result.Y, f);
+  SinCosine(starRecord.RA * (0.01 * PI / 180), f, Result.X, Result.Z);
+end;
+
+//----------------------------------------------------------------------
+
+function StarRecordPositionZUp(const starRecord: TGLStarRecord): TAffineVector;
+var
+  f: Single;
+begin
+  SinCosine(starRecord.DEC * (0.01 * PI / 180), Result.Z, f);
+  SinCosine(starRecord.RA * (0.01 * PI / 180), f, Result.X, Result.Y);
+end;
+
+//----------------------------------------------------------------------
+
+function LonLatToPos(Lon, Lat: Single): TAffineVector;
+var
+  f: Single;
+begin
+  SinCosine(Lat * (PI / 180), Result.Y, f);
+  SinCosine(Lon * (360 / 24 * PI / 180), f, Result.X, Result.Z);
+end;
+
+//----------------------------------------------------------------------
+
+function StarRecordColor(const starRecord: TGLStarRecord; bias: Single): TVector4f;
+const
+  // very *rough* approximation
+  cBVm035: TVector4f = (X: 0.7; Y: 0.8; Z: 1.0; W: 1);
+  cBV015: TVector4f = (X: 1.0; Y: 1.0; Z: 1.0; W: 1);
+  cBV060: TVector4f = (X: 1.0; Y: 1.0; Z: 0.7; W: 1);
+  cBV135: TVector4f = (X: 1.0; Y: 0.8; Z: 0.7; W: 1);
+var
+  bvIndex100: Integer;
+begin
+  bvIndex100 := starRecord.BVColorIndex - 50;
+  // compute RGB color for B&V index
+  if bvIndex100 < -035 then
+    Result := cBVm035
+  else if bvIndex100 < 015 then
+    VectorLerp(cBVm035, cBV015, (bvIndex100 + 035) * (1 / (015 + 035)), Result)
+  else if bvIndex100 < 060 then
+    VectorLerp(cBV015, cBV060, (bvIndex100 - 015) * (1 / (060 - 015)), Result)
+  else if bvIndex100 < 135 then
+    VectorLerp(cBV060, cBV135, (bvIndex100 - 060) * (1 / (135 - 060)), Result)
+  else
+    Result := cBV135;
+  // compute transparency for VMag
+  // the actual factor is 2.512, and not used here
+  Result.W := PowerSingle(1.2, -(starRecord.VMagnitude * 0.1 - bias));
+end;
+
+
 // ------------------
 // ------------------ TGLSkyBox ------------------
 // ------------------
@@ -632,49 +965,6 @@ end;
 
 //--------------------- SkyDome Region ------------------------------
 
-function StarRecordPositionYUp(const starRecord: TGLStarRecord): TAffineVector;
-var
-  f: Single;
-begin
-  SinCosine(starRecord.DEC * (0.01 * PI / 180), Result.Y, f);
-  SinCosine(starRecord.RA * (0.01 * PI / 180), f, Result.X, Result.Z);
-end;
-
-function StarRecordPositionZUp(const starRecord: TGLStarRecord): TAffineVector;
-var
-  f: Single;
-begin
-  SinCosine(starRecord.DEC * (0.01 * PI / 180), Result.Z, f);
-  SinCosine(starRecord.RA * (0.01 * PI / 180), f, Result.X, Result.Y);
-end;
-
-function StarRecordColor(const starRecord: TGLStarRecord; bias: Single): TVector4f;
-const
-  // very *rough* approximation
-  cBVm035: TVector4f = (X: 0.7; Y: 0.8; Z: 1.0; W: 1);
-  cBV015: TVector4f = (X: 1.0; Y: 1.0; Z: 1.0; W: 1);
-  cBV060: TVector4f = (X: 1.0; Y: 1.0; Z: 0.7; W: 1);
-  cBV135: TVector4f = (X: 1.0; Y: 0.8; Z: 0.7; W: 1);
-var
-  bvIndex100: Integer;
-begin
-  bvIndex100 := starRecord.BVColorIndex - 50;
-  // compute RGB color for B&V index
-  if bvIndex100 < -035 then
-    Result := cBVm035
-  else if bvIndex100 < 015 then
-    VectorLerp(cBVm035, cBV015, (bvIndex100 + 035) * (1 / (015 + 035)), Result)
-  else if bvIndex100 < 060 then
-    VectorLerp(cBV015, cBV060, (bvIndex100 - 015) * (1 / (060 - 015)), Result)
-  else if bvIndex100 < 135 then
-    VectorLerp(cBV060, cBV135, (bvIndex100 - 060) * (1 / (135 - 060)), Result)
-  else
-    Result := cBV135;
-  // compute transparency for VMag
-  // the actual factor is 2.512, and not used here
-  Result.W := PowerSingle(1.2, -(starRecord.VMagnitude * 0.1 - bias));
-end;
-
 // ------------------
 // ------------------ TGLSkyDomeBand ------------------
 // ------------------
@@ -699,6 +989,8 @@ begin
   inherited Destroy;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeBand.Assign(Source: TPersistent);
 begin
   if Source is TGLSkyDomeBand then
@@ -731,6 +1023,8 @@ begin
   FStartColor.Assign(val);
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeBand.SetStopAngle(const val: Single);
 begin
   FStopAngle := ClampValue(val, -90, 90);
@@ -767,6 +1061,8 @@ begin
   TGLSkyDomeBands(Collection).NotifyChange;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeBand.BuildList(var rci: TGLRenderContextInfo);
 // coordinates system note: X is forward, Y is left and Z is up
 // always rendered as sphere of radius 1
@@ -851,7 +1147,6 @@ end;
 // ------------------
 // ------------------ TGLSkyDomeBands ------------------
 // ------------------
-
 constructor TGLSkyDomeBands.Create(AOwner: TComponent);
 begin
   owner := AOwner;
@@ -863,6 +1158,8 @@ begin
   Result := owner;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeBands.SetItems(index: Integer; const val: TGLSkyDomeBand);
 begin
   inherited Items[index] := val;
@@ -900,7 +1197,6 @@ end;
 // ------------------
 // ------------------ TGLSkyDomeStar ------------------
 // ------------------
-
 constructor TGLSkyDomeStar.Create(Collection: TCollection);
 begin
   inherited Create(Collection);
@@ -924,6 +1220,8 @@ begin
   inherited Destroy;
 end;
 
+//----------------------------------------------------------------------
+
 function TGLSkyDomeStar.GetDisplayName: string;
 begin
   Result := Format('RA: %5.1f / Dec: %5.1f', [RA, DEC]);
@@ -932,7 +1230,6 @@ end;
 // ------------------
 // ------------------ TGLSkyDomeStars ------------------
 // ------------------
-
 constructor TGLSkyDomeStars.Create(AOwner: TComponent);
 begin
   owner := AOwner;
@@ -964,6 +1261,8 @@ begin
   Result := (inherited FindItemID(ID)) as TGLSkyDomeStar;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeStars.PrecomputeCartesianCoordinates;
 var
   i: Integer;
@@ -982,6 +1281,8 @@ begin
   end;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeStars.BuildList(var rci: TGLRenderContextInfo;
   twinkle: Boolean);
 var
@@ -991,7 +1292,7 @@ var
   lastPointSize10, pointSize10: Integer;
   Color, twinkleColor: TGLColorVector;
 
-  procedure DoTwinkle;
+  (*sub*)procedure DoTwinkle;
   begin
     if (n and 63) = 0 then
     begin
@@ -1061,9 +1362,10 @@ begin
   rci.GLStates.SetGLAlphaFunction(cfGreater, 0);
 end;
 
-//------------------------------------------------------------
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeStars.AddRandomStars(const nb: Integer; const Color: TColor;
-  const limitToTopDome: Boolean = False);
+  const LimitToTopDome: Boolean = False);
 var
   i: Integer;
   coord: TAffineVector;
@@ -1073,7 +1375,7 @@ begin
   begin
     star := Add;
     // pick a point in the half-cube
-    if limitToTopDome then
+    if LimitToTopDome then
       coord.Z := Random
     else
       coord.Z := Random * 2 - 1;
@@ -1087,11 +1389,12 @@ begin
   end;
 end;
 
-//------------------------------------------------------------
+//-----------------------------------------------------------------------
+
 procedure TGLSkyDomeStars.AddRandomStars(const nb: Integer;
   const ColorMin, ColorMax: TVector3b;
   const Magnitude_min, Magnitude_max: Single;
-  const limitToTopDome: Boolean = False);
+  const LimitToTopDome: Boolean = False);
 
   function RandomTT(Min, Max: Byte): Byte;
   begin
@@ -1108,7 +1411,7 @@ begin
   begin
     star := Add;
     // pick a point in the half-cube
-    if limitToTopDome then
+    if LimitToTopDome then
       coord.Z := Random
     else
       coord.Z := Random * 2 - 1;
@@ -1123,6 +1426,8 @@ begin
   end;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDomeStars.LoadStarsFile(const starsFileName: string);
 var
   fs: TFileStream;
@@ -1139,7 +1444,7 @@ begin
         RA := sr.RA * 0.01;
         DEC := sr.DEC * 0.01;
         colorVector := StarRecordColor(sr, 3);
-        Magnitude := sr.VMagnitude * 0.1;
+        Magnitude := sr.VMagnitude * 0.05; // default 0.1
         if sr.VMagnitude > 35 then
           Color := ConvertColorVector(colorVector, colorVector.W)
         else
@@ -1154,7 +1459,6 @@ end;
 // ------------------
 // ------------------ TGLSkyDome ------------------
 // ------------------
-
 constructor TGLSkyDome.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
@@ -1186,6 +1490,8 @@ begin
   inherited Destroy;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDome.Assign(Source: TPersistent);
 begin
   if Source is TGLSkyDome then
@@ -1196,6 +1502,8 @@ begin
   inherited;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLSkyDome.SetBands(const val: TGLSkyDomeBands);
 begin
   FBands.Assign(val);
@@ -1225,6 +1533,7 @@ begin
     StructureChanged;
   end;
 end;
+//----------------------------------------------------------------------
 
 procedure TGLSkyDome.BuildList(var rci: TGLRenderContextInfo);
 var
@@ -1252,7 +1561,6 @@ end;
 // ------------------
 // ------------------ TGLEarthSkyDome ------------------
 // ------------------
-
 constructor TGLEarthSkyDome.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
@@ -1275,6 +1583,8 @@ begin
   PreCalculate;
 end;
 
+//----------------------------------------------------------------------
+
 destructor TGLEarthSkyDome.Destroy;
 begin
   FSunZenithColor.Free;
@@ -1286,6 +1596,8 @@ begin
   inherited Destroy;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.Assign(Source: TPersistent);
 begin
   if Source is TGLSkyDome then
@@ -1310,6 +1622,8 @@ begin
   PreCalculate;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.SetSunElevation(const val: Single);
 var
   newVal: Single;
@@ -1382,6 +1696,8 @@ begin
   StructureChanged;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.BuildList(var rci: TGLRenderContextInfo);
 var
   f: Single;
@@ -1422,6 +1738,8 @@ begin
   PreCalculate;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.SetSunAtTime(HH, MM: Single);
 const
   cHourToElevation1: array [0 .. 23] of Single = (-45, -67.5, -90, -57.5, -45,
@@ -1496,6 +1814,8 @@ begin
   StructureChanged;
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.PreCalculate;
 var
   ts: Single;
@@ -1539,10 +1859,11 @@ begin
         Stars[i].RA := Stars[i].RA + 180;
     end;
   end;
-
   StructureChanged;
 end;
 
+//----------------------------------------------------------------------
+
 function TGLEarthSkyDome.CalculateColor(const theta, cosGamma: Single)
   : TGLColorVector;
 var
@@ -1557,6 +1878,8 @@ begin
     ClampValue(exp(FCurSunSkyTurbid * cosGamma * (1 + t)) * 1.1, 0, 1), Result);
 end;
 
+//----------------------------------------------------------------------
+
 procedure TGLEarthSkyDome.RenderDome;
 var
   ts: Single;
@@ -1564,15 +1887,12 @@ var
   sunPos: TAffineVector;
   sinTable, cosTable: PFloatArray;
 
-  // coordinates system note: X is forward, Y is left and Z is up
-  // always rendered as sphere of radius 1
-
-  function CalculateCosGamma(const p: TGLVector): Single;
+  (*sub*)function CalculateCosGamma(const p: TGLVector): Single;
   begin
     Result := 1 - VectorAngleCosine(PAffineVector(@p)^, sunPos);
   end;
 
-  procedure RenderDeepBand(stop: Single);
+  (*sub*)procedure RenderDeepBand(stop: Single);
   var
     i: Integer;
     r, thetaStart: Single;
@@ -1599,7 +1919,7 @@ var
     gl.End_;
   end;
 
-  procedure RenderBand(start, stop: Single);
+  (*sub*)procedure RenderBand(start, stop: Single);
   var
     i: Integer;
     r, r2, thetaStart, thetaStop: Single;
@@ -1700,6 +2020,7 @@ begin
   FreeMem(cosTable);
 end;
 
+
 // -------------------------------------------------------------
 initialization
 // -------------------------------------------------------------

+ 0 - 194
Source/GLS.SolarSystem.pas

@@ -1,194 +0,0 @@
-//
-// The graphics engine GLScene https://github.com/glscene
-//
-unit GLS.SolarSystem;
-
-(*
-  Solar system planetary elements and positions utility unit.
-  Based on document by Paul Schlyter (Stockholm, Sweden)
-  http://www.stjarnhimlen.se/comp/ppcomp.html
-  Coordinates system takes Z as "up", ie. normal to the ecliptic plane,
-  "axis" around which the planets turn.
-*)
-
-interface
-
-uses
-  System.SysUtils,
-  System.Math,
-  GLS.VectorGeometry;
-
-type
-
-  TOrbitalElements = record
-    N: Double; // longitude of the ascending node
-    i: Double; // inclination to the ecliptic (plane of the Earth's orbit)
-    w: Double; // argument of perihelion
-    a: Double; // semi-major axis, or mean distance from Sun
-    e: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
-    M: Double; // mean anomaly (0 at perihelion; increases uniformly with time)
-  end;
-
-  TOrbitalElementsData = record
-    NConst, NVar: Double; // longitude of the ascending node
-    iConst, iVar: Double;
-    // inclination to the ecliptic (plane of the Earth's orbit)
-    wConst, wVar: Double; // argument of perihelion
-    aConst, aVar: Double; // semi-major axis, or mean distance from Sun
-    eConst, eVar: Double; // eccentricity (0=circle, 0-1=ellipse, 1=parabola)
-    MConst, MVar: Double;
-    // mean anomaly (0 at perihelion; increases uniformly with time)
-  end;
-
-const
-  // geocentric sun elements 
-  cSunOrbitalElements: TOrbitalElementsData = (NConst: 0.0; NVar: 0.0;
-    iConst: 0.0; iVar: 0.0; wConst: 282.9404; wVar: 4.70935E-5;
-    aConst: 1.000000; aVar: 0.0; // (AU)
-    eConst: 0.016709; eVar: - 1.151E-9; MConst: 356.0470; MVar: 0.9856002585);
-
-  // geocentric moon elements
-  cMoonOrbitalElements: TOrbitalElementsData = (NConst: 125.1228;
-    NVar: - 0.0529538083; iConst: 5.1454; iVar: 0.0; wConst: 318.0634;
-    wVar: 0.1643573223; aConst: 60.2666; aVar: 0.0; // (Earth radii)
-    eConst: 0.054900; eVar: 0.0; MConst: 115.3654; MVar: 13.0649929509);
-
-  // heliocentric mercury elements
-  cMercuryOrbitalElements: TOrbitalElementsData = (NConst: 48.3313;
-    NVar: 3.24587E-5; iConst: 7.0047; iVar: 5.00E-8; wConst: 29.1241;
-    wVar: 1.01444E-5; aConst: 0.387098; aVar: 0.0; // (AU)
-    eConst: 0.205635; eVar: 5.59E-10; MConst: 168.6562; MVar: 4.0923344368);
-
-  // heliocentric venus elements
-  cVenusOrbitalElements: TOrbitalElementsData = (NConst: 76.6799;
-    NVar: 2.46590E-5; iConst: 3.3946; iVar: 2.75E-8; wConst: 54.8910;
-    wVar: 1.38374E-5; aConst: 0.723330; aVar: 0.0; // (AU)
-    eConst: 0.006773; eVar: - 1.302E-9; MConst: 48.0052; MVar: 1.6021302244);
-
-  // heliocentric mars elements
-  cMarsOrbitalElements: TOrbitalElementsData = (NConst: 49.5574;
-    NVar: 2.11081E-5; iConst: 1.8497; iVar: - 1.78E-8; wConst: 286.5016;
-    wVar: 2.92961E-5; aConst: 1.523688; aVar: 0.0; // (AU)
-    eConst: 0.093405; eVar: 2.516E-9; MConst: 18.6021; MVar: 0.5240207766);
-
-  // heliocentric jupiter elements
-  cJupiterOrbitalElements: TOrbitalElementsData = (NConst: 100.4542;
-    NVar: 2.76854E-5; iConst: 1.3030; iVar: - 1.557E-7; wConst: 273.8777;
-    wVar: 1.64505E-5; aConst: 5.20256; aVar: 0.0; // (AU)
-    eConst: 0.048498; eVar: 4.469E-9; MConst: 19.8950; MVar: 0.0830853001);
-
-  // heliocentric saturn elements
-  cSaturnOrbitalElements: TOrbitalElementsData = (NConst: 113.6634;
-    NVar: 2.38980E-5; iConst: 2.4886; iVar: - 1.081E-7; wConst: 339.3939;
-    wVar: 2.97661E-5; aConst: 9.55475; aVar: 0.0; // (AU)
-    eConst: 0.055546; eVar: - 9.499E-9; MConst: 316.9670; MVar: 0.0334442282);
-
-  // heliocentric uranus elements
-  cUranusOrbitalElements: TOrbitalElementsData = (NConst: 74.0005;
-    NVar: 1.3978E-5; iConst: 0.7733; iVar: 1.9E-8; wConst: 96.6612;
-    wVar: 3.0565E-5; aConst: 19.18171; aVar: - 1.55E-8; // (AU)
-    eConst: 0.047318; eVar: 7.45E-9; MConst: 142.5905; MVar: 0.011725806);
-
-  // heliocentric neptune elements
-  cNeptuneOrbitalElements: TOrbitalElementsData = (NConst: 131.7806;
-    NVar: 3.0173E-5; iConst: 1.7700; iVar: - 2.55E-7; wConst: 272.8461;
-    wVar: - 6.027E-6; aConst: 30.05826; aVar: 3.313E-8; // (AU)
-    eConst: 0.008606; eVar: 2.15E-9; MConst: 260.2471; MVar: 0.005995147);
-
-  cAUToKilometers = 149.6E6; // astronomical units to kilometers
-  cEarthRadius = 6371; // average earth radius in kilometers
-
-// Converts a TDateTime (GMT+0) into the Julian day used for computations.
-function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
-// Compute orbital elements for given Julian day.
-function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
-  const d: Double): TOrbitalElements;
-
-// Compute the planet position for given Julian day (in AU).
-function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
-  : TAffineVector; overload;
-function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
-  const d: Double): TAffineVector; overload;
-
-// ------------------------------------------------------------------------------
-implementation
-// ------------------------------------------------------------------------------
-
-function GMTDateTimeToJulianDay(const dt: TDateTime): Double;
-begin
-  Result := dt - EncodeDate(2000, 1, 1);
-end;
-
-//--------------------------------------------------------------------------------
-
-function ComputeOrbitalElements(const oeData: TOrbitalElementsData;
-  const d: Double): TOrbitalElements;
-begin
-  with Result, oeData do
-  begin
-    N := NConst + NVar * d;
-    i := iConst + iVar * d;
-    w := wConst + wVar * d;
-    a := aConst + aVar * d;
-    e := eConst + eVar * d;
-    M := MConst + MVar * d;
-  end;
-end;
-
-//--------------------------------------------------------------------------------
-
-function ComputePlanetPosition(const orbitalElements: TOrbitalElements)
-  : TAffineVector;
-var
-  eccentricAnomaly, eA0: Double;
-  sm, cm, se, ce, si, ci, cn, sn, cvw, svw: Double;
-  xv, yv, v, r: Double;
-  nn: Integer; // numerical instability bailout
-begin
-  with orbitalElements do
-  begin
-    // E = M + e*(180/pi) * sin(M) * ( 1.0 + e * cos(M) )
-    SinCos(M * cPIdiv180, sm, cm);
-    eccentricAnomaly := M + e * c180divPI * sm * (1.0 + e * cm);
-
-    nn := 0;
-    repeat
-      eA0 := eccentricAnomaly;
-      // E1 = E0 - ( E0 - e*(180/pi) * sin(E0) - M ) / ( 1 - e * cos(E0) )
-      SinCos(eA0 * cPIdiv180, se, ce);
-      eccentricAnomaly := eA0 - (eA0 - e * c180divPI * se - M) / (1 - e * ce);
-      Inc(nn);
-    until (nn > 10) or (Abs(eccentricAnomaly - eA0) < 1E-4);
-
-    SinCos(eccentricAnomaly * cPIdiv180, se, ce);
-    xv := a * (ce - e);
-    yv := a * (Sqrt(1.0 - e * e) * se);
-
-    v := ArcTan2(yv, xv) * c180divPI;
-    r := Sqrt(xv * xv + yv * yv);
-
-    SinCos(i * cPIdiv180, si, ci);
-    SinCos(N * cPIdiv180, sn, cn);
-    SinCos((v + w) * cPIdiv180, svw, cvw);
-  end;
-
-  // xh = r * ( cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i) )
-  Result.X := r * (cn * cvw - sn * svw * ci);
-  // yh = r * ( sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i) )
-  Result.Y := r * (sn * cvw + cn * svw * ci);
-  // zh = r * ( sin(v+w) * sin(i) )
-  Result.Z := r * (svw * si);
-end;
-
-//--------------------------------------------------------------------------------
-
-function ComputePlanetPosition(const orbitalElementsData: TOrbitalElementsData;
-  const d: Double): TAffineVector;
-var
-  oe: TOrbitalElements;
-begin
-  oe := ComputeOrbitalElements(orbitalElementsData, d);
-  Result := ComputePlanetPosition(oe);
-end;
-
-end.