source: trunk/Packages/bgrabitmap/face3d.inc

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 14.3 KB
Line 
1type
2 PBGRAFaceVertexDescription = ^TBGRAFaceVertexDescription;
3 TBGRAFaceVertexDescription = record
4 Vertex: IBGRAVertex3D;
5 Normal: IBGRANormal3D;
6 Color: TBGRAPixel;
7 TexCoord: TPointF;
8 ColorOverride: boolean;
9 TexCoordOverride: boolean;
10 ActualColor: TBGRAPixel;
11 ActualTexCoord: TPointF;
12 end;
13
14 { TBGRAFace3D }
15
16 TBGRAFace3D = class(TInterfacedObject,IBGRAFace3D)
17 private
18 FVertices: packed array of TBGRAFaceVertexDescription;
19 FVertexCount: integer;
20 FTexture, FActualTexture: IBGRAScanner;
21 FMaterial: IBGRAMaterial3D;
22 FActualMaterial: TBGRAMaterial3D;
23 FMaterialName: string;
24 FParentTexture: boolean;
25 FViewNormal: TPoint3D_128;
26 FViewCenter: TPoint3D_128;
27 FObject3D : IBGRAObject3D;
28 FBiface: boolean;
29 FLightThroughFactor: single;
30 FLightThroughFactorOverride: boolean;
31 FCustomFlags: DWord;
32 function GetCustomFlags: DWord;
33 function GetVertexDescription(AIndex : integer): PBGRAFaceVertexDescription;
34 procedure SetCustomFlags(AValue: DWord);
35 procedure ComputeActualVertexColor(AIndex: integer);
36 procedure ComputeActualTexCoord(AMinIndex, AMaxIndex: integer);
37 procedure UpdateTexture;
38 public
39 function GetObject3D: IBGRAObject3D;
40 constructor Create(AObject3D: IBGRAObject3D; AVertices: array of IBGRAVertex3D);
41 destructor Destroy; override;
42 procedure ComputeVertexColors;
43 procedure UpdateMaterial;
44 procedure FlipFace;
45 function AddVertex(AVertex: IBGRAVertex3D): integer;
46 function GetParentTexture: boolean;
47 function GetTexture: IBGRAScanner;
48 function GetVertex(AIndex: Integer): IBGRAVertex3D;
49 function GetVertexColor(AIndex: Integer): TBGRAPixel;
50 function GetVertexColorOverride(AIndex: Integer): boolean;
51 function GetVertexCount: integer;
52 function GetNormal(AIndex: Integer): IBGRANormal3D;
53 function GetMaterial: IBGRAMaterial3D;
54 function GetMaterialName: string;
55 function GetTexCoord(AIndex: Integer): TPointF;
56 function GetTexCoordOverride(AIndex: Integer): boolean;
57 function GetViewNormal: TPoint3D;
58 function GetViewNormal_128: TPoint3D_128;
59 function GetViewCenter: TPoint3D;
60 function GetViewCenter_128: TPoint3D_128;
61 function GetViewCenterZ: single;
62 function GetBiface: boolean;
63 function GetLightThroughFactor: single;
64 function GetLightThroughFactorOverride: boolean;
65 procedure SetParentTexture(const AValue: boolean);
66 procedure SetTexture(const AValue: IBGRAScanner);
67 procedure SetColor(AColor: TBGRAPixel);
68 procedure SetVertexColor(AIndex: Integer; const AValue: TBGRAPixel);
69 procedure SetVertexColorOverride(AIndex: Integer; const AValue: boolean);
70 procedure SetTexCoord(AIndex: Integer; const AValue: TPointF);
71 procedure SetTexCoordOverride(AIndex: Integer; const AValue: boolean);
72 procedure SetBiface(const AValue: boolean);
73 procedure SetLightThroughFactor(const AValue: single);
74 procedure SetLightThroughFactorOverride(const AValue: boolean);
75 procedure SetVertex(AIndex: Integer; AValue: IBGRAVertex3D);
76 procedure SetNormal(AIndex: Integer; AValue: IBGRANormal3D);
77 procedure ComputeViewNormalAndCenter;
78 procedure SetMaterial(const AValue: IBGRAMaterial3D);
79 procedure SetMaterialName(const AValue: string);
80 function GetAsObject: TObject;
81 property Texture: IBGRAScanner read GetTexture write SetTexture;
82 property ParentTexture: boolean read GetParentTexture write SetParentTexture;
83 property VertexCount: integer read GetVertexCount;
84 property Vertex[AIndex: Integer]: IBGRAVertex3D read GetVertex write SetVertex;
85 property Normal[AIndex: Integer]: IBGRANormal3D read GetNormal write SetNormal;
86 property VertexColor[AIndex: Integer]: TBGRAPixel read GetVertexColor write SetVertexColor;
87 property VertexColorOverride[AIndex: Integer]: boolean read GetVertexColorOverride write SetVertexColorOverride;
88 property TexCoord[AIndex: Integer]: TPointF read GetTexCoord write SetTexCoord;
89 property TexCoordOverride[AIndex: Integer]: boolean read GetTexCoordOverride write SetTexCoordOverride;
90 property ViewNormal: TPoint3D read GetViewNormal;
91 property ViewNormal_128: TPoint3D_128 read GetViewNormal_128;
92 property ViewCenter: TPoint3D read GetViewCenter;
93 property ViewCenter_128: TPoint3D_128 read GetViewCenter_128;
94 property ViewCenterZ: single read GetViewCenterZ;
95 property Object3D: IBGRAObject3D read GetObject3D;
96 property Biface: boolean read GetBiface write SetBiface;
97 property LightThroughFactor: single read GetLightThroughFactor write SetLightThroughFactor;
98 property LightThroughFactorOverride: boolean read GetLightThroughFactorOverride write SetLightThroughFactorOverride;
99 property Material: IBGRAMaterial3D read GetMaterial write SetMaterial;
100 property ActualMaterial: TBGRAMaterial3D read FActualMaterial;
101 property ActualTexture: IBGRAScanner read FActualTexture;
102 property VertexDescription[AIndex : integer]: PBGRAFaceVertexDescription read GetVertexDescription;
103 property CustomFlags: DWord read GetCustomFlags write SetCustomFlags;
104 end;
105
106{ TBGRAFace3D }
107
108function TBGRAFace3D.GetVertexDescription(AIndex : integer
109 ): PBGRAFaceVertexDescription;
110begin
111 result := @FVertices[AIndex];
112end;
113
114function TBGRAFace3D.GetCustomFlags: DWord;
115begin
116 result := FCustomFlags;
117end;
118
119function TBGRAFace3D.GetNormal(AIndex: Integer): IBGRANormal3D;
120begin
121 result := FVertices[AIndex].Normal;
122end;
123
124procedure TBGRAFace3D.SetCustomFlags(AValue: DWord);
125begin
126 FCustomFlags:= AValue;
127end;
128
129procedure TBGRAFace3D.ComputeActualVertexColor(AIndex: integer);
130begin
131 with FVertices[AIndex] do
132 begin
133 if ColorOverride then
134 ActualColor := Color
135 else
136 if Vertex.ParentColor then
137 ActualColor := FObject3D.Color
138 else
139 ActualColor := Vertex.Color;
140 end;
141end;
142
143procedure TBGRAFace3D.ComputeActualTexCoord(AMinIndex, AMaxIndex: integer);
144var
145 i: Integer;
146 zoom: TPointF;
147 m: IBGRAMaterial3D;
148begin
149 m := ActualMaterial;
150 if m <> nil then zoom := m.TextureZoom
151 else zoom := PointF(1,1);
152 for i := AMinIndex to AMaxIndex do
153 with FVertices[i] do
154 begin
155 if TexCoordOverride then
156 ActualTexCoord := TexCoord
157 else
158 ActualTexCoord := Vertex.TexCoord;
159 ActualTexCoord.x *= zoom.x;
160 ActualTexCoord.y *= zoom.y;
161 end;
162end;
163
164procedure TBGRAFace3D.UpdateTexture;
165begin
166 if FParentTexture then
167 begin
168 FActualTexture := nil;
169 if FActualMaterial <> nil then
170 FActualTexture := FActualMaterial.GetTexture;
171 if FActualTexture = nil then
172 FActualTexture := FObject3D.Texture
173 end
174 else
175 FActualTexture := FTexture;
176end;
177
178procedure TBGRAFace3D.SetNormal(AIndex: Integer; AValue: IBGRANormal3D);
179begin
180 FVertices[AIndex].Normal := AValue;
181end;
182
183function TBGRAFace3D.GetObject3D: IBGRAObject3D;
184begin
185 result := FObject3D;
186end;
187
188constructor TBGRAFace3D.Create(AObject3D: IBGRAObject3D;
189 AVertices: array of IBGRAVertex3D);
190var
191 i: Integer;
192begin
193 FObject3D := AObject3D;
194 FBiface := false;
195 FParentTexture := True;
196 FLightThroughFactor:= 0;
197 FLightThroughFactorOverride:= false;
198
199 UpdateMaterial;
200
201 SetLength(FVertices, length(AVertices));
202 for i:= 0 to high(AVertices) do
203 AddVertex(AVertices[i]);
204end;
205
206destructor TBGRAFace3D.Destroy;
207begin
208 FMaterial := nil;
209 fillchar(FTexture,sizeof(FTexture),0);
210 fillchar(FActualTexture,sizeof(FActualTexture),0);
211 inherited Destroy;
212end;
213
214procedure TBGRAFace3D.ComputeVertexColors;
215var
216 i: Integer;
217begin
218 for i := 0 to FVertexCount-1 do
219 ComputeActualVertexColor(i);
220end;
221
222procedure TBGRAFace3D.UpdateMaterial;
223begin
224 if Material <> nil then
225 FActualMaterial := TBGRAMaterial3D(Material.GetAsObject)
226 else if FObject3D.Material <> nil then
227 FActualMaterial := TBGRAMaterial3D(FObject3D.Material.GetAsObject)
228 else if TBGRAScene3D(FObject3D.Scene).DefaultMaterial <> nil then
229 FActualMaterial := TBGRAMaterial3D(TBGRAScene3D(FObject3D.Scene).DefaultMaterial.GetAsObject);
230
231 UpdateTexture;
232
233 ComputeActualTexCoord(0,FVertexCount-1);
234end;
235
236procedure TBGRAFace3D.FlipFace;
237var i: integer;
238 temp: TBGRAFaceVertexDescription;
239begin
240 for i := 0 to (VertexCount div 2)-1 do
241 begin
242 temp := FVertices[i];
243 FVertices[i] := FVertices[VertexCount-1-i];
244 FVertices[VertexCount-1-i] := temp;
245 end;
246end;
247
248function TBGRAFace3D.AddVertex(AVertex: IBGRAVertex3D): integer;
249begin
250 if FVertexCount = length(FVertices) then
251 setlength(FVertices, FVertexCount*2+3);
252 result := FVertexCount;
253 with FVertices[result] do
254 begin
255 Color := BGRAWhite;
256 ColorOverride := false;
257 TexCoord := PointF(0,0);
258 TexCoordOverride := false;
259 Vertex := AVertex;
260 Normal := nil;
261 end;
262 ComputeActualVertexColor(result);
263 ComputeActualTexCoord(result,result);
264 inc(FVertexCount);
265end;
266
267function TBGRAFace3D.GetParentTexture: boolean;
268begin
269 result := FParentTexture;
270end;
271
272function TBGRAFace3D.GetTexture: IBGRAScanner;
273begin
274 result := FTexture;
275end;
276
277function TBGRAFace3D.GetVertex(AIndex: Integer): IBGRAVertex3D;
278begin
279 if (AIndex < 0) or (AIndex >= FVertexCount) then
280 raise Exception.Create('Index out of bounds');
281 result := FVertices[AIndex].Vertex;
282end;
283
284procedure TBGRAFace3D.SetVertex(AIndex: Integer; AValue: IBGRAVertex3D);
285begin
286 if (AIndex < 0) or (AIndex >= FVertexCount) then
287 raise Exception.Create('Index out of bounds');
288 FVertices[AIndex].Vertex := AValue;
289 ComputeActualVertexColor(AIndex);
290end;
291
292function TBGRAFace3D.GetVertexColor(AIndex: Integer): TBGRAPixel;
293begin
294 if (AIndex < 0) or (AIndex >= FVertexCount) then
295 raise Exception.Create('Index out of bounds');
296 result := FVertices[AIndex].ActualColor;
297end;
298
299function TBGRAFace3D.GetVertexColorOverride(AIndex: Integer): boolean;
300begin
301 if (AIndex < 0) or (AIndex >= FVertexCount) then
302 raise Exception.Create('Index out of bounds');
303 result := FVertices[AIndex].ColorOverride;
304end;
305
306function TBGRAFace3D.GetVertexCount: integer;
307begin
308 result := FVertexCount;
309end;
310
311function TBGRAFace3D.GetMaterial: IBGRAMaterial3D;
312begin
313 result := FMaterial;
314end;
315
316function TBGRAFace3D.GetMaterialName: string;
317begin
318 result := FMaterialName;
319end;
320
321procedure TBGRAFace3D.SetParentTexture(const AValue: boolean);
322begin
323 FParentTexture := AValue;
324 UpdateTexture;
325end;
326
327procedure TBGRAFace3D.SetTexture(const AValue: IBGRAScanner);
328begin
329 FTexture := AValue;
330 FParentTexture := false;
331 UpdateTexture;
332end;
333
334procedure TBGRAFace3D.SetColor(AColor: TBGRAPixel);
335var i: integer;
336begin
337 for i := 0 to GetVertexCount-1 do
338 SetVertexColor(i,AColor);
339end;
340
341procedure TBGRAFace3D.SetVertexColor(AIndex: Integer; const AValue: TBGRAPixel
342 );
343begin
344 if (AIndex < 0) or (AIndex >= FVertexCount) then
345 raise Exception.Create('Index out of bounds');
346 with FVertices[AIndex] do
347 begin
348 Color := AValue;
349 ColorOverride := true;
350 end;
351 ComputeActualVertexColor(AIndex);
352end;
353
354procedure TBGRAFace3D.SetVertexColorOverride(AIndex: Integer;
355 const AValue: boolean);
356begin
357 if (AIndex < 0) or (AIndex >= FVertexCount) then
358 raise Exception.Create('Index out of bounds');
359 FVertices[AIndex].ColorOverride := AValue;
360 ComputeActualVertexColor(AIndex);
361end;
362
363function TBGRAFace3D.GetTexCoord(AIndex: Integer): TPointF;
364begin
365 if (AIndex < 0) or (AIndex >= FVertexCount) then
366 raise Exception.Create('Index out of bounds');
367 result := FVertices[AIndex].TexCoord;
368end;
369
370function TBGRAFace3D.GetTexCoordOverride(AIndex: Integer): boolean;
371begin
372 if (AIndex < 0) or (AIndex >= FVertexCount) then
373 raise Exception.Create('Index out of bounds');
374 result := FVertices[AIndex].TexCoordOverride;
375end;
376
377procedure TBGRAFace3D.SetTexCoord(AIndex: Integer; const AValue: TPointF);
378begin
379 if (AIndex < 0) or (AIndex >= FVertexCount) then
380 raise Exception.Create('Index out of bounds');
381 FVertices[AIndex].TexCoord := AValue;
382 FVertices[AIndex].TexCoordOverride := true;
383 ComputeActualTexCoord(AIndex, AIndex);
384end;
385
386procedure TBGRAFace3D.SetTexCoordOverride(AIndex: Integer; const AValue: boolean
387 );
388begin
389 if (AIndex < 0) or (AIndex >= FVertexCount) then
390 raise Exception.Create('Index out of bounds');
391 FVertices[AIndex].TexCoordOverride := AValue;
392end;
393
394function TBGRAFace3D.GetViewNormal: TPoint3D;
395begin
396 result := Point3D(FViewNormal);
397end;
398
399function TBGRAFace3D.GetViewNormal_128: TPoint3D_128;
400begin
401 result := FViewNormal;
402end;
403
404function TBGRAFace3D.GetViewCenter: TPoint3D;
405begin
406 result := Point3D(FViewCenter);
407end;
408
409function TBGRAFace3D.GetViewCenter_128: TPoint3D_128;
410begin
411 result := FViewCenter;
412end;
413
414function TBGRAFace3D.GetViewCenterZ: single;
415begin
416 result := FViewCenter.Z;
417end;
418
419function TBGRAFace3D.GetBiface: boolean;
420begin
421 result := FBiface;
422end;
423
424procedure TBGRAFace3D.SetBiface(const AValue: boolean);
425begin
426 FBiface := AValue;
427end;
428
429function TBGRAFace3D.GetLightThroughFactor: single;
430begin
431 result := FLightThroughFactor;
432end;
433
434function TBGRAFace3D.GetLightThroughFactorOverride: boolean;
435begin
436 result := FLightThroughFactorOverride;
437end;
438
439procedure TBGRAFace3D.SetLightThroughFactor(const AValue: single);
440begin
441 if AValue < 0 then
442 FLightThroughFactor := 0
443 else
444 FLightThroughFactor:= AValue;
445 FLightThroughFactorOverride := true;
446end;
447
448procedure TBGRAFace3D.SetLightThroughFactorOverride(const AValue: boolean);
449begin
450 FLightThroughFactorOverride := AValue;
451end;
452
453procedure TBGRAFace3D.ComputeViewNormalAndCenter;
454var v1,v2: TPoint3D_128;
455 i: Integer;
456 p0,p1,p2: IBGRAVertex3D;
457begin
458 if FVertexCount < 3 then
459 ClearPoint3D_128(FViewNormal)
460 else
461 begin
462 p0 := FVertices[0].Vertex;
463 p1 := FVertices[1].Vertex;
464 p2 := FVertices[2].Vertex;
465 v1 := p1.ViewCoord_128 - p0.ViewCoord_128;
466 v2 := p2.ViewCoord_128 - p1.ViewCoord_128;
467 VectProduct3D_128(v2,v1,FViewNormal);
468 Normalize3D_128(FViewNormal);
469 for i := 0 to FVertexCount-1 do
470 FVertices[i].Vertex.AddViewNormal(FViewNormal);
471 end;
472 ClearPoint3D_128(FViewCenter);
473 if FVertexCount > 0 then
474 begin
475 for i := 0 to FVertexCount-1 do
476 FViewCenter += FVertices[i].Vertex.ViewCoord_128;
477 FViewCenter *= 1/FVertexCount;
478 end;
479end;
480
481procedure TBGRAFace3D.SetMaterial(const AValue: IBGRAMaterial3D);
482begin
483 if AValue <> FMaterial then
484 begin
485 FMaterial := AValue;
486 UpdateMaterial;
487 end;
488end;
489
490procedure TBGRAFace3D.SetMaterialName(const AValue: string);
491begin
492 if AValue <> FMaterialName then
493 begin
494 FMaterialName := AValue;
495 TBGRAScene3D(FObject3D.Scene).UseMaterial(FMaterialName, self);
496 end;
497end;
498
499function TBGRAFace3D.GetAsObject: TObject;
500begin
501 result := self;
502end;
503
504
Note: See TracBrowser for help on using the repository browser.