fTerrain.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. unit fTerrain;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. Winapi.Windows,
  6. System.SysUtils,
  7. System.Classes,
  8. System.Math,
  9. Vcl.ExtCtrls,
  10. Vcl.StdCtrls,
  11. Vcl.Graphics,
  12. Vcl.Controls,
  13. Vcl.Forms,
  14. Vcl.Dialogs,
  15. Vcl.Imaging.GIFImg,
  16. Vcl.Imaging.Jpeg,
  17. GLS.Scene,
  18. GLS.VectorTypes,
  19. GLS.Objects,
  20. GLS.TerrainRenderer,
  21. GLS.HeightData,
  22. GLS.Color,
  23. GLS.Cadencer,
  24. GLS.Texture,
  25. GLS.BitmapFont,
  26. GLS.Keyboard,
  27. GLS.SkyDome,
  28. GLS.SceneViewer,
  29. GLS.Sound,
  30. Sounds.BASS,
  31. GLS.VectorGeometry,
  32. GLS.LensFlare,
  33. GLS.Material,
  34. GLS.Coordinates,
  35. GLS.BaseClasses,
  36. GLS.State,
  37. GLS.FileMP3,
  38. GLS.Utils,
  39. GLS.HUDObjects;
  40. type
  41. TFormTerrain = class(TForm)
  42. GLSceneViewer1: TGLSceneViewer;
  43. GLBitmapHDS1: TGLBitmapHDS;
  44. GLScene1: TGLScene;
  45. GLCamera1: TGLCamera;
  46. DummyCube1: TGLDummyCube;
  47. TerrainRenderer1: TGLTerrainRenderer;
  48. Timer1: TTimer;
  49. GLCadencer1: TGLCadencer;
  50. GLMaterialLibrary1: TGLMaterialLibrary;
  51. BitmapFont1: TGLBitmapFont;
  52. HUDText1: TGLHUDText;
  53. SkyDome1: TGLSkyDome;
  54. SPMoon: TGLSprite;
  55. SPSun: TGLSprite;
  56. DCSound: TGLDummyCube;
  57. GLSMBASS1: TGLSMBASS;
  58. TISound: TTimer;
  59. GLSoundLibrary: TGLSoundLibrary;
  60. GLLensFlare: TGLLensFlare;
  61. GLDummyCube1: TGLDummyCube;
  62. InitialRenderPoint: TGLRenderPoint;
  63. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  64. Shift: TShiftState; X, Y: Integer);
  65. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  66. X, Y: Integer);
  67. procedure Timer1Timer(Sender: TObject);
  68. procedure GLCadencer1Progress(Sender: TObject;
  69. const deltaTime, newTime: Double);
  70. procedure FormCreate(Sender: TObject);
  71. procedure FormKeyPress(Sender: TObject; var Key: Char);
  72. procedure TISoundTimer(Sender: TObject);
  73. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  74. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  75. public
  76. mx, my: Integer;
  77. fullScreen: Boolean;
  78. FCamHeight: Single;
  79. end;
  80. var
  81. FormTerrain: TFormTerrain;
  82. implementation
  83. {$R *.DFM}
  84. procedure TFormTerrain.FormCreate(Sender: TObject);
  85. begin
  86. SetGLSceneMediaDir();
  87. // 8 MB height data cache
  88. // Note this is the data size in terms of elevation samples, it does not
  89. // take into account all the data required/allocated by the renderer
  90. GLBitmapHDS1.MaxPoolSize := 8 * 1024 * 1024;
  91. // specify height map data
  92. GLBitmapHDS1.Picture.LoadFromFile('terrain.bmp');
  93. // load the texture maps
  94. GLMaterialLibrary1.Materials[0].Material.Texture.Image.LoadFromFile('snow512.jpg');
  95. GLMaterialLibrary1.Materials[1].Material.Texture.Image.LoadFromFile('detailmap.jpg');
  96. SPMoon.Material.Texture.Image.LoadFromFile('moon.bmp');
  97. SPSun.Material.Texture.Image.LoadFromFile('flare1.bmp');
  98. // apply texture map scale (our heightmap size is 256)
  99. TerrainRenderer1.TilesPerTexture := 256 / TerrainRenderer1.TileSize;
  100. // load Bitmap Font
  101. BitmapFont1.Glyphs.LoadFromFile('darkgold_font.bmp');
  102. // load and setup sound samples
  103. with GLSoundLibrary.Samples do
  104. begin
  105. Add.LoadFromFile('ChillyWind.mp3');
  106. Add.LoadFromFile('howl.mp3');
  107. end;
  108. // Could've been done at design time, but then it hurts the eyes ;)
  109. GLSceneViewer1.Buffer.BackgroundColor := clWhite;
  110. // Move camera starting point to an interesting hand-picked location
  111. DummyCube1.Position.X := 570;
  112. DummyCube1.Position.Z := -385;
  113. DummyCube1.Turn(90);
  114. // Initial camera height offset (controled with pageUp/pageDown)
  115. FCamHeight := 10;
  116. end;
  117. procedure TFormTerrain.GLCadencer1Progress(Sender: TObject;
  118. const deltaTime, newTime: Double);
  119. var
  120. speed: Single;
  121. begin
  122. // handle keypresses
  123. if IsKeyDown(VK_SHIFT) then
  124. speed := 5 * deltaTime
  125. else
  126. speed := deltaTime;
  127. with GLCamera1.Position do
  128. begin
  129. if IsKeyDown(VK_UP) then
  130. DummyCube1.Translate(Z * speed, 0, -X * speed);
  131. if IsKeyDown(VK_DOWN) then
  132. DummyCube1.Translate(-Z * speed, 0, X * speed);
  133. if IsKeyDown(VK_LEFT) then
  134. DummyCube1.Translate(-X * speed, 0, -Z * speed);
  135. if IsKeyDown(VK_RIGHT) then
  136. DummyCube1.Translate(X * speed, 0, Z * speed);
  137. if IsKeyDown(VK_PRIOR) then
  138. FCamHeight := FCamHeight + 10 * speed;
  139. if IsKeyDown(VK_NEXT) then
  140. FCamHeight := FCamHeight - 10 * speed;
  141. if IsKeyDown(VK_ESCAPE) then
  142. Close;
  143. end;
  144. // don't drop through terrain!
  145. with DummyCube1.Position do
  146. Y := TerrainRenderer1.InterpolatedHeight(AsVector) + FCamHeight;
  147. end;
  148. // Standard mouse rotation & FPS code below
  149. procedure TFormTerrain.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  150. Shift: TShiftState; X, Y: Integer);
  151. begin
  152. mx := X;
  153. my := Y;
  154. end;
  155. procedure TFormTerrain.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  156. X, Y: Integer);
  157. begin
  158. if ssLeft in Shift then
  159. begin
  160. GLCamera1.MoveAroundTarget((my - Y) * 0.5, (mx - X) * 0.5);
  161. mx := X;
  162. my := Y;
  163. end;
  164. end;
  165. procedure TFormTerrain.Timer1Timer(Sender: TObject);
  166. begin
  167. HUDText1.Text := Format('%.1f FPS - %d', [GLSceneViewer1.FramesPerSecond,
  168. TerrainRenderer1.LastTriangleCount]);
  169. GLSceneViewer1.ResetPerformanceMonitor;
  170. end;
  171. procedure TFormTerrain.FormKeyPress(Sender: TObject; var Key: Char);
  172. var
  173. Color: TGIFColor;
  174. begin
  175. case Key of
  176. 'w', 'W':
  177. with GLMaterialLibrary1.Materials[0].Material do
  178. begin
  179. if PolygonMode = pmLines then
  180. PolygonMode := pmFill
  181. else
  182. PolygonMode := pmLines;
  183. end;
  184. '+':
  185. if GLCamera1.DepthOfView < 2000 then
  186. begin
  187. GLCamera1.DepthOfView := GLCamera1.DepthOfView * 1.2;
  188. with GLSceneViewer1.Buffer.FogEnvironment do
  189. begin
  190. FogEnd := FogEnd * 1.2;
  191. FogStart := FogStart * 1.2;
  192. end;
  193. end;
  194. '-':
  195. if GLCamera1.DepthOfView > 300 then
  196. begin
  197. GLCamera1.DepthOfView := GLCamera1.DepthOfView / 1.2;
  198. with GLSceneViewer1.Buffer.FogEnvironment do
  199. begin
  200. FogEnd := FogEnd / 1.2;
  201. FogStart := FogStart / 1.2;
  202. end;
  203. end;
  204. '*':
  205. with TerrainRenderer1 do
  206. if CLODPrecision > 20 then
  207. CLODPrecision := Round(CLODPrecision * 0.8);
  208. '/':
  209. with TerrainRenderer1 do
  210. if CLODPrecision < 1000 then
  211. CLODPrecision := Round(CLODPrecision * 1.2);
  212. '8':
  213. with TerrainRenderer1 do
  214. if QualityDistance > 40 then
  215. QualityDistance := Round(QualityDistance * 0.8);
  216. '9':
  217. with TerrainRenderer1 do
  218. if QualityDistance < 1000 then
  219. QualityDistance := Round(QualityDistance * 1.2);
  220. 'n', 'N':
  221. with SkyDome1 do
  222. if Stars.Count = 0 then
  223. begin
  224. // turn on 'night' mode
  225. Color.Red := 0;
  226. Color.Green := 0;
  227. Color.Blue := 8;
  228. Bands[0].StopColor.AsWinColor := TGIFColorMap.RGB2Color(Color);
  229. Color.Red := 0;
  230. Color.Green := 0;
  231. Color.Blue := 0;
  232. Bands[0].StartColor.AsWinColor := TGIFColorMap.RGB2Color(Color);
  233. Color.Red := 0;
  234. Color.Green := 0;
  235. Color.Blue := 16;
  236. Bands[1].StopColor.AsWinColor := TGIFColorMap.RGB2Color(Color);
  237. Color.Red := 0;
  238. Color.Green := 0;
  239. Color.Blue := 8;
  240. Bands[1].StartColor.AsWinColor := TGIFColorMap.RGB2Color(Color);
  241. with Stars do
  242. begin
  243. AddRandomStars(700, clWhite, True); // many white stars
  244. Color.Red := 255;
  245. Color.Green := 100;
  246. Color.Blue := 100;
  247. AddRandomStars(100, TGIFColorMap.RGB2Color(Color), True);
  248. // some redish ones
  249. Color.Red := 100;
  250. Color.Green := 100;
  251. Color.Blue := 255;
  252. AddRandomStars(100, TGIFColorMap.RGB2Color(Color), True);
  253. // some blueish ones
  254. Color.Red := 255;
  255. Color.Green := 255;
  256. Color.Blue := 100;
  257. AddRandomStars(100, TGIFColorMap.RGB2Color(Color), True);
  258. // some yellowish ones
  259. end;
  260. GLSceneViewer1.Buffer.BackgroundColor := clBlack;
  261. with GLSceneViewer1.Buffer.FogEnvironment do
  262. begin
  263. FogColor.AsWinColor := clBlack;
  264. FogStart := -FogStart; // Fog is used to make things darker
  265. end;
  266. SPMoon.Visible := True;
  267. SPSun.Visible := False;
  268. GLLensFlare.Visible := False;
  269. end;
  270. 'd', 'D':
  271. with SkyDome1 do
  272. if Stars.Count > 0 then
  273. begin
  274. // turn on 'day' mode
  275. Bands[1].StopColor.Color := clrNavy;
  276. Bands[1].StartColor.Color := clrBlue;
  277. Bands[0].StopColor.Color := clrBlue;
  278. Bands[0].StartColor.Color := clrWhite;
  279. Stars.Clear;
  280. GLSceneViewer1.Buffer.BackgroundColor := clWhite;
  281. with GLSceneViewer1.Buffer.FogEnvironment do
  282. begin
  283. FogColor.AsWinColor := clWhite;
  284. FogStart := -FogStart;
  285. end;
  286. GLSceneViewer1.Buffer.FogEnvironment.FogStart := 0;
  287. SPMoon.Visible := False;
  288. SPSun.Visible := True;
  289. end;
  290. 't':
  291. with SkyDome1 do
  292. begin
  293. if sdoTwinkle in Options then
  294. Options := Options - [sdoTwinkle]
  295. else
  296. Options := Options + [sdoTwinkle];
  297. end;
  298. 'l':
  299. with GLLensFlare do
  300. Visible := (not Visible) and SPSun.Visible;
  301. end;
  302. Key := #0;
  303. end;
  304. procedure TFormTerrain.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  305. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  306. begin
  307. GLCamera1.AdjustDistanceToTarget(Power(1.03, WheelDelta/120));
  308. end;
  309. procedure TFormTerrain.TISoundTimer(Sender: TObject);
  310. var
  311. wolfPos: TGLVector;
  312. c, s: Single;
  313. begin
  314. if not GLSMBASS1.Active then
  315. Exit;
  316. if SkyDome1.Stars.Count = 0 then
  317. begin
  318. // wind blows around camera
  319. with GetOrCreateSoundEmitter(GLCamera1) do
  320. begin
  321. Source.SoundLibrary := GLSoundLibrary;
  322. Source.SoundName := GLSoundLibrary.Samples[0].Name;
  323. Source.Volume := Random * 0.5 + 0.5;
  324. Playing := True;
  325. end;
  326. end
  327. else
  328. begin
  329. // wolf howl at some distance, at ground level
  330. wolfPos := GLCamera1.AbsolutePosition;
  331. SinCosine(Random * c2PI, 100 + Random(1000), s, c);
  332. wolfPos.X := wolfPos.X + c;
  333. wolfPos.Z := wolfPos.Z + s;
  334. wolfPos.Y := TerrainRenderer1.InterpolatedHeight(wolfPos);
  335. DCSound.Position.AsVector := wolfPos;
  336. with GetOrCreateSoundEmitter(DCSound) do
  337. begin
  338. Source.SoundLibrary := GLSoundLibrary;
  339. Source.SoundName := GLSoundLibrary.Samples[1].Name;
  340. Source.MinDistance := 100;
  341. Source.MaxDistance := 4000;
  342. Playing := True;
  343. end;
  344. end;
  345. TISound.Enabled := False;
  346. TISound.Interval := 10000 + Random(10000);
  347. TISound.Enabled := True;
  348. end;
  349. // Test Code for InterpolatedHeight, use as a Button1's click event
  350. {
  351. procedure TForm1.Button1Click(Sender: TObject);
  352. var
  353. x, y : Integer;
  354. sph : TGLSphere;
  355. begin
  356. for x:=-5 to 5 do begin
  357. for y:=-5 to 5 do begin
  358. sph:=TGLSphere(GLScene1.Objects.AddNewChild(TGLSphere));
  359. sph.Position.X:=DummyCube1.Position.X+X*2;
  360. sph.Position.Z:=DummyCube1.Position.Z+Y*2;
  361. sph.Position.Y:=TerrainRenderer1.InterpolatedHeight(sph.Position.AsVector);
  362. sph.Radius:=0.5;
  363. end;
  364. end;
  365. end; }
  366. end.