fTerrainD.pas 11 KB

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