ArenaZ
513 строк · 13.8 Кб
1unit umainform;
2
3{$IFDEF FPC}
4{$MODE Delphi}
5{$ENDIF}
6
7interface
8
9uses
10{$IFnDEF FPC}
11Windows,
12{$ELSE}
13LCLIntf, LCLType, LMessages,
14{$ENDIF}
15Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
16Dialogs, ExtCtrls, Contnrs, ComCtrls, Buttons, StdCtrls,
17//GLS
18GLLCLViewer, GLScene, GLVectorFileObjects, GLState,
19GLTexture, GLObjects, GLVectorGeometry, GLVectorTypes, OpenGLTokens,
20GLMaterial, GLCoordinates, GLCrossPlatform, GLBaseClasses, FileUtil;
21
22type
23TModifierCube = class(TGLCube)
24public
25FVectorIndex : Integer;
26FMeshObjIndex : Integer;
27constructor Create(AOwner: TComponent); override;
28end;
29
30{ TfrmMain }
31
32TfrmMain = class(TForm)
33Label2: TLabel;
34Panel2: TPanel;
35Panel3: TPanel;
36GLSceneViewer: TGLSceneViewer;
37GLScene: TGLScene;
38GLCamera: TGLCamera;
39GLFreeForm: TGLFreeForm;
40Label1: TLabel;
41cbPolygonMode: TComboBox;
42dcModifiers: TGLDummyCube;
43chbViewPoints: TCheckBox;
44StatusBar: TStatusBar;
45GroupBox1: TGroupBox;
46chbShowAxis: TCheckBox;
47Label3: TLabel;
48Label4: TLabel;
49Label5: TLabel;
50Label6: TLabel;
51tbPos: TTrackBar;
52GroupBox2: TGroupBox;
53rbXY: TRadioButton;
54rbZY: TRadioButton;
55GLLightSource1: TGLLightSource;
56GroupBox3: TGroupBox;
57btnVertex: TBitBtn;
58btnNormals: TBitBtn;
59btnTextcoords: TBitBtn;
60btnGroups: TBitBtn;
61GLMaterialLibrary1: TGLMaterialLibrary;
62procedure FormCreate(Sender: TObject);
63procedure GLSceneViewerMouseDown(Sender: TObject;
64Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
65procedure GLSceneViewerMouseMove(Sender: TObject; Shift: TShiftState;
66X, Y: Integer);
67procedure cbPolygonModeChange(Sender: TObject);
68procedure FormDestroy(Sender: TObject);
69procedure chbViewPointsClick(Sender: TObject);
70procedure GLSceneViewerMouseUp(Sender: TObject; Button: TMouseButton;
71Shift: TShiftState; X, Y: Integer);
72procedure chbShowAxisClick(Sender: TObject);
73procedure tbPosChange(Sender: TObject);
74procedure GLSceneViewerBeforeRender(Sender: TObject);
75procedure btnVertexClick(Sender: TObject);
76procedure btnNormalsClick(Sender: TObject);
77procedure btnTextcoordsClick(Sender: TObject);
78procedure btnGroupsClick(Sender: TObject);
79private
80//Private declarations
81private
82{ Private declarations }
83FOldX, FOldY : Integer;
84FModifierList : TObjectList;
85FSelectedModifier : TModifierCube;
86FMoveZ : Boolean;
87FOldMouseWorldPos : TVector;
88
89{Create cubes used to modify vertex points}
90procedure SetVertexModifiers;
91{Populate statusbar with object information}
92procedure ShowModifierStatus(const aObj : TModifierCube);
93{Change the mesh vector property for the selected modifier.}
94procedure ChangeMeshVector(const aObj : TModifierCube; const aPos : TVector4f);
95{Identify mouse position in X, Y and Z axis}
96function MouseWorldPos(x, y : Integer) : TVector;
97{Strip redundent data, recalculate normals and faces}
98procedure StripAndRecalc;
99{Set Freeform's polygon mode: line, fill or points}
100public
101{ Public declarations }
102end;
103
104var
105frmMain: TfrmMain;
106
107implementation
108
109uses
110GLPersistentClasses, GLVectorLists,MeshData, GLMeshUtils,
111GLFile3DS, GLColor, GLContext;
112
113{$IFnDEF FPC}
114{$IFnDEF FPC}
115{$R *.lfm}
116{$ELSE}
117{$R *.lfm}
118{$ENDIF}
119{$ELSE}
120{$R *.lfm}
121{$ENDIF}
122
123const
124{Default combobox index for startup}
125CLinePolyMode = 1;
126{Scale dimention}
127CModifierDim = 0.04;
128
129var
130{Modifier colors}
131CModColorNormal : TColorVector;
132CModColorSelect : TColorVector;
133
134constructor TModifierCube.Create(AOwner: TComponent);
135begin
136inherited;
137{Set the modifiers initial size and color}
138CubeWidth := CModifierDim;
139CubeHeight := CModifierDim;
140CubeDepth := CModifierDim;
141Material.FrontProperties.Diffuse.Color := CModColorNormal;
142end;
143
144
145procedure TfrmMain.FormCreate(Sender: TObject);
146var
147lsDir : String;
148lsFileName : String;
149begin
150{Do initial setup}
151FModifierList := TObjectList.Create;
152CModColorNormal := clrCoral;
153CModColorSelect := clrSkyBlue;
154
155lsDir := ExtractFileDir(Application.ExeName);
156lsFileName := Format('%s\media\cube.3ds', [lsDir]);
157if FileExistsUTF8(lsFileName) { *Converti depuis FileExists* } then
158begin
159GLFreeForm.LoadFromFile(lsFileName);
160StripAndRecalc;
161SetVertexModifiers;
162end;
163
164cbPolygonMode.ItemIndex := CLinePolyMode;
165end;
166
167procedure TfrmMain.GLSceneViewerMouseDown(Sender: TObject;
168Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
169var
170lObj : TGLBaseSceneObject;
171begin
172FOldX := X; FOldY := Y;
173{If selecting a different modifier, change the last one's color back to default}
174if Assigned(FSelectedModifier) then
175FSelectedModifier.Material.FrontProperties.Diffuse.Color := CModColorNormal;
176
177
178{Get selected objects}
179if not (ssCtrl in Shift) then
180Exit;
181
182{Check if selected object is a modifier.
183If so, change modifiers color as to indicated selected modifier.}
184lObj := GLSceneViewer.Buffer.GetPickedObject(X, Y);
185if (lObj is TModifierCube) then
186begin
187FSelectedModifier := TModifierCube(lObj);
188FSelectedModifier.Material.FrontProperties.Diffuse.Color := CModColorSelect;
189FSelectedModifier.NotifyChange(FSelectedModifier);
190ShowModifierStatus(TModifierCube(lObj));
191
192FMoveZ := rbZY.Checked;
193FOldMouseWorldPos := MouseWorldPos(X, Y);
194end;
195end;
196
197procedure TfrmMain.GLSceneViewerMouseMove(Sender: TObject;
198Shift: TShiftState; X, Y: Integer);
199var
200lCurrentPos : TVector;
201lOldV : TVector3f;
202lDiff : TVector4f;
203begin
204{If ctrl is not in use, move around freeform}
205if (ssLeft in Shift) and (not (ssCtrl in Shift)) then
206begin
207GLCamera.MoveAroundTarget(FOldY - Y, FOldX - X);
208FOldX := X; FOldY := Y;
209Exit;
210end;
211
212{Move modifier and change relevant vertex data}
213if (ssLeft in Shift) then
214begin
215FMoveZ := rbZY.Checked;
216
217lCurrentPos := MouseWorldPos(X, Y);
218if Assigned(FSelectedModifier) and (VectorNorm(FOldMouseWorldPos) <> 0) then
219begin
220MakeVector(lOldV, FSelectedModifier.Position.X, FSelectedModifier.Position.Y, FSelectedModifier.Position.Z);
221lDiff := VectorSubtract(lCurrentPos, FOldMouseWorldPos);
222FSelectedModifier.Position.Translate(lDiff);
223ChangeMeshVector(FSelectedModifier, lDiff);
224end;
225FOldMouseWorldPos := lCurrentPos;
226end;
227end;
228
229procedure TfrmMain.cbPolygonModeChange(Sender: TObject);
230begin
231case cbPolygonMode.ItemIndex of
2320: GLFreeForm.Material.PolygonMode := pmFill;
2331: GLFreeForm.Material.PolygonMode := pmLines;
2342: GLFreeForm.Material.PolygonMode := pmPoints;
235end;
236
237
238end;
239
240procedure TfrmMain.SetVertexModifiers;
241procedure ScaleVector(var V1, V2 : TVector3F);
242begin
243V1.X := V1.X * V2.X;
244V1.Y := V1.Y * V2.Y;
245V1.Z := V1.Z * V2.Z;
246end;
247var
248i, j : Integer;
249lVector, lScale : TVector3F;
250lModifier : TModifierCube;
251begin
252FModifierList.Clear;
253GLScene.BeginUpdate;
254try
255with GLFreeForm.MeshObjects do
256begin
257for i := 0 to Count - 1 do
258for j := 0 to Items[i].Vertices.Count - 1 do
259begin
260lVector := Items[i].Vertices.Items[j];
261lModifier := TModifierCube.Create(nil);
262lModifier.FVectorIndex := j;
263lModifier.FMeshObjIndex := i;
264
265FModifierList.Add(lModifier);
266GLScene.Objects.AddChild(lModifier);
267
268lScale := GLFreeForm.Scale.AsAffineVector;
269ScaleVector(lVector, lScale);
270lModifier.Position.Translate(lVector);
271end;
272end;
273finally
274GLScene.EndUpdate;
275end;
276end;
277
278procedure TfrmMain.FormDestroy(Sender: TObject);
279begin
280FModifierList.Clear;
281FreeAndNil(FModifierList);
282end;
283
284procedure TfrmMain.chbViewPointsClick(Sender: TObject);
285var
286i : Integer;
287begin
288GLScene.BeginUpdate;
289try
290for i := 0 to FModifierList.Count - 1 do
291TModifierCube(FModifierList.Items[i]).Visible := chbViewPoints.Checked;
292finally
293GLScene.EndUpdate;
294end;
295end;
296
297procedure TfrmMain.ShowModifierStatus(const aObj: TModifierCube);
298begin
299if aObj = nil then
300StatusBar.Panels[0].Text := ''
301else
302StatusBar.Panels[0].Text := Format('Modifier vector index [%d]', [aObj.FVectorIndex]);
303end;
304
305function TfrmMain.MouseWorldPos(x, y: Integer): TVector;
306var
307v : TVector;
308begin
309y := GLSceneViewer.Height - y;
310
311if Assigned(FSelectedModifier) then
312begin
313SetVector(v, x, y, 0);
314if FMoveZ then
315GLSceneViewer.Buffer.ScreenVectorIntersectWithPlaneXZ(v, FSelectedModifier.Position.Y, Result)
316else
317GLSceneViewer.Buffer.ScreenVectorIntersectWithPlaneXY(v, FSelectedModifier.Position.Z, Result);
318end
319else
320SetVector(Result, NullVector);
321end;
322
323procedure TfrmMain.ChangeMeshVector(const aObj : TModifierCube; const aPos : TVector4f);
324var
325lVIndex,
326lMIndex : Integer;
327v : TVector3f;
328begin
329if aObj = nil then
330Exit;
331
332lVIndex := aObj.FVectorIndex;
333lMIndex := aObj.FMeshObjIndex;
334
335{Get new vertex position, keep freeform scale in mind and redraw freeform.}
336MakeVector(v, aPos.X/CModifierDim, aPos.Y/CModifierDim, aPos.Z/CModifierDim);
337GLFreeForm.MeshObjects.Items[lMIndex].Vertices.TranslateItem(lVIndex, v);
338GLFreeForm.StructureChanged;
339end;
340
341procedure TfrmMain.GLSceneViewerMouseUp(Sender: TObject;
342Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
343begin
344if Assigned(FSelectedModifier) then
345begin
346FSelectedModifier.Material.FrontProperties.Diffuse.Color := CModColorNormal;
347FSelectedModifier := nil;
348{Recalculate structure and redraw freeform}
349StripAndRecalc;
350{Reset vertex modifiers and their data.}
351SetVertexModifiers;
352end;
353end;
354
355procedure TfrmMain.chbShowAxisClick(Sender: TObject);
356begin
357dcModifiers.ShowAxes := TCheckBox(Sender).Checked;
358end;
359
360procedure TfrmMain.tbPosChange(Sender: TObject);
361begin
362GLCamera.Position.Z := tbPos.Position;
363
364end;
365
366procedure TfrmMain.GLSceneViewerBeforeRender(Sender: TObject);
367begin
368gl.Enable(GL_NORMALIZE);
369end;
370
371procedure TfrmMain.btnVertexClick(Sender: TObject);
372var
373i, j : Integer;
374lList : TStringList;
375lVector : TVector3f;
376begin
377lList := TStringList.Create;
378try
379with GLFreeForm.MeshObjects do
380for i := 0 to Count - 1 do
381begin
382lList.Add('For mesh object ' + IntToStr(i));
383for j := 0 to Items[i].Vertices.Count - 1 do
384begin
385lVector := Items[i].Vertices.Items[j];
386lList.Add(Format('%f %f %f', [lVector.X, lVector.Y, lVector.Z]));
387end;
388end;
389ShowMeshData(lList);
390finally
391FreeAndNil(lList);
392end;
393end;
394
395procedure TfrmMain.btnNormalsClick(Sender: TObject);
396var
397i, j : Integer;
398lList : TStringList;
399lVector : TVector3f;
400begin
401lList := TStringList.Create;
402try
403with GLFreeForm.MeshObjects do
404for i := 0 to Count - 1 do
405begin
406lList.Add('For mesh object ' + IntToStr(i));
407for j := 0 to Items[i].Normals.Count - 1 do
408begin
409lVector := Items[i].Normals.Items[j];
410lList.Add(Format('%f %f %f', [lVector.X, lVector.Y, lVector.Z]));
411end;
412end;
413ShowMeshData(lList);
414finally
415FreeAndNil(lList);
416end;
417end;
418
419procedure TfrmMain.btnTextcoordsClick(Sender: TObject);
420var
421i, j : Integer;
422lList : TStringList;
423lVector : TVector3f;
424begin
425lList := TStringList.Create;
426try
427with GLFreeForm.MeshObjects do
428for i := 0 to Count - 1 do
429begin
430lList.Add('For mesh object ' + IntToStr(i));
431for j := 0 to Items[i].TexCoords.Count - 1 do
432begin
433lVector := Items[i].TexCoords.Items[j];
434lList.Add(Format('%f %f %f', [lVector.X, lVector.Y, lVector.Z]));
435end;
436end;
437ShowMeshData(lList);
438finally
439FreeAndNil(lList);
440end;
441end;
442
443procedure TfrmMain.btnGroupsClick(Sender: TObject);
444var
445i : Integer;
446lList : TStringList;
447begin
448lList := TStringList.Create;
449try
450with GLFreeForm.MeshObjects do
451for i := 0 to Count - 1 do
452begin
453lList.Add('For mesh object ' + IntToStr(i));
454lList.Add(IntToStr(Items[i].TriangleCount));
455end;
456ShowMeshData(lList);
457finally
458FreeAndNil(lList);
459end;
460end;
461
462procedure TfrmMain.StripAndRecalc;
463var
464lTrigList,
465lNormals : TAffineVectorList;
466lIndices : TIntegerList;
467lObj : TGLMeshObject;
468lStrips : TPersistentObjectList;
469
470lFaceGroup : TFGVertexIndexList;
471i : Integer;
472begin
473// Extract raw triangle data to work with.
474lTrigList := GLFreeForm.MeshObjects.ExtractTriangles;
475
476// Builds a vector-count optimized indices list.
477lIndices := BuildVectorCountOptimizedIndices(lTrigList);
478// Alter reference/indice pair and removes unused reference values.
479RemapAndCleanupReferences(lTrigList, lIndices);
480// Calculate normals.
481lNormals := BuildNormals(lTrigList, lIndices);
482
483// Strip where posible.
484lStrips := StripifyMesh(lIndices, lTrigList.Count, True);
485
486// Clear current mesh object data.
487GLFreeForm.MeshObjects.Clear;
488
489// Setup new mesh object.
490lObj := TGLMeshObject.CreateOwned(GLFreeForm.MeshObjects);
491lObj.Vertices := lTrigList;
492lObj.Mode := momFaceGroups;
493lObj.Normals := lNormals;
494
495for i:=0 to lStrips.Count-1 do
496begin
497lFaceGroup := TFGVertexIndexList.CreateOwned(lObj.FaceGroups);
498lFaceGroup.VertexIndices := (lStrips[i] as TIntegerList);
499if i > 0 then
500lFaceGroup.Mode := fgmmTriangleStrip
501else
502lFaceGroup.Mode := fgmmTriangles;
503lFaceGroup.MaterialName:=IntToStr(i and 15);
504end;
505// Redraw freeform
506GLFreeForm.StructureChanged;
507
508lTrigList.Free;
509lNormals.Free;
510lIndices.Free;
511end;
512
513end.
514