fTerrainD.pas 11 KB

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