Unit1.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. // ---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #include <tchar.h>
  4. #pragma hdrstop
  5. #include "Unit1.h"
  6. // ---------------------------------------------------------------------------
  7. #pragma package(smart_init)
  8. #pragma link "GLBaseClasses"
  9. #pragma link "GLBitmapFont"
  10. #pragma link "GLCadencer"
  11. #pragma link "GLCoordinates"
  12. #pragma link "GLCrossPlatform"
  13. #pragma link "GLHeightData"
  14. #pragma link "GLHeightTileFileHDS"
  15. #pragma link "GLMaterial"
  16. #pragma link "GLObjects"
  17. #pragma link "GLScene"
  18. #pragma link "GLSkydome"
  19. #pragma link "GLTerrainRenderer"
  20. #pragma link "GLVectorFileObjects"
  21. #pragma link "GLWin32Viewer"
  22. #pragma link "GLWindowsFont"
  23. #pragma link "GLBaseClasses"
  24. #pragma link "GLBitmapFont"
  25. #pragma link "GLCadencer"
  26. #pragma link "GLCoordinates"
  27. #pragma link "GLCrossPlatform"
  28. #pragma link "GLHeightData"
  29. #pragma link "GLHeightTileFileHDS"
  30. #pragma link "GLHUDObjects"
  31. #pragma link "GLMaterial"
  32. #pragma link "GLObjects"
  33. #pragma link "GLScene"
  34. #pragma link "GLSkydome"
  35. #pragma link "GLTerrainRenderer"
  36. #pragma link "GLVectorFileObjects"
  37. #pragma link "GLWin32Viewer"
  38. #pragma link "GLWindowsFont"
  39. #pragma link "GLBaseClasses"
  40. #pragma link "GLBitmapFont"
  41. #pragma link "GLCadencer"
  42. #pragma link "GLCoordinates"
  43. #pragma link "GLCrossPlatform"
  44. #pragma link "GLHeightData"
  45. #pragma link "GLHeightTileFileHDS"
  46. #pragma link "GLHUDObjects"
  47. #pragma link "GLMaterial"
  48. #pragma link "GLObjects"
  49. #pragma link "GLScene"
  50. #pragma link "GLSkydome"
  51. #pragma link "GLTerrainRenderer"
  52. #pragma link "GLVectorFileObjects"
  53. #pragma link "GLWin32Viewer"
  54. #pragma link "GLWindowsFont"
  55. #pragma resource "*.dfm"
  56. TForm1 *Form1;
  57. #define cWaterLevel -10000
  58. #define cWaterOpaqueDepth 2000
  59. #define cWaveAmplitude 120
  60. // ---------------------------------------------------------------------------
  61. __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
  62. }
  63. // ---------------------------------------------------------------------------
  64. void __fastcall TForm1::FormCreate(TObject *Sender) {
  65. int i, j;
  66. String name;
  67. TGLLibMaterial *libMat;
  68. String DataPath;
  69. // DataPath = ExtractFilePath(ParamStr(0));
  70. DataPath = ExtractFilePath(Application->ExeName);
  71. DataPath += "Data\\";
  72. SetCurrentDir(DataPath);
  73. MaterialLibrary->TexturePaths = DataPath;
  74. GLCustomHDS1->MaxPoolSize = 8 * 1024 * 1024;
  75. GLCustomHDS1->DefaultHeight = cWaterLevel;
  76. // load texmaps
  77. for (i = 0; i <= 3; i++)
  78. for (j = 0; j <= 3; j++) {
  79. name = Format("Tex_%d_%d.bmp", ARRAYOFCONST((i, j)));
  80. if (!FileExists(name)) {
  81. ShowMessage("Texture file " + name + " not found...\r\
  82. Did you run " "splitter->exe"
  83. " as said in the readme->txt?");
  84. Application->Terminate();
  85. Abort();
  86. }
  87. libMat = MaterialLibrary->AddTextureMaterial(name, name, false);
  88. libMat->Material->Texture->TextureMode = tmReplace;
  89. libMat->Material->Texture->TextureWrap = twNone;
  90. // comment out to turn off texture compression
  91. libMat->Material->Texture->Compression = tcStandard;
  92. libMat->Material->Texture->FilteringQuality = tfAnisotropic;
  93. libMat->Texture2Name = "detail";
  94. }
  95. // Initial camera height offset (controled with pageUp/pageDown)
  96. CamHeight = 20;
  97. // Water plane active
  98. WaterPlane = true;
  99. // load the sailboat
  100. FFSailBoat->LoadFromFile("sailboat.glsm");
  101. MLSailBoat->LoadFromFile("sailboat.glml");
  102. FFSailBoat->Position->SetPoint(-125*TerrainRenderer->Scale->X, 0,
  103. -100*TerrainRenderer->Scale->Z);
  104. FFSailBoat->TurnAngle = -30;
  105. // boost ambient
  106. for (i = 0; i < MLSailBoat->Materials->Count; i++)
  107. MLSailBoat->Materials->Items[i]
  108. ->Material->FrontProperties->Ambient->Color =
  109. MLSailBoat->Materials->Items[i]
  110. ->Material->FrontProperties->Diffuse->Color;
  111. // Move camera starting point near the sailboat
  112. DCCamera->Position = FFSailBoat->Position;
  113. DCCamera->Translate(25, 0, -15);
  114. DCCamera->Turn(200);
  115. // Help text
  116. HTHelp->Text = "GLScene Archipelago Demo\r\
  117. * : Increase CLOD precision\r\
  118. / : decrease CLOD precision\r\
  119. W : wireframe on/off\r\
  120. S : sea surface on/off\r\
  121. B : sailboat visible on/off\r\
  122. Num4 & Num6 : steer the sailboat\r\
  123. F1: show this help";
  124. HTHelp->Position->SetPoint(Screen->Width / 2 - 100,
  125. Screen->Height / 2 - 150, 0);
  126. HelpOpacity = 4;
  127. GLSceneViewer->Cursor = crNone;
  128. }
  129. // ---------------------------------------------------------------------------
  130. void TForm1::ResetMousePos(void) {
  131. if (GLSceneViewer->Cursor == crNone)
  132. SetCursorPos(Screen->Width / 2, Screen->Height / 2);
  133. }
  134. // ---------------------------------------------------------------------------
  135. void __fastcall TForm1::GLCadencerProgress(TObject *Sender,
  136. const double deltaTime, const double newTime) {
  137. float Speed, Alpha, f;
  138. float TerrainHeight, SurfaceHeight;
  139. Glvectorgeometry::TVector Sbp;
  140. POINT NewMousePos;
  141. // Handle keypresses
  142. if (IsKeyDown(VK_SHIFT))
  143. Speed = 100 * deltaTime;
  144. else
  145. Speed = 20 * deltaTime;
  146. if (IsKeyDown(VK_UP))
  147. DCCamera->Position->AddScaledVector(Speed,
  148. GLCamera->AbsoluteVectorToTarget());
  149. if (IsKeyDown(VK_DOWN))
  150. DCCamera->Position->AddScaledVector(-Speed,
  151. GLCamera->AbsoluteVectorToTarget());
  152. if (IsKeyDown(VK_LEFT))
  153. DCCamera->Position->AddScaledVector(-Speed,
  154. GLCamera->AbsoluteRightVectorToTarget());
  155. if (IsKeyDown(VK_RIGHT))
  156. DCCamera->Position->AddScaledVector(Speed,
  157. GLCamera->AbsoluteRightVectorToTarget());
  158. if (IsKeyDown(VK_PRIOR))
  159. CamHeight = CamHeight + Speed;
  160. if (IsKeyDown(VK_NEXT))
  161. CamHeight = CamHeight - Speed;
  162. if (IsKeyDown(VK_ESCAPE))
  163. Close();
  164. if (IsKeyDown(VK_F1))
  165. HelpOpacity = ClampValue(HelpOpacity + deltaTime * 5, 3, 5);
  166. if (IsKeyDown(VK_NUMPAD4))
  167. FFSailBoat->Turn(-deltaTime*3);
  168. if (IsKeyDown(VK_NUMPAD6))
  169. FFSailBoat->Turn(deltaTime*3);
  170. // Mouse movements and actions
  171. if (IsKeyDown(VK_LBUTTON)) {
  172. Alpha = DCCamera->Position->Y;
  173. DCCamera->Position->AddScaledVector(Speed,
  174. GLCamera->AbsoluteVectorToTarget());
  175. CamHeight = CamHeight + DCCamera->Position->Y - Alpha;
  176. }
  177. if (IsKeyDown(VK_RBUTTON)) {
  178. Alpha = DCCamera->Position->Y;
  179. DCCamera->Position->AddScaledVector(-Speed,
  180. GLCamera->AbsoluteVectorToTarget());
  181. CamHeight = CamHeight + DCCamera->Position->Y - Alpha;
  182. }
  183. GetCursorPos(&NewMousePos);
  184. GLCamera->MoveAroundTarget((Screen->Height / 2 - NewMousePos.y)*0.25,
  185. (Screen->Width / 2 - NewMousePos.x)*0.25);
  186. ResetMousePos();
  187. // Don"t drop our target through terrain!
  188. TerrainHeight = TerrainRenderer->InterpolatedHeight
  189. (DCCamera->Position->AsVector);
  190. SurfaceHeight = TerrainRenderer->Scale->Z * cWaterLevel / 128;
  191. if (TerrainHeight < SurfaceHeight)
  192. TerrainHeight = SurfaceHeight;
  193. DCCamera->Position->Y = TerrainHeight + CamHeight;
  194. // Adjust fog distance/color for air/water
  195. if ((GLCamera->AbsolutePosition.Y > SurfaceHeight) || (!WaterPlane)) {
  196. if (!WasAboveWater) {
  197. SkyDome->Visible = true;
  198. GLSceneViewer->Buffer->FogEnvironment->FogColor->Color = clrWhite;
  199. GLSceneViewer->Buffer->FogEnvironment->FogEnd = 1000;
  200. GLSceneViewer->Buffer->FogEnvironment->FogStart = 500;
  201. GLSceneViewer->Buffer->BackgroundColor = clWhite;
  202. GLCamera->DepthOfView = 1000;
  203. WasAboveWater = true;
  204. }
  205. }
  206. else {
  207. if (WasAboveWater) {
  208. SkyDome->Visible = false;
  209. GLSceneViewer->Buffer->FogEnvironment->FogColor->AsWinColor =
  210. clNavy;
  211. GLSceneViewer->Buffer->FogEnvironment->FogEnd = 100;
  212. GLSceneViewer->Buffer->FogEnvironment->FogStart = 0;
  213. GLSceneViewer->Buffer->BackgroundColor = clNavy;
  214. GLCamera->DepthOfView = 100;
  215. WasAboveWater = false;
  216. }
  217. }
  218. // Visibility of Help
  219. if (HelpOpacity > 0) {
  220. HelpOpacity = HelpOpacity - deltaTime;
  221. Alpha = ClampValue(HelpOpacity, 0, 1);
  222. if (Alpha > 0) {
  223. HTHelp->Visible = true;
  224. HTHelp->ModulateColor->Alpha = Alpha;
  225. }
  226. else
  227. HTHelp->Visible = false;
  228. }
  229. // Rock the sailboat
  230. Sbp = TerrainRenderer->AbsoluteToLocal(FFSailBoat->AbsolutePosition);
  231. Alpha = WaterPhase(Sbp.X + TerrainRenderer->TileSize * 0.5,
  232. Sbp.Y + TerrainRenderer->TileSize * 0.5);
  233. FFSailBoat->Position->Y = (cWaterLevel + sin(Alpha) * cWaveAmplitude) *
  234. (TerrainRenderer->Scale->Z / 128) - 1.5;
  235. f = cWaveAmplitude * 0.01;
  236. FFSailBoat->Up->SetVector(cos(Alpha)*0.02*f, 1,
  237. (sin(Alpha)*0.02 - 0.005)*f);
  238. FFSailBoat->Move(deltaTime*2);
  239. }
  240. // ---------------------------------------------------------------------------
  241. void __fastcall TForm1::Timer1Timer(TObject *Sender) {
  242. HTFPS->Text = Format("%.1f FPS - %d - %d",
  243. ARRAYOFCONST((GLSceneViewer->FramesPerSecond(),
  244. TerrainRenderer->LastTriangleCount, WaterPolyCount)));
  245. GLSceneViewer->ResetPerformanceMonitor();
  246. }
  247. // ---------------------------------------------------------------------------
  248. void __fastcall TForm1::FormKeyPress(TObject *Sender, System::WideChar &Key) {
  249. int i;
  250. TPolygonMode pm;
  251. switch (Key) {
  252. case 'w':
  253. case 'W': {
  254. if (MaterialLibrary->Materials->Items[0]->Material->PolygonMode ==
  255. pmLines)
  256. pm = pmFill;
  257. else
  258. pm = pmLines;
  259. for (i = 0; i < MaterialLibrary->Materials->Count; i++)
  260. MaterialLibrary->Materials->Items[i]
  261. ->Material->PolygonMode = pm;
  262. for (i = 0; i < MLSailBoat->Materials->Count; i++)
  263. MLSailBoat->Materials->Items[i]->Material->PolygonMode = pm;
  264. FFSailBoat->StructureChanged();
  265. break;
  266. }
  267. case 's':
  268. case 'S':
  269. WaterPlane = !WaterPlane;
  270. break;
  271. case 'b':
  272. case 'B':
  273. FFSailBoat->Visible = !FFSailBoat->Visible;
  274. break;
  275. case '*':
  276. if (TerrainRenderer->CLODPrecision > 1)
  277. TerrainRenderer->CLODPrecision =
  278. (int)(TerrainRenderer->CLODPrecision * 0.8);
  279. break;
  280. case '/':
  281. if (TerrainRenderer->CLODPrecision < 1000)
  282. TerrainRenderer->CLODPrecision =
  283. (int)(TerrainRenderer->CLODPrecision * 1.2 + 1);
  284. break;
  285. }
  286. Key = 0x0;
  287. }
  288. // ---------------------------------------------------------------------------
  289. void __fastcall TForm1::GLCustomHDS1MarkDirtyEvent(const TRect &area) {
  290. GLHeightTileFileHDS1->MarkDirty(area);
  291. }
  292. // ---------------------------------------------------------------------------
  293. void __fastcall TForm1::GLCustomHDS1StartPreparingData(TGLHeightData *heightData)
  294. {
  295. TGLHeightData *htfHD;
  296. int i, j, n;
  297. TTexPoint offset;
  298. htfHD = GLHeightTileFileHDS1->GetData(heightData->XLeft, heightData->YTop,
  299. heightData->Size, heightData->DataType);
  300. if ((htfHD->DataState == hdsNone))
  301. // or (htfHD->HeightMax<=cWaterLevel-cWaterOpaqueDepth)
  302. heightData->DataState = hdsNone;
  303. else {
  304. i = (heightData->XLeft / 128);
  305. j = (heightData->YTop / 128);
  306. if ((Cardinal(i) < 4) & (Cardinal(j) < 4)) {
  307. heightData->MaterialName =
  308. Format("Tex_%d_%d.bmp", ARRAYOFCONST((i, j)));
  309. heightData->TextureCoordinatesMode = tcmLocal;
  310. n = ((heightData->XLeft / 32) & 3);
  311. offset.S = n * 0.25;
  312. n = ((heightData->YTop / 32) & 3);
  313. offset.T = -n * 0.25;
  314. heightData->TextureCoordinatesOffset = offset;
  315. heightData->TextureCoordinatesScale = TexPointMake(0.25, 0.25);
  316. heightData->DataType = hdtSmallInt;
  317. htfHD->DataType = hdtSmallInt;
  318. heightData->Allocate(hdtSmallInt);
  319. Move(htfHD->SmallIntData, heightData->SmallIntData,
  320. htfHD->DataSize);
  321. heightData->DataState = hdsReady;
  322. heightData->HeightMin = htfHD->HeightMin;
  323. heightData->HeightMax = htfHD->HeightMax;
  324. }
  325. else
  326. heightData->DataState = hdsNone;
  327. }
  328. GLHeightTileFileHDS1->Release(htfHD);
  329. }
  330. // ---------------------------------------------------------------------------
  331. void __fastcall TForm1::GLSceneViewerBeforeRender(TObject *Sender) {
  332. int i, n;
  333. PAProgress->Left = (Width - PAProgress->Width) / 2;
  334. PAProgress->Visible = true;
  335. n = MaterialLibrary->Materials->Count;
  336. ProgressBar->Max = n - 1;
  337. try {
  338. for (i = 0; i < n; i++) {
  339. ProgressBar->Position = i;
  340. MaterialLibrary->Materials->Items[i]->Material->Texture->Handle;
  341. PAProgress->Repaint();
  342. }
  343. }
  344. __finally {
  345. ResetMousePos();
  346. PAProgress->Visible = false;
  347. GLSceneViewer->BeforeRender = NULL;
  348. }
  349. }
  350. // ---------------------------------------------------------------------------
  351. float TForm1::WaterPhase(const float px, const float py) {
  352. return GLCadencer->CurrentTime * 1.0 + px * 0.16 + py * 0.09;
  353. }
  354. // ---------------------------------------------------------------------------
  355. float TForm1::WaterHeight(const float px, const float py) {
  356. float alpha;
  357. alpha = WaterPhase(px + TerrainRenderer->TileSize * 0.5,
  358. py + TerrainRenderer->TileSize * 0.5);
  359. return (cWaterLevel + sin(alpha) * cWaveAmplitude) *
  360. (TerrainRenderer->Scale->Z * (1.0 / 128));
  361. }
  362. // ---------------------------------------------------------------------------
  363. void TForm1::IssuePoint(TGLHeightData *hd, int x, int y, int s2, float t, int rx,
  364. int ry) {
  365. const float r = 0.75;
  366. const float g = 0.75;
  367. const float b = 1.0;
  368. float px, py;
  369. float alpha, colorRatio, ca, sa;
  370. px = x + rx + s2;
  371. py = y + ry + s2;
  372. if (hd->DataState == hdsNone) {
  373. alpha = 1;
  374. }
  375. else {
  376. alpha = (cWaterLevel - hd->SmallIntHeight(rx, ry)) *
  377. (1 / cWaterOpaqueDepth);
  378. alpha = ClampValue(alpha, 0.5, 1.0);
  379. }
  380. SinCos(WaterPhase(px, py), sa, ca);
  381. colorRatio = 1 - alpha * 0.1;
  382. glColor4f(r*colorRatio, g*colorRatio, b, alpha);
  383. glTexCoord2f(px*0.01 + 0.002*sa, py*0.01 + 0.0022*ca - t*0.002);
  384. glVertex3f(px, py, cWaterLevel + cWaveAmplitude*sa);
  385. }
  386. // ---------------------------------------------------------------------------
  387. void __fastcall TForm1::TerrainRendererHeightDataPostRender
  388. (TGLRenderContextInfo &rci, TList *&HeightDatas) {
  389. int i, x, y, s, s2;
  390. float t;
  391. TGLHeightData *hd;
  392. if (WaterPlane) {
  393. t = GLCadencer->CurrentTime;
  394. MaterialLibrary->ApplyMaterial("water", rci);
  395. do {
  396. if (!WasAboveWater)
  397. rci.GLStates->InvertGLFrontFace();
  398. glPushAttrib(GL_ENABLE_BIT);
  399. glDisable(GL_LIGHTING);
  400. glDisable(GL_NORMALIZE);
  401. glStencilFunc(GL_ALWAYS, 1, 255);
  402. glStencilMask(255);
  403. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  404. glEnable(GL_STENCIL_TEST);
  405. glNormal3f(0, 0, 1);
  406. for (i = 0; i < HeightDatas->Count; i++) {
  407. hd = (TGLHeightData*)(HeightDatas->List[i]);
  408. if ((hd->DataState == hdsReady) && (hd->HeightMin >
  409. cWaterLevel))
  410. continue;
  411. x = hd->XLeft;
  412. y = hd->YTop;
  413. s = hd->Size - 1;
  414. s2 = s / 2;
  415. glBegin(GL_TRIANGLE_FAN);
  416. IssuePoint(hd, x, y, s2, t, s2, s2);
  417. IssuePoint(hd, x, y, s2, t, 0, 0);
  418. IssuePoint(hd, x, y, s2, t, s2, 0);
  419. IssuePoint(hd, x, y, s2, t, s, 0);
  420. IssuePoint(hd, x, y, s2, t, s, s2);
  421. IssuePoint(hd, x, y, s2, t, s, s);
  422. IssuePoint(hd, x, y, s2, t, s2, s);
  423. IssuePoint(hd, x, y, s2, t, 0, s);
  424. IssuePoint(hd, x, y, s2, t, 0, s2);
  425. IssuePoint(hd, x, y, s2, t, 0, 0);
  426. glEnd();
  427. }
  428. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  429. glPopAttrib();
  430. if (!WasAboveWater)
  431. rci.GLStates->InvertGLFrontFace();
  432. WaterPolyCount = HeightDatas->Count * 8;
  433. }
  434. while (MaterialLibrary->UnApplyMaterial(rci));
  435. }
  436. }
  437. // ---------------------------------------------------------------------------
  438. void __fastcall TForm1::DOWakeProgress(TObject *Sender, const double deltaTime,
  439. const double newTime) {
  440. int i;
  441. Glvectorgeometry::TVector sbp, sbr;
  442. if (WakeVertices == NULL) {
  443. WakeVertices = new TAffineVectorList();
  444. WakeStretch = new TAffineVectorList();
  445. WakeTime = new TSingleList();
  446. }
  447. // enlarge current vertices
  448. i = 0;
  449. while (i < WakeVertices->Count) {
  450. WakeVertices->CombineItem(i, WakeStretch->Items[i >> 1],
  451. -0.45*deltaTime);
  452. WakeVertices->CombineItem(i + 1, WakeStretch->Items[i >> 1],
  453. 0.45*deltaTime);
  454. i += 2;
  455. }
  456. // Progress wake
  457. if (newTime > DOWake->TagFloat) {
  458. if (DOWake->TagFloat == 0) {
  459. DOWake->TagFloat = newTime + 0.2;
  460. }
  461. else {
  462. DOWake->TagFloat = newTime + 1;
  463. sbp = VectorCombine(FFSailBoat->AbsolutePosition,
  464. FFSailBoat->AbsoluteDirection, 1, 3);
  465. sbr = FFSailBoat->AbsoluteRight();
  466. // add new
  467. WakeVertices->Add(VectorCombine(sbp, sbr, 1, -2));
  468. WakeVertices->Add(VectorCombine(sbp, sbr, 1, 2));
  469. WakeStretch->Add(VectorScale(sbr, (0.95 + Random()*0.1)));
  470. WakeTime->Add(newTime*0.1);
  471. if (WakeVertices->Count >= 80) {
  472. WakeVertices->Delete(0);
  473. WakeVertices->Delete(0);
  474. WakeStretch->Delete(0);
  475. WakeTime->Delete(0);
  476. }
  477. }
  478. }
  479. }
  480. // ---------------------------------------------------------------------------
  481. void __fastcall TForm1::DOWakeRender(TObject *Sender, TGLRenderContextInfo &rci) {
  482. int i, n;
  483. Glvectortypes::TVector3f p;
  484. Glvectorgeometry::TVector sbp;
  485. float c;
  486. if (!(WakeVertices) && (!((FFSailBoat->Visible) || (WaterPlane)))) {
  487. MaterialLibrary->ApplyMaterial("wake", rci);
  488. do {
  489. glPushAttrib(GL_ENABLE_BIT);
  490. glDisable(GL_LIGHTING);
  491. glDisable(GL_FOG);
  492. glEnable(GL_BLEND);
  493. glBlendFunc(GL_ONE, GL_ONE);
  494. glStencilFunc(GL_EQUAL, 1, 255);
  495. glStencilMask(255);
  496. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  497. glEnable(GL_STENCIL_TEST);
  498. glDisable(GL_DEPTH_TEST);
  499. if (!WasAboveWater)
  500. rci.GLStates->InvertGLFrontFace();
  501. glBegin(GL_TRIANGLE_STRIP);
  502. n = WakeVertices->Count;
  503. for (i = 0; i < n; i++) {
  504. p = WakeVertices->Items[i ^ 1];
  505. sbp = TerrainRenderer->AbsoluteToLocal(VectorMake(p, 0));
  506. if ((i & 1) == 0) {
  507. c = (i & 0xFFE) * 0.2 / n;
  508. glColor3f(c, c, c);
  509. glTexCoord2f(0, WakeTime->Items[i / 2]);
  510. }
  511. else
  512. glTexCoord2f(1, WakeTime->Items[i / 2]);
  513. glVertex3f(p.X, WaterHeight(sbp.X, sbp.Y), p.Z);
  514. }
  515. glEnd();
  516. if (!WasAboveWater)
  517. rci.GLStates->InvertGLFrontFace();
  518. glPopAttrib();
  519. glDisable(stStencilTest);
  520. }
  521. while (MaterialLibrary->UnApplyMaterial(rci));
  522. }
  523. }
  524. // ---------------------------------------------------------------------------