fGLSViewer.pas 28 KB

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