fGLSViewer.pas 29 KB

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