fMain.pas 27 KB

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