1 | type
|
---|
2 | { TBGRAPart3D }
|
---|
3 |
|
---|
4 | TBGRAPart3D = class(TInterfacedObject,IBGRAPart3D)
|
---|
5 | private
|
---|
6 | FVertices: array of IBGRAVertex3D;
|
---|
7 | FVertexCount: integer;
|
---|
8 | FNormals: array of IBGRANormal3D;
|
---|
9 | FNormalCount: integer;
|
---|
10 | FMatrix: TMatrix3D;
|
---|
11 | FParts: array of IBGRAPart3D;
|
---|
12 | FPartCount: integer;
|
---|
13 | FContainer: IBGRAPart3D;
|
---|
14 | FCoordPool: TBGRACoordPool3D;
|
---|
15 | FNormalPool: TBGRANormalPool3D;
|
---|
16 | FObject3D: TBGRAObject3D;
|
---|
17 | public
|
---|
18 | constructor Create(AObject3D: TBGRAObject3D; AContainer: IBGRAPart3D);
|
---|
19 | destructor Destroy; override;
|
---|
20 | procedure Clear(ARecursive: boolean);
|
---|
21 | function Add(x,y,z: single): IBGRAVertex3D; overload;
|
---|
22 | function Add(pt: TPoint3D): IBGRAVertex3D; overload;
|
---|
23 | function Add(pt: TPoint3D; normal: TPoint3D): IBGRAVertex3D; overload;
|
---|
24 | function Add(pt: TPoint3D_128): IBGRAVertex3D; overload;
|
---|
25 | function Add(pt: TPoint3D_128; normal: TPoint3D_128): IBGRAVertex3D; overload;
|
---|
26 | function Add(const coords: array of single): arrayOfIBGRAVertex3D; overload;
|
---|
27 | function Add(const pts: array of TPoint3D): arrayOfIBGRAVertex3D; overload;
|
---|
28 | function Add(const pts: array of TPoint3D_128): arrayOfIBGRAVertex3D; overload;
|
---|
29 | procedure Add(const pts: array of IBGRAVertex3D); overload;
|
---|
30 | procedure Add(AVertex: IBGRAVertex3D); overload;
|
---|
31 | function AddNormal(x,y,z: single): IBGRANormal3D; overload;
|
---|
32 | function AddNormal(pt: TPoint3D): IBGRANormal3D; overload;
|
---|
33 | function AddNormal(pt: TPoint3D_128): IBGRANormal3D; overload;
|
---|
34 | procedure AddNormal(ANormal: IBGRANormal3D); overload;
|
---|
35 | procedure RemoveVertex(Index: integer);
|
---|
36 | procedure RemoveNormal(Index: integer);
|
---|
37 | function GetBoundingBox: TBox3D;
|
---|
38 | function GetRadius: single;
|
---|
39 | function GetMatrix: TMatrix3D;
|
---|
40 | function GetPart(AIndex: Integer): IBGRAPart3D;
|
---|
41 | function GetPartCount: integer;
|
---|
42 | function GetVertex(AIndex: Integer): IBGRAVertex3D;
|
---|
43 | function GetVertexCount: integer;
|
---|
44 | function GetNormal(AIndex: Integer): IBGRANormal3D;
|
---|
45 | function GetNormalCount: integer;
|
---|
46 | function GetTotalVertexCount: integer;
|
---|
47 | function GetTotalNormalCount: integer;
|
---|
48 | function GetContainer: IBGRAPart3D;
|
---|
49 | procedure SetVertex(AIndex: Integer; AValue: IBGRAVertex3D);
|
---|
50 | procedure SetNormal(AIndex: Integer; AValue: IBGRANormal3D);
|
---|
51 | procedure ResetTransform;
|
---|
52 | procedure Translate(x,y,z: single; Before: boolean = true); overload;
|
---|
53 | procedure Translate(ofs: TPoint3D; Before: boolean = true); overload;
|
---|
54 | procedure Scale(size: single; Before: boolean = true); overload;
|
---|
55 | procedure Scale(x,y,z: single; Before: boolean = true); overload;
|
---|
56 | procedure Scale(size: TPoint3D; Before: boolean = true); overload;
|
---|
57 | procedure RotateXDeg(angle: single; Before: boolean = true);
|
---|
58 | procedure RotateYDeg(angle: single; Before: boolean = true);
|
---|
59 | procedure RotateZDeg(angle: single; Before: boolean = true);
|
---|
60 | procedure RotateXRad(angle: single; Before: boolean = true);
|
---|
61 | procedure RotateYRad(angle: single; Before: boolean = true);
|
---|
62 | procedure RotateZRad(angle: single; Before: boolean = true);
|
---|
63 | procedure SetMatrix(const AValue: TMatrix3D);
|
---|
64 | procedure ComputeWithMatrix(const AMatrix: TMatrix3D; const AProjection: TProjection3D);
|
---|
65 | function ComputeCoordinate(var ASceneCoord: TPoint3D_128; const AProjection: TProjection3D): TPointF;
|
---|
66 | procedure NormalizeViewNormal;
|
---|
67 | function CreatePart: IBGRAPart3D;
|
---|
68 | procedure LookAt(ALookWhere,ATopDir: TPoint3D);
|
---|
69 | procedure RemoveUnusedVertices;
|
---|
70 | function IndexOf(AVertex: IBGRAVertex3D): integer;
|
---|
71 | procedure ForEachVertex(ACallback: TVertex3DCallback);
|
---|
72 | end;
|
---|
73 |
|
---|
74 | { TBGRAPart3D }
|
---|
75 |
|
---|
76 | procedure TBGRAPart3D.LookAt(ALookWhere,ATopDir: TPoint3D);
|
---|
77 | var ZDir, XDir, YDir: TPoint3D_128;
|
---|
78 | ViewPoint: TPoint3D_128;
|
---|
79 | CurPart: IBGRAPart3D;
|
---|
80 | ComposedMatrix: TMatrix3D;
|
---|
81 | begin
|
---|
82 | YDir := -Point3D_128(ATopDir);
|
---|
83 | if IsPoint3D_128_Zero(YDir) then exit;
|
---|
84 | Normalize3D_128(YDir);
|
---|
85 |
|
---|
86 | ComposedMatrix := FMatrix;
|
---|
87 | CurPart := self.FContainer;
|
---|
88 | while CurPart <> nil do
|
---|
89 | begin
|
---|
90 | ComposedMatrix := CurPart.Matrix*ComposedMatrix;
|
---|
91 | CurPart := CurPart.Container;
|
---|
92 | end;
|
---|
93 | ViewPoint := ComposedMatrix*Point3D_128_Zero;
|
---|
94 |
|
---|
95 | ZDir := Point3D_128(ALookWhere)-ViewPoint;
|
---|
96 | if IsPoint3D_128_Zero(ZDir) then exit;
|
---|
97 | Normalize3D_128(ZDir);
|
---|
98 |
|
---|
99 | VectProduct3D_128(YDir,ZDir,XDir);
|
---|
100 | VectProduct3D_128(ZDir,XDir,YDir); //correct Y dir
|
---|
101 |
|
---|
102 | FMatrix := Matrix3D(XDir,YDir,ZDir,ViewPoint);
|
---|
103 | ComposedMatrix := MatrixIdentity3D;
|
---|
104 | CurPart := self.FContainer;
|
---|
105 | while CurPart <> nil do
|
---|
106 | begin
|
---|
107 | ComposedMatrix := CurPart.Matrix*ComposedMatrix;
|
---|
108 | CurPart := CurPart.Container;
|
---|
109 | end;
|
---|
110 | FMatrix := MatrixInverse3D(ComposedMatrix)*FMatrix;
|
---|
111 | end;
|
---|
112 |
|
---|
113 | procedure TBGRAPart3D.RemoveUnusedVertices;
|
---|
114 | var
|
---|
115 | i: Integer;
|
---|
116 | begin
|
---|
117 | for i := FVertexCount-1 downto 0 do
|
---|
118 | if FVertices[i].Usage <= 2 then RemoveVertex(i);
|
---|
119 | for i := 0 to FPartCount-1 do
|
---|
120 | FParts[i].RemoveUnusedVertices;
|
---|
121 | end;
|
---|
122 |
|
---|
123 | function TBGRAPart3D.IndexOf(AVertex: IBGRAVertex3D): integer;
|
---|
124 | var i: integer;
|
---|
125 | begin
|
---|
126 | for i := 0 to FVertexCount-1 do
|
---|
127 | if FVertices[i] = AVertex then
|
---|
128 | begin
|
---|
129 | result := i;
|
---|
130 | exit;
|
---|
131 | end;
|
---|
132 | result := -1;
|
---|
133 | end;
|
---|
134 |
|
---|
135 | procedure TBGRAPart3D.ForEachVertex(ACallback: TVertex3DCallback);
|
---|
136 | var i: integer;
|
---|
137 | begin
|
---|
138 | for i := 0 to FVertexCount-1 do
|
---|
139 | ACallback(FVertices[i]);
|
---|
140 | end;
|
---|
141 |
|
---|
142 | procedure TBGRAPart3D.Add(AVertex: IBGRAVertex3D);
|
---|
143 | begin
|
---|
144 | if FVertexCount = length(FVertices) then
|
---|
145 | setlength(FVertices, FVertexCount*2+3);
|
---|
146 | FVertices[FVertexCount] := AVertex;
|
---|
147 | inc(FVertexCount);
|
---|
148 | end;
|
---|
149 |
|
---|
150 | function TBGRAPart3D.AddNormal(x, y, z: single): IBGRANormal3D;
|
---|
151 | begin
|
---|
152 | if not Assigned(FNormalPool) then FNormalPool := TBGRANormalPool3D.Create(4);
|
---|
153 | result := TBGRANormal3D.Create(FNormalPool,Point3D_128(x,y,z));
|
---|
154 | AddNormal(result);
|
---|
155 | end;
|
---|
156 |
|
---|
157 | function TBGRAPart3D.AddNormal(pt: TPoint3D): IBGRANormal3D;
|
---|
158 | begin
|
---|
159 | if not Assigned(FNormalPool) then FNormalPool := TBGRANormalPool3D.Create(4);
|
---|
160 | result := TBGRANormal3D.Create(FNormalPool,pt);
|
---|
161 | AddNormal(result);
|
---|
162 | end;
|
---|
163 |
|
---|
164 | function TBGRAPart3D.AddNormal(pt: TPoint3D_128): IBGRANormal3D;
|
---|
165 | begin
|
---|
166 | if not Assigned(FNormalPool) then FNormalPool := TBGRANormalPool3D.Create(4);
|
---|
167 | result := TBGRANormal3D.Create(FNormalPool,pt);
|
---|
168 | AddNormal(result);
|
---|
169 | end;
|
---|
170 |
|
---|
171 | procedure TBGRAPart3D.AddNormal(ANormal: IBGRANormal3D);
|
---|
172 | begin
|
---|
173 | if FNormalCount = length(FNormals) then
|
---|
174 | setlength(FNormals, FNormalCount*2+3);
|
---|
175 | FNormals[FNormalCount] := ANormal;
|
---|
176 | inc(FNormalCount);
|
---|
177 | end;
|
---|
178 |
|
---|
179 | procedure TBGRAPart3D.RemoveVertex(Index: integer);
|
---|
180 | var i: integer;
|
---|
181 | begin
|
---|
182 | if (Index >= 0) and (Index < FVertexCount) then
|
---|
183 | begin
|
---|
184 | for i := Index to FVertexCount-2 do
|
---|
185 | FVertices[i] := FVertices[i+1];
|
---|
186 | FVertices[FVertexCount-1] := nil;
|
---|
187 | dec(FVertexCount);
|
---|
188 | end;
|
---|
189 | end;
|
---|
190 |
|
---|
191 | procedure TBGRAPart3D.RemoveNormal(Index: integer);
|
---|
192 | var i: integer;
|
---|
193 | begin
|
---|
194 | if (Index >= 0) and (Index < FNormalCount) then
|
---|
195 | begin
|
---|
196 | for i := Index to FNormalCount-2 do
|
---|
197 | FNormals[i] := FNormals[i+1];
|
---|
198 | FNormals[FNormalCount-1] := nil;
|
---|
199 | dec(FNormalCount);
|
---|
200 | end;
|
---|
201 | end;
|
---|
202 |
|
---|
203 | function TBGRAPart3D.GetRadius: single;
|
---|
204 | var i: integer;
|
---|
205 | pt: TPoint3D_128;
|
---|
206 | d: single;
|
---|
207 | begin
|
---|
208 | result := 0;
|
---|
209 | for i := 0 to GetVertexCount-1 do
|
---|
210 | begin
|
---|
211 | pt := GetVertex(i).SceneCoord_128;
|
---|
212 | d:= sqrt(DotProduct3D_128(pt,pt));
|
---|
213 | if d > result then result := d;
|
---|
214 | end;
|
---|
215 | end;
|
---|
216 |
|
---|
217 | constructor TBGRAPart3D.Create(AObject3D: TBGRAObject3D; AContainer: IBGRAPart3D);
|
---|
218 | begin
|
---|
219 | FObject3D := AObject3D;
|
---|
220 | FContainer := AContainer;
|
---|
221 | FMatrix := MatrixIdentity3D;
|
---|
222 | FCoordPool := TBGRACoordPool3D.Create(4);
|
---|
223 | FNormalPool := nil;
|
---|
224 | FNormalCount:= 0;
|
---|
225 | FVertexCount := 0;
|
---|
226 | end;
|
---|
227 |
|
---|
228 | destructor TBGRAPart3D.Destroy;
|
---|
229 | begin
|
---|
230 | FVertices := nil;
|
---|
231 | FVertexCount := 0;
|
---|
232 | if FCoordPool.UsedCapacity > 0 then
|
---|
233 | raise Exception.Create('Coordinate pool still used. Please set vertex references to nil before destroying the scene.');
|
---|
234 | FreeAndNil(FCoordPool);
|
---|
235 | if Assigned(FNormalPool) then
|
---|
236 | begin
|
---|
237 | if FNormalPool.UsedCapacity > 0 then
|
---|
238 | raise Exception.Create('Normal pool still used');
|
---|
239 | FreeAndNil(FNormalPool);
|
---|
240 | end;
|
---|
241 | inherited Destroy;
|
---|
242 | end;
|
---|
243 |
|
---|
244 | procedure TBGRAPart3D.Clear(ARecursive: boolean);
|
---|
245 | var i: integer;
|
---|
246 | begin
|
---|
247 | FVertices := nil;
|
---|
248 | FVertexCount := 0;
|
---|
249 | FNormals := nil;
|
---|
250 | FNormalCount := 0;
|
---|
251 | if ARecursive then
|
---|
252 | begin
|
---|
253 | for i := 0 to FPartCount-1 do
|
---|
254 | FParts[i].Clear(ARecursive);
|
---|
255 | FParts := nil;
|
---|
256 | FPartCount := 0;
|
---|
257 | end;
|
---|
258 | end;
|
---|
259 |
|
---|
260 | function TBGRAPart3D.Add(x, y, z: single): IBGRAVertex3D;
|
---|
261 | begin
|
---|
262 | result := TBGRAVertex3D.Create(FObject3D,FCoordPool,Point3D(x,y,z));
|
---|
263 | Add(result);
|
---|
264 | end;
|
---|
265 |
|
---|
266 | function TBGRAPart3D.Add(pt: TPoint3D): IBGRAVertex3D;
|
---|
267 | begin
|
---|
268 | result := TBGRAVertex3D.Create(FObject3D,FCoordPool,pt);
|
---|
269 | Add(result);
|
---|
270 | end;
|
---|
271 |
|
---|
272 | function TBGRAPart3D.Add(pt: TPoint3D; normal: TPoint3D): IBGRAVertex3D;
|
---|
273 | begin
|
---|
274 | result := TBGRAVertex3D.Create(FObject3D,FCoordPool,pt);
|
---|
275 | result.CustomNormal := normal;
|
---|
276 | Add(result);
|
---|
277 | end;
|
---|
278 |
|
---|
279 | function TBGRAPart3D.Add(pt: TPoint3D_128): IBGRAVertex3D;
|
---|
280 | begin
|
---|
281 | result := TBGRAVertex3D.Create(FObject3D,FCoordPool,pt);
|
---|
282 | Add(result);
|
---|
283 | end;
|
---|
284 |
|
---|
285 | function TBGRAPart3D.Add(pt: TPoint3D_128; normal: TPoint3D_128): IBGRAVertex3D;
|
---|
286 | begin
|
---|
287 | result := TBGRAVertex3D.Create(FObject3D,FCoordPool,pt);
|
---|
288 | result.CustomNormal := Point3D(normal);
|
---|
289 | Add(result);
|
---|
290 | end;
|
---|
291 |
|
---|
292 | function TBGRAPart3D.Add(const coords: array of single
|
---|
293 | ): arrayOfIBGRAVertex3D;
|
---|
294 | var pts: array of TPoint3D;
|
---|
295 | CoordsIdx: integer;
|
---|
296 | i: Integer;
|
---|
297 | begin
|
---|
298 | if length(coords) mod 3 <> 0 then
|
---|
299 | raise exception.Create('Array size must be a multiple of 3');
|
---|
300 | setlength(pts, length(coords) div 3);
|
---|
301 | coordsIdx := 0;
|
---|
302 | for i := 0 to high(pts) do
|
---|
303 | begin
|
---|
304 | pts[i] := Point3D(coords[CoordsIdx],coords[CoordsIdx+1],coords[CoordsIdx+2]);
|
---|
305 | inc(coordsIdx,3);
|
---|
306 | end;
|
---|
307 | result := Add(pts);
|
---|
308 | end;
|
---|
309 |
|
---|
310 | function TBGRAPart3D.Add(const pts: array of TPoint3D): arrayOfIBGRAVertex3D;
|
---|
311 | var
|
---|
312 | i: Integer;
|
---|
313 | begin
|
---|
314 | setlength(result, length(pts));
|
---|
315 | for i := 0 to high(pts) do
|
---|
316 | result[i] := TBGRAVertex3D.Create(FObject3D,FCoordPool,pts[i]);
|
---|
317 | Add(result);
|
---|
318 | end;
|
---|
319 |
|
---|
320 | function TBGRAPart3D.Add(const pts: array of TPoint3D_128
|
---|
321 | ): arrayOfIBGRAVertex3D;
|
---|
322 | var
|
---|
323 | i: Integer;
|
---|
324 | begin
|
---|
325 | setlength(result, length(pts));
|
---|
326 | for i := 0 to high(pts) do
|
---|
327 | result[i] := TBGRAVertex3D.Create(FObject3D,FCoordPool,pts[i]);
|
---|
328 | Add(result);
|
---|
329 | end;
|
---|
330 |
|
---|
331 | procedure TBGRAPart3D.Add(const pts: array of IBGRAVertex3D);
|
---|
332 | var
|
---|
333 | i: Integer;
|
---|
334 | begin
|
---|
335 | if FVertexCount + length(pts) > length(FVertices) then
|
---|
336 | setlength(FVertices, (FVertexCount*2 + length(pts))+1);
|
---|
337 | for i := 0 to high(pts) do
|
---|
338 | begin
|
---|
339 | FVertices[FVertexCount] := pts[i];
|
---|
340 | inc(FVertexCount);
|
---|
341 | end;
|
---|
342 | end;
|
---|
343 |
|
---|
344 | function TBGRAPart3D.GetBoundingBox: TBox3D;
|
---|
345 | var i: integer;
|
---|
346 | pt: TPoint3D_128;
|
---|
347 | begin
|
---|
348 | if GetVertexCount > 0 then
|
---|
349 | begin
|
---|
350 | result.min := GetVertex(0).SceneCoord;
|
---|
351 | result.max := result.min;
|
---|
352 | end else
|
---|
353 | begin
|
---|
354 | result.min := Point3D(0,0,0);
|
---|
355 | result.max := Point3D(0,0,0);
|
---|
356 | exit;
|
---|
357 | end;
|
---|
358 | for i := 1 to GetVertexCount-1 do
|
---|
359 | begin
|
---|
360 | pt := GetVertex(i).SceneCoord_128;
|
---|
361 | if pt.x < result.min.x then result.min.x := pt.x else
|
---|
362 | if pt.x > result.max.x then result.max.x := pt.x;
|
---|
363 | if pt.y < result.min.y then result.min.y := pt.y else
|
---|
364 | if pt.y > result.max.y then result.max.y := pt.y;
|
---|
365 | if pt.z < result.min.z then result.min.z := pt.z else
|
---|
366 | if pt.z > result.max.z then result.max.z := pt.z;
|
---|
367 | end;
|
---|
368 | end;
|
---|
369 |
|
---|
370 | function TBGRAPart3D.GetMatrix: TMatrix3D;
|
---|
371 | begin
|
---|
372 | result := FMatrix;
|
---|
373 | end;
|
---|
374 |
|
---|
375 | function TBGRAPart3D.GetPart(AIndex: Integer): IBGRAPart3D;
|
---|
376 | begin
|
---|
377 | if (AIndex < 0) or (AIndex >= FPartCount) then
|
---|
378 | raise ERangeError.Create('Index of out bounds');
|
---|
379 | result := FParts[AIndex];
|
---|
380 | end;
|
---|
381 |
|
---|
382 | function TBGRAPart3D.GetPartCount: integer;
|
---|
383 | begin
|
---|
384 | result := FPartCount;
|
---|
385 | end;
|
---|
386 |
|
---|
387 | function TBGRAPart3D.GetVertex(AIndex: Integer): IBGRAVertex3D;
|
---|
388 | begin
|
---|
389 | if (AIndex < 0) or (AIndex >= FVertexCount) then
|
---|
390 | raise ERangeError.Create('Index of out bounds');
|
---|
391 | result := FVertices[AIndex];
|
---|
392 | end;
|
---|
393 |
|
---|
394 | function TBGRAPart3D.GetVertexCount: integer;
|
---|
395 | begin
|
---|
396 | result := FVertexCount;
|
---|
397 | end;
|
---|
398 |
|
---|
399 | function TBGRAPart3D.GetNormal(AIndex: Integer): IBGRANormal3D;
|
---|
400 | begin
|
---|
401 | if (AIndex < 0) or (AIndex >= FNormalCount) then
|
---|
402 | raise ERangeError.Create('Index of out bounds');
|
---|
403 | result := FNormals[AIndex];
|
---|
404 | end;
|
---|
405 |
|
---|
406 | function TBGRAPart3D.GetNormalCount: integer;
|
---|
407 | begin
|
---|
408 | result := FNormalCount;
|
---|
409 | end;
|
---|
410 |
|
---|
411 | function TBGRAPart3D.GetTotalVertexCount: integer;
|
---|
412 | var i: integer;
|
---|
413 | begin
|
---|
414 | result := GetVertexCount;
|
---|
415 | for i := 0 to GetPartCount-1 do
|
---|
416 | result += GetPart(i).GetTotalVertexCount;
|
---|
417 | end;
|
---|
418 |
|
---|
419 | function TBGRAPart3D.GetTotalNormalCount: integer;
|
---|
420 | var i: integer;
|
---|
421 | begin
|
---|
422 | result := GetNormalCount;
|
---|
423 | for i := 0 to GetPartCount-1 do
|
---|
424 | result += GetPart(i).GetTotalNormalCount;
|
---|
425 | end;
|
---|
426 |
|
---|
427 | procedure TBGRAPart3D.ResetTransform;
|
---|
428 | begin
|
---|
429 | FMatrix := MatrixIdentity3D;
|
---|
430 | end;
|
---|
431 |
|
---|
432 | procedure TBGRAPart3D.Scale(size: single; Before: boolean = true);
|
---|
433 | begin
|
---|
434 | Scale(size,size,size,Before);
|
---|
435 | end;
|
---|
436 |
|
---|
437 | procedure TBGRAPart3D.Scale(x, y, z: single; Before: boolean = true);
|
---|
438 | begin
|
---|
439 | Scale(Point3D(x,y,z),Before);
|
---|
440 | end;
|
---|
441 |
|
---|
442 | procedure TBGRAPart3D.Scale(size: TPoint3D; Before: boolean = true);
|
---|
443 | begin
|
---|
444 | if Before then
|
---|
445 | FMatrix *= MatrixScale3D(size)
|
---|
446 | else
|
---|
447 | FMatrix := MatrixScale3D(size)*FMatrix;
|
---|
448 | end;
|
---|
449 |
|
---|
450 | procedure TBGRAPart3D.RotateXDeg(angle: single; Before: boolean = true);
|
---|
451 | begin
|
---|
452 | RotateXRad(-angle*Pi/180, Before);
|
---|
453 | end;
|
---|
454 |
|
---|
455 | procedure TBGRAPart3D.RotateYDeg(angle: single; Before: boolean = true);
|
---|
456 | begin
|
---|
457 | RotateYRad(-angle*Pi/180, Before);
|
---|
458 | end;
|
---|
459 |
|
---|
460 | procedure TBGRAPart3D.RotateZDeg(angle: single; Before: boolean = true);
|
---|
461 | begin
|
---|
462 | RotateZRad(-angle*Pi/180, Before);
|
---|
463 | end;
|
---|
464 |
|
---|
465 | procedure TBGRAPart3D.RotateXRad(angle: single; Before: boolean = true);
|
---|
466 | begin
|
---|
467 | if Before then
|
---|
468 | FMatrix *= MatrixRotateX(angle)
|
---|
469 | else
|
---|
470 | FMatrix := MatrixRotateX(angle) * FMatrix;
|
---|
471 | end;
|
---|
472 |
|
---|
473 | procedure TBGRAPart3D.RotateYRad(angle: single; Before: boolean = true);
|
---|
474 | begin
|
---|
475 | if Before then
|
---|
476 | FMatrix *= MatrixRotateY(angle)
|
---|
477 | else
|
---|
478 | FMatrix := MatrixRotateY(angle) * FMatrix;
|
---|
479 | end;
|
---|
480 |
|
---|
481 | procedure TBGRAPart3D.RotateZRad(angle: single; Before: boolean = true);
|
---|
482 | begin
|
---|
483 | if Before then
|
---|
484 | FMatrix *= MatrixRotateZ(angle)
|
---|
485 | else
|
---|
486 | FMatrix := MatrixRotateZ(angle) * FMatrix;
|
---|
487 | end;
|
---|
488 |
|
---|
489 | procedure TBGRAPart3D.SetMatrix(const AValue: TMatrix3D);
|
---|
490 | begin
|
---|
491 | FMatrix := AValue;
|
---|
492 | end;
|
---|
493 |
|
---|
494 | {$PUSH}{$OPTIMIZATION OFF} //avoids Internal error 2012090607
|
---|
495 | procedure TBGRAPart3D.ComputeWithMatrix(const AMatrix: TMatrix3D; const AProjection: TProjection3D);
|
---|
496 | var
|
---|
497 | i: Integer;
|
---|
498 | Composed: TMatrix3D;
|
---|
499 | begin
|
---|
500 | Composed := AMatrix* self.FMatrix;
|
---|
501 | FCoordPool.ComputeWithMatrix(Composed, AProjection);
|
---|
502 | if Assigned(FNormalPool) then FNormalPool.ComputeWithMatrix(Composed);
|
---|
503 | for i := 0 to FPartCount-1 do
|
---|
504 | FParts[i].ComputeWithMatrix(Composed,AProjection);
|
---|
505 | end;
|
---|
506 | {$POP}
|
---|
507 |
|
---|
508 | function TBGRAPart3D.ComputeCoordinate(var ASceneCoord: TPoint3D_128; const AProjection: TProjection3D): TPointF;
|
---|
509 | var part: IBGRAPart3D;
|
---|
510 | newViewCoord: TPoint3D_128;
|
---|
511 | InvZ: single;
|
---|
512 | begin
|
---|
513 | newViewCoord := FMatrix * ASceneCoord;
|
---|
514 | part := FContainer;
|
---|
515 | while part <> nil do
|
---|
516 | begin
|
---|
517 | newViewCoord := part.Matrix * newViewCoord;
|
---|
518 | part := part.Container;
|
---|
519 | end;
|
---|
520 | if NewViewCoord.z > 0 then
|
---|
521 | begin
|
---|
522 | InvZ := 1/NewViewCoord.z;
|
---|
523 | result := PointF(NewViewCoord.x*InvZ*AProjection.Zoom.x + AProjection.Center.x,
|
---|
524 | NewViewCoord.y*InvZ*AProjection.Zoom.Y + AProjection.Center.y);
|
---|
525 | end else
|
---|
526 | result := PointF(0,0);
|
---|
527 | end;
|
---|
528 |
|
---|
529 | procedure TBGRAPart3D.NormalizeViewNormal;
|
---|
530 | var
|
---|
531 | i: Integer;
|
---|
532 | begin
|
---|
533 | for i := 0 to FVertexCount-1 do
|
---|
534 | FVertices[i].NormalizeViewNormal;
|
---|
535 | for i := 0 to FPartCount-1 do
|
---|
536 | FParts[i].NormalizeViewNormal;
|
---|
537 | end;
|
---|
538 |
|
---|
539 | procedure TBGRAPart3D.Translate(x, y, z: single; Before: boolean = true);
|
---|
540 | begin
|
---|
541 | Translate(Point3D(x,y,z),Before);
|
---|
542 | end;
|
---|
543 |
|
---|
544 | procedure TBGRAPart3D.Translate(ofs: TPoint3D; Before: boolean = true);
|
---|
545 | begin
|
---|
546 | if Before then
|
---|
547 | FMatrix *= MatrixTranslation3D(ofs)
|
---|
548 | else
|
---|
549 | FMatrix := MatrixTranslation3D(ofs)*FMatrix;
|
---|
550 | end;
|
---|
551 |
|
---|
552 | function TBGRAPart3D.CreatePart: IBGRAPart3D;
|
---|
553 | begin
|
---|
554 | if FPartCount = length(FParts) then
|
---|
555 | setlength(FParts, FPartCount*2+1);
|
---|
556 | result := TBGRAPart3D.Create(FObject3D,self);
|
---|
557 | FParts[FPartCount] := result;
|
---|
558 | inc(FPartCount);
|
---|
559 | end;
|
---|
560 |
|
---|
561 | function TBGRAPart3D.GetContainer: IBGRAPart3D;
|
---|
562 | begin
|
---|
563 | result := FContainer;
|
---|
564 | end;
|
---|
565 |
|
---|
566 | procedure TBGRAPart3D.SetVertex(AIndex: Integer; AValue: IBGRAVertex3D);
|
---|
567 | begin
|
---|
568 | if (AIndex < 0) or (AIndex >= FVertexCount) then
|
---|
569 | raise ERangeError.Create('Index of out bounds');
|
---|
570 | FVertices[AIndex] := AValue;
|
---|
571 | end;
|
---|
572 |
|
---|
573 | procedure TBGRAPart3D.SetNormal(AIndex: Integer; AValue: IBGRANormal3D);
|
---|
574 | begin
|
---|
575 | if (AIndex < 0) or (AIndex >= FNormalCount) then
|
---|
576 | raise ERangeError.Create('Index of out bounds');
|
---|
577 | FNormals[AIndex] := AValue;
|
---|
578 | end;
|
---|
579 |
|
---|
580 |
|
---|