//---------------------------------------------------------------------------

#include <vcl.h>
#include <Keyboard.hpp>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "OpenGL1x"
#pragma link "GLTexCombineShader"
#pragma link "GLBumpmapHDS"
#pragma link "GLLensFlare"
#pragma link "VectorGeometry"
#pragma link "GLWin32Viewer"
#pragma link "GLSkydome"
#pragma link "GLTexture"
#pragma link "GLCadencer"
#pragma link "GLHeightData"
#pragma link "jpeg"
#pragma link "GLMisc"
#pragma link "GLObjects"
#pragma link "GLTerrainRenderer"
#pragma link "GLScene"
#pragma link "Keyboard"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent * Owner):TForm(Owner)
{
  SetCurrentDir(ExtractFilePath(Application->ExeName) + "..\\..\\media");
  // 8 MB height data cache
  // Note this is the data size in terms of elevation samples, it does not
  // take into account all the data required/allocated by the renderer
  GLBitmapHDS1->MaxPoolSize = 8 * 1024 * 1024;

  // specify height map data
  GLBitmapHDS1->Picture->LoadFromFile("terrain.bmp");

  // load the texture maps
  GLMaterialLibrary1->LibMaterialByName("details")->Material->Texture->Image->
    LoadFromFile("detailmap.jpg");
  SPSun->Material->Texture->Image->LoadFromFile("flare1.bmp");

  // apply texture map scale (our heightmap size is 256)
  TerrainRenderer1->TilesPerTexture = 1;        //256/TerrainRenderer1.TileSize;
  TerrainRenderer1->MaterialLibrary = GLMaterialLibrary1;

  // Could've been done at design time, but then it hurts the eyes ;)
  GLSceneViewer1->Buffer->BackgroundColor = clWhite;
  // Initial camera height offset (controled with pageUp/pageDown)
  FCamHeight = 10;

  // initialize intensity texture
  TBIntensityChange(this);
}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormShow(TObject * Sender)
{
  TBSubSamplingChange(this);
}

//---------------------------------------------------------------------------

void __fastcall TForm1::GLBumpmapHDS1NewTilePrepared(TGLBumpmapHDS * Sender,
                                                     THeightData * heightData,
                                                     TGLLibMaterial *
                                                     normalMapMaterial)
{
  TVector n;

  heightData->MaterialName = normalMapMaterial->Name;
  normalMapMaterial->Texture2Name = "contrast";
  normalMapMaterial->Shader = GLTexCombineShader1;
  normalMapMaterial->Material->MaterialOptions =
    normalMapMaterial->Material->MaterialOptions << moNoLighting;
  n = VectorNormalize(SPSun->AbsolutePosition);
  ScaleVector(n, 0.5);
  n.Coord[1] = -n.Coord[1];
  n.Coord[2] = -n.Coord[2];
  AddVector(n, 0.5);
  normalMapMaterial->Material->FrontProperties->Diffuse->Color = n;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::GLCadencer1Progress(TObject * Sender,
                                            const double deltaTime,
                                            const double newTime)
{
  float speed;

  // handle keypresses
  if(IsKeyDown(VK_SHIFT))
    speed = 5 * deltaTime;
  else
    speed = deltaTime;

  TGLCoordinates *p = GLCamera1->Position;
  if(IsKeyDown(VK_UP))
    DummyCube1->Translate(-p->X * speed, 0, -p->Z * speed);
  if(IsKeyDown(VK_DOWN))
    DummyCube1->Translate(p->X * speed, 0, p->Z * speed);
  if(IsKeyDown(VK_LEFT))
    DummyCube1->Translate(-p->Z * speed, 0, p->X * speed);
  if(IsKeyDown(VK_RIGHT))
    DummyCube1->Translate(p->Z * speed, 0, -p->X * speed);
  if(IsKeyDown(VK_PRIOR))
    FCamHeight = FCamHeight + 10 * speed;
  if(IsKeyDown(VK_NEXT))
    FCamHeight = FCamHeight - 10 * speed;
  if(IsKeyDown(VK_ESCAPE))
    Close();

  // don't drop through terrain!
  DummyCube1->Position->Y =
    TerrainRenderer1->InterpolatedHeight(DummyCube1->Position->AsVector) +
    FCamHeight;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::GLSceneViewer1MouseDown(TObject * Sender,
                                                TMouseButton Button,
                                                TShiftState Shift, int X, int Y)
{
  GLSceneViewer1->SetFocus();
  mx = X;
  my = Y;
}

//---------------------------------------------------------------------------

void __fastcall TForm1::GLSceneViewer1MouseMove(TObject * Sender,
                                                TShiftState Shift, int X, int Y)
{
  if(Shift.Contains(ssLeft))
  {
    GLCamera1->MoveAroundTarget((my - Y) * 0.5, (mx - X) * 0.5);
    my = Y;
    mx = X;
  }
}

//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject * Sender)
{
  Caption = GLSceneViewer1->FramesPerSecondText(1);
  GLSceneViewer1->ResetPerformanceMonitor();
}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormKeyPress(TObject * Sender, char &Key)
{
  TGLFaceProperties *fp;
  TGLFogEnvironment *fe;
  switch (Key)
  {
  case 'w':
  case 'W':
    fp = GLMaterialLibrary1->Materials->Items[0]->Material->FrontProperties;
    if(fp->PolygonMode == pmLines)
      fp->PolygonMode = pmFill;
    else
      fp->PolygonMode = pmLines;
    break;
  case '+':
    if(GLCamera1->DepthOfView < 2000.0)
    {
      GLCamera1->DepthOfView = GLCamera1->DepthOfView * 1.2;
      fe = GLSceneViewer1->Buffer->FogEnvironment;
      fe->FogEnd = fe->FogEnd * 1.2;
      fe->FogStart = fe->FogStart * 1.2;
    }
    break;
  case '-':
    if(GLCamera1->DepthOfView > 300)
    {
      GLCamera1->DepthOfView = GLCamera1->DepthOfView / 1.2;
      fe = GLSceneViewer1->Buffer->FogEnvironment;
      fe->FogEnd = fe->FogEnd / 1.2;
      fe->FogStart = fe->FogStart / 1.2;
    }
    break;
  case '*':
    if(TerrainRenderer1->CLODPrecision > 10)
      TerrainRenderer1->CLODPrecision =
        Round(TerrainRenderer1->CLODPrecision * 0.8);
    break;
  case '/':
    if(TerrainRenderer1->CLODPrecision < 1000)
      TerrainRenderer1->CLODPrecision =
        Round(TerrainRenderer1->CLODPrecision * 1.2);
    break;
  case 'l':
    GLLensFlare->Visible = (!GLLensFlare->Visible) && SPSun->Visible;
    break;
  }
  Key = '\0';
}

//---------------------------------------------------------------------------

void __fastcall TForm1::GLSceneViewer1BeforeRender(TObject * Sender)
{
  GLLensFlare->PreRender((TGLSceneBuffer *) Sender);
}

//---------------------------------------------------------------------------

void __fastcall TForm1::TBSubSamplingChange(TObject * Sender)
{
  GLBumpmapHDS1->SubSampling = (1 << TBSubSampling->Position);
  String s;
  s.printf("(%d) -> BumpMaps are %dx",
           GLBumpmapHDS1->SubSampling,
           TerrainRenderer1->TileSize / GLBumpmapHDS1->SubSampling);
  LASubFactor->Caption = s;
  // don't leave the focus to the trackbar, otherwise it'll keep some keystrokes
  // for itself, like the arrow keys
  SetFocus();
}

//---------------------------------------------------------------------------

void __fastcall TForm1::TBIntensityChange(TObject * Sender)
{
  int i;
  Graphics::TBitmap * bmp;

  TGLMaterial *m = GLMaterialLibrary1->LibMaterialByName("contrast")->Material;
  bmp = new Graphics::TBitmap;
  try
  {
    bmp->PixelFormat = pf24bit;
    bmp->Width = 1;
    bmp->Height = 1;
    i = 255;
    bmp->Canvas->Pixels[0][0] = (Graphics::TColor) RGB(i, i, i);
    m->Texture->Image->Assign(bmp);
  }
  __finally
  {
    delete bmp;
  }
  i = (TBIntensity->Position * 255) / 100;
  m->Texture->EnvColor->AsWinColor = (Graphics::TColor) RGB(i, i, i);

  LABumpIntensity->Caption = IntToStr(TBIntensity->Position) + " %";
}

//---------------------------------------------------------------------------
 
