//--------------------------------------------------------------------------- #include #pragma hdrstop #include "fSynthTerrainC.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "GLS.BaseClasses" #pragma link "GLS.Cadencer" #pragma link "GLS.Coordinates" #pragma link "GLS.HeightData" #pragma link "GLS.Material" #pragma link "GLS.Objects" #pragma link "GLS.Scene" #pragma link "GLS.TerrainRenderer" #pragma link "GLS.SceneViewer" #pragma link "GLS.HeightData" #pragma link "GLS.HeightData" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { int i; TBitmap *bmp; // 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 GLCustomHDS->MaxPoolSize = 8*1024*1024; // Move camera starting point to an interesting hand-picked location DummyCube1->Position->X = 50; DummyCube1->Position->Z = 150; // Initial camera height offset (controled with pageUp/pageDown) FCamHeight = 20; // We build several basic 1D textures which are just color ramps // all use automatic texture mapping corodinates, in ObjectLinear method // (ie. texture coordinates for a vertex depend on that vertex coordinates) bmp = new TBitmap; bmp->PixelFormat = pf24bit; bmp->Width = 256; bmp->Height = 1; // Black-White ramp, autotexture maps to Z coordinate // This one changes with altitude, this is a quick way to obtain // altitude-dependant coloring for (i=0; i < 255; i++) bmp->Canvas->Pixels[i][0] = RGB(i, i, i); GLMaterialLibrary1->AddTextureMaterial("BW", bmp)->Material->Texture->MappingMode = tmmObjectLinear; GLMaterialLibrary1->AddTextureMaterial("BW", bmp)->Material->Texture->MappingSCoordinates->AsVector = VectorMake(0, 0, 0.0001, 0); // Red, Blue map linearly to X and Y axis respectively for (i=0; i < 255; i++) bmp->Canvas->Pixels[i][0] = RGB(i, 0, 0); GLMaterialLibrary1->AddTextureMaterial("Red", bmp)->Material->Texture->MappingMode = tmmObjectLinear; GLMaterialLibrary1->AddTextureMaterial("Red", bmp)->Material->Texture->MappingSCoordinates->AsVector = VectorMake(0.1, 0, 0, 0); for (i=0; i < 255; i++) bmp->Canvas->Pixels[i][0] = RGB(0, 0, i); GLMaterialLibrary1->AddTextureMaterial("Blue", bmp)->Material->Texture->MappingMode = tmmObjectLinear; GLMaterialLibrary1->AddTextureMaterial("Blue", bmp)->Material->Texture->MappingSCoordinates->AsVector = VectorMake(0, 0.1, 0, 0); bmp->Free(); TerrainRenderer1->MaterialLibrary = GLMaterialLibrary1; } //--------------------------------------------------------------------------- // // The beef : this event does all the interesting elevation data stuff // void __fastcall TForm1::GLCustomHDSStartPreparingData(TGLHeightData *HeightData) { int x, y; TByteRaster rasterLine; TGLHeightDataType oldType; TByteVector * b; float d, dy; HeightData->DataState = hdsPreparing; // retrieve data oldType = HeightData->DataType; HeightData->Allocate(hdtByte); // Cheap texture changed (32 is our tileSize = 2^5) // This basicly picks a texture for each tile depending on the tile's position switch ((((HeightData->XLeft ^ HeightData->YTop) << 5) && 3)) { case 0, 3 : HeightData->MaterialName = "BW"; break; case 1 : HeightData->MaterialName = "Blue"; break; case 2 : HeightData->MaterialName = "Red"; break; default: ; } // 'Cheap' elevation data : this is just a formula z=f(x, y) for (y=HeightData->YTop; y < HeightData->YTop+HeightData->Size-1; y++) { rasterLine = HeightData->ByteRaster[y-HeightData->YTop]; dy = y*y; for (x = HeightData->XLeft; x < HeightData->XLeft+HeightData->Size-1; x++) { d = sqrt(x*x+dy); b->data[0,0,0] = (float) RoundInt(128+128*Sin(d*0.2)/(d*0.1+1)); rasterLine[x-HeightData->XLeft] = b; } } if (oldType != hdtByte) HeightData->DataType = oldType; ///inherited; } //--------------------------------------------------------------------------- // Movement, mouse handling etc. void __fastcall TForm1::GLSceneViewer1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { mx = X; my = Y; } //--------------------------------------------------------------------------- void __fastcall TForm1::GLSceneViewer1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if (Shift.Contains(ssLeft)) { GLCamera1->MoveAroundTarget(my-Y, mx-X); mx = X; my = Y; } } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { Caption = "Synthetic Terrain " + Format("%.1f FPS - %d", ARRAYOFCONST ((GLSceneViewer1->FramesPerSecond(), TerrainRenderer1->LastTriangleCount))); GLSceneViewer1->ResetPerformanceMonitor(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormKeyPress(TObject *Sender, System::WideChar &Key) { switch (Key) { case '+' : if (GLCamera1->DepthOfView < 4000) { GLCamera1->DepthOfView = GLCamera1->DepthOfView*1.2; GLSceneViewer1->Buffer->FogEnvironment->FogEnd = GLSceneViewer1->Buffer->FogEnvironment->FogEnd*1.2; GLSceneViewer1->Buffer->FogEnvironment->FogStart = GLSceneViewer1->Buffer->FogEnvironment->FogStart*1.2; } break; case '-' : if (GLCamera1->DepthOfView > 300) { GLCamera1->DepthOfView = GLCamera1->DepthOfView/1.2; GLSceneViewer1->Buffer->FogEnvironment->FogEnd = GLSceneViewer1->Buffer->FogEnvironment->FogEnd/1.2; GLSceneViewer1->Buffer->FogEnvironment->FogStart = GLSceneViewer1->Buffer->FogEnvironment->FogStart/1.2; } break; case '*' : if (TerrainRenderer1->CLODPrecision > 5) TerrainRenderer1->CLODPrecision = RoundInt(TerrainRenderer1->CLODPrecision*0.8); break; case '/' : if (TerrainRenderer1->CLODPrecision<500) TerrainRenderer1->CLODPrecision = RoundInt(TerrainRenderer1->CLODPrecision*1.2); break; case '8' : if (TerrainRenderer1->QualityDistance>40) TerrainRenderer1->QualityDistance = RoundInt(TerrainRenderer1->QualityDistance*0.8); break; case '9' : if (TerrainRenderer1->QualityDistance<1000) TerrainRenderer1->QualityDistance = RoundInt(TerrainRenderer1->QualityDistance*1.2); break; default: ; } Key = 0x0; } //--------------------------------------------------------------------------- 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; if (IsKeyDown(VK_RIGHT)) DummyCube1->Translate(GLCamera1->Position->Z*speed, 0, -GLCamera1->Position->X*speed); if (IsKeyDown(VK_LEFT)) DummyCube1->Translate(-GLCamera1->Position->Z*speed, 0, GLCamera1->Position->X*speed); if (IsKeyDown(VK_UP)) DummyCube1->Translate(-GLCamera1->Position->X*speed, 0, -GLCamera1->Position->Z*speed); if (IsKeyDown(VK_DOWN)) DummyCube1->Translate(GLCamera1->Position->X*speed, 0, GLCamera1->Position->Z*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; } //---------------------------------------------------------------------------