fMain.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. unit fMain;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. Winapi.Messages,
  6. Winapi.OpenGL,
  7. System.SysUtils,
  8. System.Classes,
  9. System.IniFiles,
  10. System.Win.Registry,
  11. System.ImageList,
  12. System.Math,
  13. System.Actions,
  14. System.Types,
  15. Vcl.Graphics,
  16. Vcl.Controls,
  17. Vcl.Forms,
  18. Vcl.Dialogs,
  19. Vcl.ActnList,
  20. Vcl.Menus,
  21. Vcl.ImgList,
  22. Vcl.ToolWin,
  23. Vcl.ComCtrls,
  24. Vcl.ExtDlgs,
  25. Vcl.ExtCtrls,
  26. Vcl.ActnMan,
  27. Vcl.ActnCtrls,
  28. Vcl.ActnMenus,
  29. Vcl.StdActns,
  30. Vcl.BandActn,
  31. Vcl.PlatformDefaultStyleActnCtrls,
  32. GLS.Material,
  33. GLS.Scene,
  34. GLS.SceneViewer,
  35. GLS.VectorFileObjects,
  36. GLS.Objects,
  37. GLS.VectorGeometry,
  38. GLS.Texture,
  39. GLS.Context,
  40. GLS.VectorLists,
  41. GLS.Cadencer,
  42. GLS.Coordinates,
  43. GLS.BaseClasses,
  44. GLS.State,
  45. GLS.RenderContextInfo,
  46. Scenario.TextureFormat,
  47. GLS.Color,
  48. GLS.Keyboard,
  49. GLS.Graphics,
  50. GLS.PersistentClasses,
  51. GLS.MeshUtils,
  52. GLS.VectorTypes,
  53. GnuGettext,
  54. GLS.AsyncTimer,
  55. GLS.Graph,
  56. GLS.MeshBuilder,
  57. GLS.Navigator,
  58. GLS.Utils,
  59. fGLForm,
  60. fGLAbout,
  61. fGLOptions,
  62. fGLDialog,
  63. dGLSViewer,
  64. GLS.SimpleNavigation;
  65. type
  66. TMainForm = class(TGLForm)
  67. ImageList: TImageList;
  68. StatusBar: TStatusBar;
  69. Scene: TGLScene;
  70. ffObject: TGLFreeForm;
  71. LightSource: TGLLightSource;
  72. MaterialLib: TGLMaterialLibrary;
  73. CubeExtents: TGLCube;
  74. dcTarget: TGLDummyCube;
  75. Camera: TGLCamera;
  76. dcAxis: TGLDummyCube;
  77. Cadencer: TGLCadencer;
  78. Timer: TTimer;
  79. LightmapLib: TGLMaterialLibrary;
  80. snViewer: TGLSceneViewer;
  81. ActionManager: TActionManager;
  82. acOptimizeMesh: TAction;
  83. acProcessInvertNormals: TAction;
  84. acReverseRendering: TAction;
  85. acConvertToTriangles: TAction;
  86. acProcessStripify: TAction;
  87. acToolsOptions: TAction;
  88. acToolsFaceCulling: TAction;
  89. acToolsTexturing: TAction;
  90. acToolsLighting: TAction;
  91. acToolsCustomize: TCustomizeActionBars;
  92. acToolsShowFPS: TAction;
  93. acViewSmoothShading: TAction;
  94. acViewFlatShading: TAction;
  95. acViewFlatLines: TAction;
  96. acViewHiddenLines: TAction;
  97. acViewWireFrame: TAction;
  98. acViewZoomIn: TAction;
  99. acViewZoomOut: TAction;
  100. acViewReset: TAction;
  101. acFileOpen: TAction;
  102. acFilePick: TAction;
  103. acFileOpenTexLib: TAction;
  104. acFileSaveAs: TAction;
  105. acFileSaveTextures: TAction;
  106. acFileExit: TAction;
  107. acHelpContents: THelpContents;
  108. acHelpTopicSearch: THelpTopicSearch;
  109. acHelpOnHelp: THelpOnHelp;
  110. acHelpGLSHomePage: TAction;
  111. acHelpAbout: TAction;
  112. acAADefault: TAction;
  113. acAA2X: TAction;
  114. acAA4X: TAction;
  115. acEditUndo: TEditUndo;
  116. acEditCut: TEditCut;
  117. acEditCopy: TEditCopy;
  118. acEditPaste: TEditPaste;
  119. acEditSelectAll: TEditSelectAll;
  120. acEditDelete: TEditDelete;
  121. ImageListMenu: TImageList;
  122. ControlBar: TControlBar;
  123. amMenuBar: TActionMainMenuBar;
  124. acAA8X: TAction;
  125. acAA16X: TAction;
  126. acCSA8X: TAction;
  127. acCSA16X: TAction;
  128. atbTools: TActionToolBar;
  129. atbView: TActionToolBar;
  130. atbFile: TActionToolBar;
  131. acPoints: TAction;
  132. AsyncTimer: TGLAsyncTimer;
  133. dcWorld: TGLDummyCube;
  134. grdXYZ: TGLXYZGrid;
  135. acToolsNaviCube: TAction;
  136. GLPoints: TGLPoints;
  137. acToolsInfo: TAction;
  138. GLSimpleNavigation: TGLSimpleNavigation;
  139. acSpheres: TAction;
  140. procedure FormCreate(Sender: TObject);
  141. procedure snViewerMouseDown(Sender: TObject; Button: TMouseButton;
  142. Shift: TShiftState; X, Y: Integer);
  143. procedure snViewerMouseMove(Sender: TObject; Shift: TShiftState;
  144. X, Y: Integer);
  145. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  146. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  147. procedure snViewerMouseUp(Sender: TObject; Button: TMouseButton;
  148. Shift: TShiftState; X, Y: Integer);
  149. procedure snViewerBeforeRender(Sender: TObject);
  150. procedure snViewerAfterRender(Sender: TObject);
  151. procedure FormShow(Sender: TObject);
  152. procedure MaterialLibTextureNeeded(Sender: TObject;
  153. var textureFileName: String);
  154. procedure acInvertNormalsExecute(Sender: TObject);
  155. procedure acSaveAsUpdate(Sender: TObject);
  156. procedure acReverseRenderingOrderExecute(Sender: TObject);
  157. procedure acConvertToIndexedTrianglesExecute(Sender: TObject);
  158. procedure CadencerProgress(Sender: TObject;
  159. const deltaTime, newTime: Double);
  160. procedure TimerTimer(Sender: TObject);
  161. procedure acOptimizeExecute(Sender: TObject);
  162. procedure acStripifyExecute(Sender: TObject);
  163. procedure acHelpAboutExecute(Sender: TObject);
  164. procedure acFilePickExecute(Sender: TObject);
  165. procedure acFileOpenTexLibExecute(Sender: TObject);
  166. procedure acFileOpenExecute(Sender: TObject);
  167. procedure acFileSaveAsExecute(Sender: TObject);
  168. procedure acFileSaveTexturesExecute(Sender: TObject);
  169. procedure acFileExitExecute(Sender: TObject);
  170. procedure acToolsOptionsExecute(Sender: TObject);
  171. procedure acToolsTexturingExecute(Sender: TObject);
  172. procedure acToolsFaceCullingExecute(Sender: TObject);
  173. procedure acToolsLightingExecute(Sender: TObject);
  174. procedure acToolsShowFPSExecute(Sender: TObject);
  175. procedure acAADefaultExecute(Sender: TObject);
  176. procedure acViewSmoothShadingExecute(Sender: TObject);
  177. procedure acViewFlatShadingExecute(Sender: TObject);
  178. procedure acViewFlatLinesExecute(Sender: TObject);
  179. procedure acViewHiddenLinesExecute(Sender: TObject);
  180. procedure acViewWireFrameExecute(Sender: TObject);
  181. procedure acViewResetExecute(Sender: TObject);
  182. procedure acViewZoomOutExecute(Sender: TObject);
  183. procedure acViewZoomInExecute(Sender: TObject);
  184. procedure acPointsExecute(Sender: TObject);
  185. procedure AsyncTimerTimer(Sender: TObject);
  186. procedure acToolsNaviCubeExecute(Sender: TObject);
  187. procedure acToolsInfoExecute(Sender: TObject);
  188. procedure snViewerMouseLeave(Sender: TObject);
  189. private
  190. procedure DoResetCamera;
  191. procedure SetupFreeFormShading;
  192. procedure ApplyShadeModeToMaterial(aMaterial: TGLMaterial);
  193. procedure ApplyShadeMode;
  194. procedure ApplyFSAA;
  195. procedure ApplyFaceCull;
  196. procedure ApplyTexturing;
  197. procedure ApplyFPS;
  198. procedure DoOpen(const FileName: String);
  199. public
  200. md, nthShow: Boolean;
  201. mx, my: Integer;
  202. hlShader: TGLShader;
  203. lastFileName: String;
  204. lastLoadWithTextures: Boolean;
  205. Points: TGLPoints;
  206. procedure ApplyBgColor;
  207. procedure ReadIniFile; override;
  208. procedure WriteIniFile; override;
  209. end;
  210. var
  211. MainForm: TMainForm;
  212. NaviCube: TGLNaviCube;
  213. //=======================================================================
  214. implementation
  215. //=======================================================================
  216. {$R *.dfm}
  217. uses
  218. GLS.FileOBJ,
  219. GLS.FileSTL,
  220. GLS.FileLWO,
  221. GLS.FileQ3BSP,
  222. GLS.FileOCT,
  223. GLS.FileMS3D,
  224. GLS.FileNMF,
  225. GLS.FileMD3,
  226. GLS.File3DS,
  227. GLS.FileMD2,
  228. GLS.FileSMD,
  229. GLS.FilePLY,
  230. GLS.FileGTS,
  231. GLS.FileVRML,
  232. GLS.FileMD5,
  233. GLS.FileTIN,
  234. GLS.FileDXF,
  235. GLS.FileGRD,
  236. GLS.FileX,
  237. GLS.FileGLTF;
  238. type
  239. // Hidden line shader (specific implem for the viewer, *not* generic)
  240. THiddenLineShader = class(TGLShader)
  241. private
  242. LinesColor: TGLColorVector;
  243. BackgroundColor: TGLColorVector;
  244. PassCount: Integer;
  245. public
  246. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  247. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  248. end;
  249. procedure THiddenLineShader.DoApply(var rci: TGLRenderContextInfo;
  250. Sender: TObject);
  251. begin
  252. PassCount := 1;
  253. with rci.GLStates do
  254. begin
  255. PolygonMode := pmFill;
  256. gl.Color3fv(@BackgroundColor);
  257. ActiveTextureEnabled[ttTexture2D] := False;
  258. Enable(stPolygonOffsetFill);
  259. PolygonOffsetFactor := 1;
  260. PolygonOffsetUnits := 2;
  261. end;
  262. end;
  263. function THiddenLineShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  264. begin
  265. case PassCount of
  266. 1:
  267. with rci.GLStates do
  268. begin
  269. PassCount := 2;
  270. PolygonMode := pmLines;
  271. glColor3fv(@LinesColor);
  272. Disable(stLighting);
  273. Result := True;
  274. end;
  275. 2:
  276. begin
  277. rci.GLStates.Disable(stPolygonOffsetFill);
  278. Result := False;
  279. end;
  280. else
  281. // doesn't hurt to be cautious
  282. Assert(False);
  283. Result := False;
  284. end;
  285. end;
  286. procedure TMainForm.FormCreate(Sender: TObject);
  287. begin
  288. inherited;
  289. // SetCurrentDir(ExtractFilePath(ParamStr(0)));
  290. SetCurrentDirToAsset();
  291. NaviCube := TGLNaviCube.CreateAsChild(Scene.Objects);
  292. NaviCube.SceneViewer := snViewer;
  293. NaviCube.FPS := 30;
  294. // instantiate our specific hidden-lines shader
  295. hlShader := THiddenLineShader.Create(Self);
  296. ffObject.IgnoreMissingTextures := True;
  297. end;
  298. procedure TMainForm.FormShow(Sender: TObject);
  299. begin
  300. if not nthShow then
  301. begin
  302. // using formats supported by gls
  303. dmGLSViewer.OpenDialog.Filter := VectorFileFormatsFilter;
  304. dmGLSViewer.SaveDialog.Filter := VectorFileFormatsSaveFilter;
  305. ApplyFSAA;
  306. ApplyFaceCull;
  307. ApplyFPS;
  308. if ParamCount > 0 then
  309. DoOpen(ParamStr(0));
  310. nthShow := True;
  311. end;
  312. end;
  313. procedure TMainForm.acFileExitExecute(Sender: TObject);
  314. begin
  315. Close;
  316. end;
  317. procedure TMainForm.acFileOpenExecute(Sender: TObject);
  318. begin
  319. NaviCube.ActiveMouse := False;
  320. if dmGLSViewer.OpenDialog.Execute then
  321. DoOpen(dmGLSViewer.OpenDialog.FileName);
  322. end;
  323. procedure TMainForm.acFileOpenTexLibExecute(Sender: TObject);
  324. var
  325. I: Integer;
  326. begin
  327. if dmGLSViewer.ODTextures.Execute then
  328. with MaterialLib do
  329. begin
  330. LoadFromFile(dmGLSViewer.ODTextures.FileName);
  331. for I := 0 to Materials.Count - 1 do
  332. with Materials[I].Material do
  333. BackProperties.Assign(FrontProperties);
  334. ApplyShadeMode;
  335. ApplyTexturing;
  336. end;
  337. end;
  338. procedure TMainForm.acFilePickExecute(Sender: TObject);
  339. begin
  340. if dmGLSViewer.opDialog.Execute then
  341. begin
  342. with MaterialLib.Materials do
  343. begin
  344. with Items[Count - 1] do
  345. begin
  346. Tag := 1;
  347. Material.Texture.Image.LoadFromFile(dmGLSViewer.opDialog.FileName);
  348. Material.Texture.Enabled := True;
  349. end;
  350. end;
  351. ApplyTexturing;
  352. end;
  353. end;
  354. procedure TMainForm.acFileSaveAsExecute(Sender: TObject);
  355. var
  356. ext: String;
  357. begin
  358. if dmGLSViewer.SaveDialog.Execute then
  359. begin
  360. ext := ExtractFileExt(dmGLSViewer.SaveDialog.FileName);
  361. if ext = '' then
  362. dmGLSViewer.SaveDialog.FileName :=
  363. ChangeFileExt(dmGLSViewer.SaveDialog.FileName,
  364. '.' + GetVectorFileFormats.FindExtByIndex
  365. (dmGLSViewer.SaveDialog.FilterIndex, False, True));
  366. if GetVectorFileFormats.FindFromFileName(dmGLSViewer.SaveDialog.FileName) = nil
  367. then
  368. ShowMessage(_('Unsupported or unspecified file extension.'))
  369. else
  370. ffObject.SaveToFile(dmGLSViewer.SaveDialog.FileName);
  371. end;
  372. end;
  373. procedure TMainForm.acFileSaveTexturesExecute(Sender: TObject);
  374. begin
  375. if dmGLSViewer.SDTextures.Execute then
  376. MaterialLib.SaveToFile(dmGLSViewer.SDTextures.FileName);
  377. end;
  378. procedure TMainForm.snViewerBeforeRender(Sender: TObject);
  379. begin
  380. THiddenLineShader(hlShader).LinesColor := VectorMake(107 / 256, 123 / 256,
  381. 173 / 256, 1);
  382. THiddenLineShader(hlShader).BackgroundColor :=
  383. ConvertWinColor(snViewer.Buffer.BackgroundColor);
  384. if not gl.ARB_multisample then
  385. begin
  386. acAADefault.Checked := True;
  387. acAA2X.Enabled := False;
  388. acAA4X.Enabled := False;
  389. acAA8X.Enabled := False;
  390. acAA16X.Enabled := False;
  391. acCSA8X.Enabled := False;
  392. acCSA16X.Enabled := False;
  393. end;
  394. end;
  395. procedure TMainForm.snViewerAfterRender(Sender: TObject);
  396. begin
  397. ApplyFSAA;
  398. Screen.Cursor := crDefault;
  399. end;
  400. procedure TMainForm.DoResetCamera;
  401. var
  402. objSize: Single;
  403. begin
  404. dcTarget.Position.AsVector := NullHmgPoint;
  405. Camera.Position.SetPoint(0, 4, 5);
  406. ffObject.Position.AsVector := NullHmgPoint;
  407. ffObject.Up.Assign(dcAxis.Up);
  408. ffObject.Direction.Assign(dcAxis.Direction);
  409. objSize := ffObject.BoundingSphereRadius;
  410. if objSize > 0 then
  411. begin
  412. if objSize < 1 then
  413. begin
  414. Camera.SceneScale := 1 / objSize;
  415. objSize := 1;
  416. end
  417. else
  418. Camera.SceneScale := 1;
  419. Camera.AdjustDistanceToTarget(objSize * 0.27);
  420. Camera.DepthOfView := 1.5 * Camera.DistanceToTarget + 2 * objSize;
  421. end;
  422. end;
  423. procedure TMainForm.ApplyShadeModeToMaterial(aMaterial: TGLMaterial);
  424. begin
  425. if acViewSmoothShading.Checked then
  426. begin
  427. snViewer.Buffer.Lighting := True;
  428. snViewer.Buffer.ShadeModel := smSmooth;
  429. aMaterial.PolygonMode := pmFill;
  430. end
  431. else if acViewFlatShading.Checked then
  432. begin
  433. snViewer.Buffer.Lighting := True;
  434. snViewer.Buffer.ShadeModel := smFlat;
  435. aMaterial.PolygonMode := pmFill;
  436. end
  437. else if acViewFlatLines.Checked then
  438. begin
  439. snViewer.Buffer.Lighting := True;
  440. snViewer.Buffer.ShadeModel := smFlat;
  441. aMaterial.PolygonMode := pmLines;
  442. end
  443. else if acViewHiddenLines.Checked then
  444. begin
  445. snViewer.Buffer.Lighting := False;
  446. snViewer.Buffer.ShadeModel := smSmooth;
  447. aMaterial.PolygonMode := pmLines;
  448. end
  449. else if acViewWireFrame.Checked then
  450. begin
  451. snViewer.Buffer.Lighting := False;
  452. snViewer.Buffer.ShadeModel := smSmooth;
  453. aMaterial.PolygonMode := pmLines;
  454. end;
  455. end;
  456. procedure TMainForm.ApplyShadeMode;
  457. var
  458. I: Integer;
  459. begin
  460. with MaterialLib.Materials do
  461. for I := 0 to Count - 1 do
  462. begin
  463. ApplyShadeModeToMaterial(Items[I].Material);
  464. if (acViewHiddenLines.Checked) or (acViewFlatLines.Checked) then
  465. Items[I].Shader := hlShader
  466. else
  467. Items[I].Shader := nil;
  468. end;
  469. snViewer.Buffer.Lighting := acToolsLighting.Checked;
  470. ffObject.StructureChanged;
  471. end;
  472. procedure TMainForm.ApplyFSAA;
  473. begin
  474. with snViewer.Buffer do
  475. begin
  476. if acAADefault.Checked then
  477. AntiAliasing := aaDefault
  478. else if acAA2X.Checked then
  479. AntiAliasing := aa2x
  480. else if acAA4X.Checked then
  481. AntiAliasing := aa4x
  482. else if acAA8X.Checked then
  483. AntiAliasing := aa8x
  484. else if acAA16X.Checked then
  485. AntiAliasing := aa16x
  486. else if acCSA8X.Checked then
  487. AntiAliasing := csa8x
  488. else if acCSA16X.Checked then
  489. AntiAliasing := csa16x;
  490. end;
  491. end;
  492. procedure TMainForm.ApplyFaceCull;
  493. begin
  494. with snViewer.Buffer do
  495. begin
  496. if acToolsFaceCulling.Checked then
  497. begin
  498. FaceCulling := True;
  499. ContextOptions := ContextOptions - [roTwoSideLighting];
  500. end
  501. else
  502. begin
  503. FaceCulling := False;
  504. ContextOptions := ContextOptions + [roTwoSideLighting];
  505. end;
  506. end;
  507. end;
  508. procedure TMainForm.ApplyBgColor;
  509. var
  510. bmp: TBitmap;
  511. col: TColor;
  512. begin
  513. bmp := TBitmap.Create;
  514. try
  515. bmp.Width := 16;
  516. bmp.Height := 16;
  517. col := ColorToRGB(dmGLSViewer.ColorDialog.Color);
  518. snViewer.Buffer.BackgroundColor := col;
  519. bmp.Canvas.Pen.Color := col xor $FFFFFF;
  520. bmp.Canvas.Rectangle(0, 0, 16, 16);
  521. bmp.Canvas.Brush.Color := col;
  522. finally
  523. bmp.Free;
  524. end;
  525. end;
  526. procedure TMainForm.ApplyTexturing;
  527. var
  528. I: Integer;
  529. begin
  530. with MaterialLib.Materials do
  531. for I := 0 to Count - 1 do
  532. begin
  533. with Items[I].Material.Texture do
  534. begin
  535. if Enabled then
  536. Items[I].Tag := Integer(True);
  537. Enabled := Boolean(Items[I].Tag) and acToolsTexturing.Checked;
  538. end;
  539. end;
  540. ffObject.StructureChanged;
  541. end;
  542. procedure TMainForm.AsyncTimerTimer(Sender: TObject);
  543. begin
  544. snViewer.ResetPerformanceMonitor;
  545. end;
  546. procedure TMainForm.ApplyFPS;
  547. begin
  548. if acToolsShowFPS.Checked then
  549. begin
  550. Timer.Enabled := True;
  551. Cadencer.Enabled := True;
  552. end
  553. else
  554. begin
  555. Timer.Enabled := False;
  556. Cadencer.Enabled := False;
  557. // StatusBar.Panels[3].Text := ' FPS';
  558. end;
  559. end;
  560. procedure TMainForm.SetupFreeFormShading;
  561. var
  562. I: Integer;
  563. LibMat: TGLLibMaterial;
  564. begin
  565. if MaterialLib.Materials.Count = 0 then
  566. begin
  567. ffObject.Material.MaterialLibrary := MaterialLib;
  568. LibMat := MaterialLib.Materials.Add;
  569. ffObject.Material.LibMaterialName := LibMat.Name;
  570. LibMat.Material.FrontProperties.Diffuse.Red := 0;
  571. end;
  572. for I := 0 to MaterialLib.Materials.Count - 1 do
  573. with MaterialLib.Materials[I].Material do
  574. BackProperties.Assign(FrontProperties);
  575. ApplyShadeMode;
  576. ApplyTexturing;
  577. ApplyFPS;
  578. end;
  579. procedure TMainForm.DoOpen(const FileName: String);
  580. var
  581. min, max: TAffineVector;
  582. Name: TFileName;
  583. begin
  584. if not FileExists(FileName) then
  585. Exit;
  586. Screen.Cursor := crHourGlass;
  587. MainForm.Caption := 'GLSViewer - ' + FileName;
  588. MaterialLib.Materials.Clear;
  589. ffObject.MeshObjects.Clear;
  590. ffObject.LoadFromFile(FileName);
  591. SetupFreeFormShading;
  592. acFileSaveTextures.Enabled := (MaterialLib.Materials.Count > 0);
  593. acFileOpenTexLib.Enabled := (MaterialLib.Materials.Count > 0);
  594. lastFileName := FileName;
  595. lastLoadWithTextures := acToolsTexturing.Enabled;
  596. ffObject.GetExtents(min, max);
  597. CubeExtents.CubeWidth := max.X - min.X;
  598. CubeExtents.CubeHeight := max.Y - min.Y;
  599. CubeExtents.CubeDepth := max.Z - min.Z;
  600. CubeExtents.Position.AsAffineVector := VectorLerp(min, max, 0.5);
  601. StatusBar.Panels[0].Text := 'X: ' + ' ';
  602. StatusBar.Panels[1].Text := 'Y: ' + ' ';
  603. StatusBar.Panels[2].Text := 'Z: ' + ' ';
  604. Name := ExtractFileName(FileName);
  605. StatusBar.Panels[3].Text := Name;
  606. DoResetCamera;
  607. end;
  608. procedure TMainForm.snViewerMouseDown(Sender: TObject; Button: TMouseButton;
  609. Shift: TShiftState; X, Y: Integer);
  610. begin
  611. mx := X;
  612. my := Y;
  613. md := True;
  614. end;
  615. procedure TMainForm.snViewerMouseLeave(Sender: TObject);
  616. begin
  617. Cadencer.Enabled := False;
  618. end;
  619. procedure TMainForm.snViewerMouseMove(Sender: TObject; Shift: TShiftState;
  620. X, Y: Integer);
  621. var
  622. d: Single;
  623. begin
  624. if md and (Shift <> []) then
  625. begin
  626. if ssLeft in Shift then
  627. if ssShift in Shift then
  628. Camera.MoveAroundTarget((my - Y) * 0.1, (mx - X) * 0.1)
  629. else
  630. Camera.MoveAroundTarget(my - Y, mx - X)
  631. else if ssRight in Shift then
  632. begin
  633. d := Camera.DistanceToTarget * 0.01 * (X - mx + Y - my);
  634. if IsKeyDown('x') then
  635. ffObject.Translate(d, 0, 0)
  636. else if IsKeyDown('y') then
  637. ffObject.Translate(0, d, 0)
  638. else if IsKeyDown('z') then
  639. ffObject.Translate(0, 0, d)
  640. else
  641. begin
  642. if ssShift in Shift then
  643. Camera.RotateObject(ffObject, (my - Y) * 0.1, (mx - X) * 0.1)
  644. else
  645. Camera.RotateObject(ffObject, my - Y, mx - X);
  646. end;
  647. end;
  648. mx := X;
  649. my := Y;
  650. end;
  651. end;
  652. procedure TMainForm.snViewerMouseUp(Sender: TObject; Button: TMouseButton;
  653. Shift: TShiftState; X, Y: Integer);
  654. begin
  655. md := False;
  656. end;
  657. procedure TMainForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  658. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  659. begin
  660. if ffObject.MeshObjects.Count > 0 then
  661. begin
  662. Camera.AdjustDistanceToTarget(Power(1.05, WheelDelta / 120));
  663. Camera.DepthOfView := 2 * Camera.DistanceToTarget + 2 *
  664. ffObject.BoundingSphereRadius;
  665. end;
  666. Handled := True;
  667. end;
  668. procedure TMainForm.MaterialLibTextureNeeded(Sender: TObject;
  669. var textureFileName: String);
  670. begin
  671. if not acToolsTexturing.Enabled then
  672. textureFileName := '';
  673. end;
  674. procedure TMainForm.acInvertNormalsExecute(Sender: TObject);
  675. var
  676. I: Integer;
  677. begin
  678. with ffObject.MeshObjects do
  679. for I := 0 to Count - 1 do
  680. Items[I].Normals.Scale(-1);
  681. ffObject.StructureChanged;
  682. end;
  683. procedure TMainForm.acReverseRenderingOrderExecute(Sender: TObject);
  684. var
  685. I, j, n: Integer;
  686. fg: TGLFaceGroup;
  687. begin
  688. with ffObject.MeshObjects do
  689. begin
  690. // invert meshobjects order
  691. for I := 0 to (Count div 2) do
  692. Exchange(I, Count - 1 - I);
  693. // for each mesh object
  694. for I := 0 to Count - 1 do
  695. with Items[I] do
  696. begin
  697. // invert facegroups order
  698. n := FaceGroups.Count;
  699. for j := 0 to (n div 2) do
  700. Exchange(j, n - 1 - j);
  701. // for each facegroup
  702. for j := 0 to n - 1 do
  703. begin
  704. fg := FaceGroups[j];
  705. fg.Reverse;
  706. end;
  707. end;
  708. end;
  709. ffObject.StructureChanged;
  710. end;
  711. procedure TMainForm.acSaveAsUpdate(Sender: TObject);
  712. begin
  713. acFileSaveAs.Enabled := (ffObject.MeshObjects.Count > 0);
  714. end;
  715. procedure TMainForm.acHelpAboutExecute(Sender: TObject);
  716. begin
  717. with TGLAbout.Create(Self) do
  718. try
  719. ShowModal;
  720. finally
  721. Free;
  722. end;
  723. end;
  724. procedure TMainForm.acAADefaultExecute(Sender: TObject);
  725. begin
  726. (Sender as TAction).Checked := True;
  727. ApplyFSAA;
  728. end;
  729. procedure TMainForm.acConvertToIndexedTrianglesExecute(Sender: TObject);
  730. var
  731. v: TGLAffineVectorList;
  732. I: TGLIntegerList;
  733. m: TGLMeshObject;
  734. fg: TFGVertexIndexList;
  735. begin
  736. v := ffObject.MeshObjects.ExtractTriangles;
  737. try
  738. I := BuildVectorCountOptimizedIndices(v);
  739. try
  740. RemapAndCleanupReferences(v, I);
  741. IncreaseCoherency(I, 12);
  742. I.Capacity := I.Count;
  743. ffObject.MeshObjects.Clean;
  744. m := TGLMeshObject.CreateOwned(ffObject.MeshObjects);
  745. m.Vertices := v;
  746. m.BuildNormals(I, momTriangles);
  747. m.Mode := momFaceGroups;
  748. fg := TFGVertexIndexList.CreateOwned(m.FaceGroups);
  749. fg.VertexIndices := I;
  750. fg.Mode := fgmmTriangles;
  751. ffObject.StructureChanged;
  752. finally
  753. I.Free;
  754. end;
  755. finally
  756. v.Free;
  757. end;
  758. MaterialLib.Materials.Clear;
  759. SetupFreeFormShading;
  760. end;
  761. procedure TMainForm.acStripifyExecute(Sender: TObject);
  762. var
  763. I: Integer;
  764. mo: TGLMeshObject;
  765. fg: TFGVertexIndexList;
  766. strips: TGLPersistentObjectList;
  767. begin
  768. acConvertToTriangles.Execute;
  769. mo := ffObject.MeshObjects[0];
  770. fg := (mo.FaceGroups[0] as TFGVertexIndexList);
  771. strips := StripifyMesh(fg.VertexIndices, mo.Vertices.Count, True);
  772. try
  773. fg.Free;
  774. for I := 0 to strips.Count - 1 do
  775. begin
  776. fg := TFGVertexIndexList.CreateOwned(mo.FaceGroups);
  777. fg.VertexIndices := (strips[I] as TGLIntegerList);
  778. if I = 0 then
  779. fg.Mode := fgmmTriangles
  780. else
  781. fg.Mode := fgmmTriangleStrip;
  782. end;
  783. finally
  784. strips.Free;
  785. end;
  786. end;
  787. procedure TMainForm.acViewFlatShadingExecute(Sender: TObject);
  788. begin
  789. ApplyShadeMode;
  790. end;
  791. procedure TMainForm.acViewHiddenLinesExecute(Sender: TObject);
  792. begin
  793. ApplyShadeMode;
  794. end;
  795. procedure TMainForm.acViewResetExecute(Sender: TObject);
  796. begin
  797. DoResetCamera;
  798. end;
  799. procedure TMainForm.acViewFlatLinesExecute(Sender: TObject);
  800. begin
  801. ApplyShadeMode;
  802. end;
  803. procedure TMainForm.acViewSmoothShadingExecute(Sender: TObject);
  804. begin
  805. ApplyShadeMode;
  806. end;
  807. procedure TMainForm.acViewWireFrameExecute(Sender: TObject);
  808. begin
  809. ApplyShadeMode;
  810. end;
  811. procedure TMainForm.acViewZoomInExecute(Sender: TObject);
  812. var
  813. h: Boolean;
  814. begin
  815. FormMouseWheel(Self, [], -120 * 4, Point(0, 0), h);
  816. end;
  817. procedure TMainForm.acViewZoomOutExecute(Sender: TObject);
  818. var
  819. h: Boolean;
  820. begin
  821. FormMouseWheel(Self, [], 120 * 4, Point(0, 0), h);
  822. end;
  823. procedure TMainForm.acOptimizeExecute(Sender: TObject);
  824. begin
  825. OptimizeMesh(ffObject.MeshObjects, [mooVertexCache, mooSortByMaterials]);
  826. ffObject.StructureChanged;
  827. SetupFreeFormShading;
  828. end;
  829. procedure TMainForm.acToolsOptionsExecute(Sender: TObject);
  830. begin
  831. with TGLOptions.Create(Self) do
  832. try
  833. ShowModal;
  834. finally
  835. Free;
  836. end;
  837. end;
  838. procedure TMainForm.acToolsFaceCullingExecute(Sender: TObject);
  839. begin
  840. acToolsFaceCulling.Checked := not acToolsFaceCulling.Checked;
  841. ApplyFaceCull;
  842. end;
  843. procedure TMainForm.acToolsInfoExecute(Sender: TObject);
  844. begin
  845. with TGLDialog.Create(Self) do
  846. try
  847. Memo.Lines[0] := 'Triangles: ' +
  848. IntToStr(ffObject.MeshObjects.TriangleCount);
  849. Memo.Lines[1] := 'Area: ' + FloatToStr(ffObject.MeshObjects.Area);
  850. Memo.Lines[2] := 'Volume: ' + FloatToStr(ffObject.MeshObjects.Volume);
  851. ShowModal;
  852. finally
  853. Free;
  854. end;
  855. end;
  856. procedure TMainForm.acToolsLightingExecute(Sender: TObject);
  857. begin
  858. acToolsLighting.Checked := not acToolsLighting.Checked;
  859. // TBLighting
  860. ApplyShadeMode;
  861. end;
  862. procedure TMainForm.acToolsShowFPSExecute(Sender: TObject);
  863. begin
  864. acToolsShowFPS.Checked := not acToolsShowFPS.Checked;
  865. ApplyFPS;
  866. end;
  867. procedure TMainForm.acToolsTexturingExecute(Sender: TObject);
  868. begin
  869. acToolsTexturing.Checked := not acToolsTexturing.Checked;
  870. if acToolsTexturing.Checked then
  871. if lastLoadWithTextures then
  872. ApplyTexturing
  873. else
  874. begin
  875. DoOpen(lastFileName);
  876. end
  877. else
  878. ApplyTexturing;
  879. end;
  880. procedure TMainForm.acToolsNaviCubeExecute(Sender: TObject);
  881. begin
  882. acToolsNaviCube.Checked := not acToolsNaviCube.Checked;
  883. if acToolsNaviCube.Checked = True then
  884. begin
  885. NaviCube.Visible := True;
  886. Cadencer.Enabled := True;
  887. end
  888. else
  889. begin
  890. NaviCube.Visible := False;
  891. Cadencer.Enabled := False;
  892. end;
  893. snViewer.Invalidate;
  894. end;
  895. // Show Base and Additional Objects
  896. procedure TMainForm.acPointsExecute(Sender: TObject);
  897. var
  898. I: Integer;
  899. Color: TVector3f;
  900. NumPoints: Integer;
  901. X, Y, Z: Single;
  902. begin
  903. NumPoints := 10000;
  904. GLPoints := TGLPoints(dcWorld.AddNewChild(TGLPoints));
  905. GLPoints.Size := 5.0;
  906. GLPoints.Style := psSmooth;
  907. for I := 0 to NumPoints - 1 do
  908. begin
  909. Color.X := Random();
  910. Color.Y := Random();
  911. Color.Z := Random();
  912. X := Random(10) - 5;
  913. Y := Random(10) - 5;
  914. Z := Random(10) - 5;
  915. GLPoints.Positions.Add(X * 0.05, Y * 0.05, Z * 0.05);
  916. // Fill array of GLPoints
  917. GLPoints.Colors.AddPoint(Color);
  918. end;
  919. // dcWorld.Remove(GLPoints, False);
  920. // GLPoints := TGLPoints(dcWorld.AddNewChild(TGLPoints));
  921. end;
  922. (*
  923. procedure TMainForm.acDeletePoints(Sender: TObject);
  924. var
  925. I: Integer;
  926. Color: TVector3f;
  927. NumPoints: Integer;
  928. X, Y, Z: Single;
  929. begin
  930. NumPoints := 10000;
  931. GLPoints := TGLPoints(dcWorld.AddNewChild(TGLPoints));
  932. for I := 0 to NumPoints - 1 do
  933. begin
  934. Color.X := Random();
  935. Color.Y := Random();
  936. Color.Z := Random();
  937. X := Random(100) - 50;
  938. Y := Random(100) - 50;
  939. Z := Random(100) - 50;
  940. GLPoints.Positions.Add(X * 0.05, Y * 0.05, Z * 0.05);
  941. // Fill array of GLPoints
  942. end;
  943. end;
  944. *)
  945. procedure TMainForm.CadencerProgress(Sender: TObject;
  946. const deltaTime, newTime: Double);
  947. begin
  948. if NaviCube.InactiveTime > 5 then
  949. begin
  950. if NaviCube.InactiveTime < 8 then
  951. Camera.TurnAngle := Camera.TurnAngle + (NaviCube.InactiveTime - 5) *
  952. deltaTime * 2
  953. else
  954. Camera.TurnAngle := Camera.TurnAngle + deltaTime * 6;
  955. end;
  956. snViewer.Refresh;
  957. if Self.Focused then
  958. snViewer.Invalidate;
  959. end;
  960. procedure TMainForm.TimerTimer(Sender: TObject);
  961. begin
  962. // StatusBar.Panels[3].Text := Format('%.1f FPS', [snViewer.FramesPerSecond]);
  963. snViewer.ResetPerformanceMonitor;
  964. end;
  965. procedure TMainForm.ReadIniFile;
  966. begin
  967. inherited;
  968. IniFile := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
  969. try
  970. Top := IniFile.ReadInteger(Name, 'Top', 100);
  971. Left := IniFile.ReadInteger(Name, 'Left', 200);
  972. finally
  973. IniFile.Free;
  974. end;
  975. end;
  976. procedure TMainForm.WriteIniFile;
  977. begin
  978. IniFile := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
  979. with IniFile do
  980. try
  981. WriteInteger(Name, 'Top', Top);
  982. WriteInteger(Name, 'Left', Left);
  983. // WriteBool(Name, 'InitMax', WindowState = wsMaximized);
  984. finally
  985. IniFile.Free;
  986. end;
  987. inherited;
  988. end;
  989. end.