unit U_OpenGL_Planets;

// Composite modeling transformations - converted from planet.c but added a moon
// to the planet.

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, CgWindow, CgTypes, CgLight, GL, GLu, Glut, StdCtrls, NumEdit,
  Spin;

type
TPForm = class(TForm)
    Timer1: TTimer;
    GroupBox1: TGroupBox;
    Xedit: TSpinEdit;
    Label1: TLabel;
    YEdit: TSpinEdit;
    ZEdit: TSpinEdit;
    Label2: TLabel;
    Label3: TLabel;
    HoursInc: TSpinEdit;
    Label4: TLabel;
    Panel1: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure setview;
end;

const
hours: GLFLoat = 0;
  days: GLfloat = 0;
  years: GLFLoat =0;

var
PForm: TPForm;
  L: TCGLight;
  CgDC1: TCGDeviceContext;

implementation

{$R *.DFM}
const

lpos: TCGVector = (x: 0; y: 0; z: 0; w: 1);
  lcol: TCGColorF = (R: 1; G: 0.75; B: 1; A: 1);

procedure TPForm.FormCreate(Sender: TObject);

var
pDC:HDC;
begin
{This gets a device context for the panel}
pDC := GetDC(Panel1.Handle);
  CgDC1 := TCGDeviceContext.Create(pDC);
  CgDC1.InitGL;  {and initializes OpenGL on the panel}

glEnable(GL_DEPTH_TEST);
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_NORMALIZE);

  L := TCGLight.Create(GL_LIGHT0);
  L.Position := lpos;
  L.Diffuse := lcol;
  L.Enable;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
with panel1 do
gluPerspective(60.0,Width/Height, 1.0, 20.0);
  gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  glMatrixMode(GL_MODELVIEW);
end;



procedure TPForm.setview;
begin
glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
with panel1 do
gluPerspective(60.0, ClientWidth/ClientHeight, 1.0, 20.0);

  gluLookAt(0, 0, zedit.value, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  glrotatef(xedit.value,0,1,0);
  glrotatef(yedit.value,1,0,0);
  glMatrixMode(GL_MODELVIEW);
end;

procedure TPForm.FormPaint(Sender: TObject);
const
sColor: array [0..3] of GLfloat = (1, 0.85, 0, 1);
  pColor: array [0..3] of GLfloat = (0.0, 0.0, 0.8, 1);
  mColor: array [0..3] of GLfloat = (0.5, 0.5, 0.6, 1);
  spec: array [0..3] of GLfloat = (0.5, 0.5, 0.5, 0.5);
  black: array [0..3] of GLfloat = (0, 0, 0, 1);
  brown: array [0..3] of GLfloat = (0.4, 0.4, 0.2, 1);
var
deltamoon:GLFloat;
begin
cgDC1.MakeCurrent;
  Setview;
  glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;
// Making the objects shiny looks bogus, but at least you can tell they're rotating.
glMaterialf(GL_FRONT, GL_SHININESS, 100);
  glMaterialfv(GL_FRONT, GL_SPECULAR, @spec[0]);

  glPushMatrix;                     // "Remember where we are"

glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, @sColor);
  glutSolidSphere(0.4, 32, 16);     // Draw the sun
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, @brown {black});

  glRotatef(360*years , 0.0, 1.0, 0.0);   // Rotate the planet around the sun.
glTranslatef(2.4, 0.0, 0.0);      // Translate it to a point on its orbit.
// We now need to remember the planet's position before we rotate it around
// it's own axis. If we PushMatrix later, the moon's orbit will also rotate
// around the planet's axis!
glPushMatrix;
// Remember the planet's position.
glRotatef(23, 0.0, 0.0, 1.0);    // Tilt the planet's axis 20 degrees.
glRotatef( (15*hours), 0.0, 1.0, 0.0);    // Rotate it around its own axis.
// Note how the transformations seem to take place in reverse order!

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @pColor);
  glutSolidSphere(0.2, 16{32}, 8{16});     // Draw the planet.

glPopMatrix;                      // Return to planet position.
glRotatef(10, 0.0, 0.0, 1.0);     // Tilt the moon's orbit
deltamoon:=360*12*years;
  glRotatef(deltamoon, 0.0, 1.0, 0.0); // Rotate the moon around the planet - 12 degrees per day.
glTranslatef(0.35, 0.0, 0.0);      // Translate it to a point on its orbit.
glRotatef(-deltamoon, 0.0, 1.0, 0.0);    // Rotate it back around its own axis.

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mColor);
  glutSolidSphere(0.08, 16{32}, 8{16});      // Draw the moon.

glPopMatrix;                      // Restore the original matrix.

cgDC1.PageFlip;

end;

procedure TPForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CgDC1.Free;
  L.Free;

end;

const
daysperyear=364.25;

procedure TPForm.Timer1Timer(Sender: TObject);
begin
{here are most of my changes original was 1 degre per step}
hours:=(hours+hoursinc.value);
if hours>=24*daysperyear then hours:=hours-24*daysperyear;
  days:=hours / 24;
  years:=days/daysperyear;

  Paint;

end;

end.