-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathCAST2.pas
More file actions
2062 lines (1755 loc) · 87.1 KB
/
CAST2.pas
File metadata and controls
2062 lines (1755 loc) · 87.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
@Abstract(CAST II Engine main unit)
(C) 2006-2009 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
Started Jan 15, 2006 <br>
Unit contains basic engine classes
*)
{$Include GDefines.inc}
{$Include C2Defines.inc}
unit CAST2;
interface
uses
Logger, Timer,
BaseTypes, Basics, BaseStr, BaseCont, Models, BaseClasses, Base3D, BaseMsg, ItemMsg, Collisions, Props, C2Types;
const
EngineVersionMajor = '0';
EngineVersionMinor = '995';
// Bounding volume kinds enumeration string
VolumeKindsEnum = 'OOBB' + StrDelim + 'Sphere' + StrDelim + 'Cylinder' + StrDelim + 'Cone' + StrDelim + 'Capsule' + StrDelim + 'Chamfer Cylinder';
// Items processing interval by default
DefaultProcessingInterval = 30/1000;
// Pass ordering enumeration string
PassOrdersEnum = 'Preprocess\&Background\&Farest\&Normal\&Sorted\&Nearest\&Foreground\&PostProcess';
// This order used for preprocess passes
poPreprocess = 0;
// This order used for passes that should be at background
poBackground = 1;
// This order used for passes that should be farest
poFarest = 2;
// This order used for usual passes
poNormal = 3;
// This order used for passes that should render corresponding items in a particular order (usually transparent items)
poSorted = 4;
// This order used for passes that should be neartest
poNearest = 5;
// This order used for passes that should be at foreground
poForeground = 6;
// This order used for postprocess passes
poPostProcess = 7;
// Order corresponding to passes with sorted items
SortedPassOrder = poSorted;
// Number of pass groups currently supported by the engine
PassGroupsCount = 16;
// Pass groups enumeration string
PassGroupsEnum = 'Group 01\&Group 02\&Group 03\&Group 04\&Group 05\&Group 06\&Group 07\&Group 08\&' +
'Group 09\&Group 10\&Group 11\&Group 12\&Group 13\&Group 14\&Group 15\&Group 16';
// Set of all pass groups
gmAll = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// Default set of pass groups
gmDefault = [0, 1, 2, 3, 4, 5, 6, 7];
// Maximum of texture coordinates sets
MaxTextureCoordSets = 8;
// Maximum of user-defined clipping planes currently supported by the engine
MaxClipPlanes = 6;
type
// Type to specify location of an object in 3D space. Additional component can be used to work with floating coordinates, space partitioning, etc.
TLocation = TVector4s;
// Traverse callback results
TTraverseResult = (// Continue traversal
trContinue,
// Skip traversal for childs of the current item
trSkip,
// Stop traversal
trStop);
// Frustum planes
TFrustumPlane = (fpLeft, fpRight, fpTop, fpBottom, fpNear, fpFar);
TFrustumCheckResult = (// An item is completely outside of the frustum
fcOutside,
// An item is completely inside the frustum
fcInside,
// An item is partially inside the frustum
fcPartially);
// Pass groups range
TPassGroup = 0..PassGroupsCount-1;
// Pass groups set. Groups used to perform some operations (lighting, render) for one set of passes and not to perform for other set of passes
TPassGroupSet = set of TPassGroup;
// User-defined clipping planes
TClipPlanes = array[0..MaxClipPlanes-1] of PPlane;
// Traverse mask
TTraverseMask = BaseTypes.TSet32;
TProcessing = class;
// Class reference of collision-related information object
CBaseColliding = class of TBaseColliding;
// Class containing abstract part of collision-related information object for an item
TBaseColliding = class(BaseCont.TBaseUniqueItem)
protected
// The item to which the collision information belongs
FOwner: BaseClasses.TItem;
// Returns True if the object contains valid physics representation and can be handled by a physics subsystem
function IsValid: Boolean; virtual; abstract;
// Flushes properties to a physics subsystem. Called automatically.
procedure FlushProperties; virtual; abstract;
public
// Bounding volumes set
Volumes: Collisions.TBoundingVolumes;
// Collision info constructor
constructor Create(AOwner: TItem); reintroduce; virtual;
// This procedure is called (by editor for example) to retrieve a list of item's properties and their values. No item links allowed.
procedure AddProperties(const Result: Props.TProperties); virtual; abstract;
// This procedure is called (by editor for example) to set values of item's properties.
procedure SetProperties(Properties: Props.TProperties); virtual; abstract;
// The item to which the collision information belongs
property Owner: BaseClasses.TItem read FOwner;
end;
// Tesselation buffers enumeration
TTesselationBuffer = (// Vertex buffer
tbVertex,
// Index buffer
tbIndex);
// Set of tesselation buffers
TTesselationBufferSet = set of TTesselationBuffer;
// Vertex/index buffers performace profile
TBuffersPerfProfile = record
// Number of tesselation calls for static and dynamic meshes in current frame. Normally should be zero for static meshes
TesselationsPerformed,
// Amount of data written to buffers during tesselation
BytesWritten,
// Number of resets of static and dynamic buffers in current frame. Normally should be zero for static buffers
BufferResetsCount,
// Current size of the buffer in bytes
BufferSize: array[Boolean] of Integer;
// Number of items rendered without tesselations of a certain buffer (vertex/index)
TesselationsBypassed,
// Number of buffer bytes reused
BytesBypassed: Integer;
end;
// Performance profile target enumeration
TPerfTimer = (// Entire frame time
ptFrame,
// Render time
ptRender,
// Objects processing time
ptProcessing,
// Collision detection
ptCollision);
// Engine performance profile data
TPerfProfile = class
private
TimeMarks: array[TPerfTimer] of TTimeMark;
FFramesPerSecond, FMinFramesPerSecond, FMaxFramesPerSecond: Single;
procedure SetFramesPerSecond(const Value: Single);
function GetPrimitivesPerSecond: Single;
public
Times: array[TPerfTimer] of TTimeUnit;
// Number of render target changes during rendering a frame
RenderTargetChanges,
// Number of primitives (triangles) rendered in current frame
PrimitivesRendered,
// Number of draw calls (DrawIndexedPrimitive etc) in current frame
DrawCalls,
// Number of clear calls during rendering a frame
ClearCalls: Integer;
// Number of items culled out with frustum culling in current frame
FrustumCulledItems,
// Number of items passed frustum culling (and probably actually drawn) in current frame
FrustumPassedItems: Integer;
// Number of sorted items in current frame
SortedItems: Integer;
// Vertex/index buffers performace profile
BuffersProfile: array[TTesselationBuffer] of TBuffersPerfProfile;
// Sets values which should be zeroed-out at frame render start
procedure OnFrameStart;
// Sets values which should be resetted at render buffers reset
procedure OnBuffersReset;
// Starts timing of the specified performance timer using the specified timer class
procedure BeginTiming(Timer: TTimer; PerfTimer: TPerfTimer);
// Stops timing and returns the specified performance timer value using the specified timer class
function EndTiming(Timer: TTimer; PerfTimer: TPerfTimer): TTimeUnit;
// Frame rate averaged through some time
property FramesPerSecond: Single read FFramesPerSecond write SetFramesPerSecond;
// Number of primitives per second
property PrimitivesPerSecond: Single read GetPrimitivesPerSecond;
// Minimal averaged frame rate
property MinFramesPerSecond: Single read FMinFramesPerSecond;
// Maximal averaged frame rate
property MaxFramesPerSecond: Single read FMaxFramesPerSecond;
end;
TBaseCore = class;
// Base class of shared tesselators manager
TBaseSharedTesselators = class
// Engine core (items manager)
Core: TBaseCore;
// Makes items associated with shared tesselators visible
procedure Render; virtual; abstract;
// Makes items associated with shared tesselators invisible
procedure Reset; virtual; abstract;
// Clears items associated with shared tesselators
procedure ClearItems; virtual; abstract;
// Completely cleans structures
procedure Clear; virtual; abstract;
end;
// Engine base core class
TBaseCore = class(TItemsManager)
private
FTesselatorManager: BaseCont.TReferencedItemManager;
Subsystems: array of TBaseSubsystem;
FTimer, DefaultTimer: Timer.TTimer;
procedure SetTimer(const Value: Timer.TTimer);
procedure SetTotalProcessingClasses(const Value: Integer);
protected
// Time mark for delta time based items processing
DeltaTimeBasedTimeMark: TTimeMark;
// Number of items to process
ProcessingItems: TItems;
// Items to process
TotalProcessingItems: Integer;
// Shared tesselators manager. For internal use only
FSharedTesselators: TBaseSharedTesselators;
// Temporary items container. Used internally for shared tesselators visualization etc.
FTempItems: BaseClasses.TItem;
// Performance profile
FPerfProfile: TPerfProfile;
// Performs delta time based items processing
procedure ProcessDeltaTimeBased(const DeltaTime: TTimeUnit);
// Performs items processing
procedure ProcessingEvent(EventID: Integer; const ErrorDelta: TTimeUnit);
procedure OnDestroy; override;
public
// If <b>Paused</b> is <b>True</b> @Link(Process) methods will be called only for items which processing class includes the @Link(pfIgnorePause) flag
Paused: Boolean;
// Delta time scale factor for all processing classes
TimeScale: Single;
// Maximum of simultaneous light sources
SimultaneousLightSources: Integer;
// Random numbers generator
RandomGen: Basics.TRandomGenerator;
// By assigning this handler reference an additional message handler can be included into the message handling chain
MessageHandler: BaseMsg.TMessageHandler;
constructor Create; override;
procedure HandleMessage(const Msg: TMessage); override;
// Register a subsystem. All registered subsystems will receive all messages received by the core.
procedure AddSubsystem(const Subsystem: TBaseSubsystem);
// Unregister a subsystem
procedure RemoveSubsystem(const Subsystem: TBaseSubsystem);
// Returns a registered subsystem of the specified class or successor
function QuerySubsystem(SubsystemClass: CSubsystem): TBaseSubsystem;
// Sets parameters of a processing class.
procedure SetProcessingClass(Index: Integer; Interval: Single; IgnorePause, DeltaTimeBased: Boolean);
// For internal use only.
procedure AddPass(const Item: BaseClasses.TItem); virtual; abstract;
// For internal use only.
procedure RemovePass(const Item: BaseClasses.TItem); virtual; abstract;
// Clears current scene
procedure ClearItems; override;
// Shared tesselators manager. For internal use only.
property SharedTesselators: TBaseSharedTesselators read FSharedTesselators;
// Tesselators manager. For internal use only.
property TesselatorManager: BaseCont.TReferencedItemManager read FTesselatorManager;
// Temporary items container. Used internally for shared tesselators visualization etc.
property TempItems: BaseClasses.TItem read FTempItems;
// Timer subsystem. Must be assigned.
property Timer: Timer.TTimer read FTimer write SetTimer;
// Performance profile
property PerfProfile: TPerfProfile read FPerfProfile;
// Number of processing classes
property TotalProcessingClasses: Integer read GetTotalProcessingClasses write SetTotalProcessingClasses;
end;
CProcessing = class of TProcessing;
// Base class of all processing (updateable) objects
TProcessing = class(TBaseProcessing)
protected
TransformValid: Boolean;
function GetTransform: TMatrix4s; {$I inline.inc}
function GetTransformPtr: PMatrix4s; {$I inline.inc}
procedure SetTransform(const ATransform: TMatrix4s); {$I inline.inc}
function GetForwardVector: TVector3s; {$I inline.inc}
function GetRightVector: TVector3s; {$I inline.inc}
function GetUpVector: TVector3s; {$I inline.inc}
function GetPosition: TVector3s; {$I inline.inc}
procedure SetPosition(const Value: TVector3s); {$I inline.inc}
function GetScale: TVector3s; {$I inline.inc}
procedure SetScale(const Value: TVector3s); {$I inline.inc}
function GetLocation: TLocation; {$I inline.inc}
procedure SetLocation(ALocation: TLocation); {$I inline.inc}
function GetOrientation: TQuaternion; {$I inline.inc}
procedure SetOrientation(AOrientation: TQuaternion); {$I inline.inc}
function GetDimensions: TVector3s; {$I inline.inc}
function GetBoundingSphereRadius: Single; {$I inline.inc}
procedure ResolveLinks; override;
protected
// Transformation matrix of the item
FTransform: TMatrix4s;
// Current orientation of the item
FOrientation: TQuaternion;
// Current location of the item
FLocation: TLocation;
// Current scale of the item
FScale: TVector3s;
// Returns True if the entity is handled by a physics subsystem
function IsPhysical: Boolean; {$I inline.inc}
//
procedure SetState(const Value: TSet32); override;
{ In CAST II engine a lazy evaluation scheme used for transformation computations.
This method will compute current transformation matrix when and only when it is necessary. }
procedure ComputeTransform; virtual;
// Calling this method will tell the engine that @Link(FTransform) became invalid and should be recomputed before next use
procedure InvalidateTransform; virtual;
// Returns AItem if OK or nil if index is invalid or impossible to set a child
function SetChild(Index: Integer; AItem: BaseClasses.TItem): BaseClasses.TItem; override;
public
// Contains information about bounding volumes of the item which will be used for collision tests
Colliding: TBaseColliding;
// Returns bounding box of the item
BoundingBox: Base3D.TBoundingBox;
// FullBoundingBox: Base3D.TBoundingBox;
constructor Create(AManager: TItemsManager); override;
destructor Destroy; override;
// Called when a collision of the item with another items was detected
procedure OnCollision(Item: TProcessing; const ColRes: Collisions.TCollisionResult); virtual;
{ This procedure is called (by editor for example) to retrieve a list of item's properties and their values.
Any TItem descendant class should override this method in order to add its own properties. }
procedure AddProperties(const Result: Props.TProperties); override;
{ This procedure is called (by editor for example) to set values of item's properties.
Any TItem descendant class should override this method to allow its own properties to be set. }
procedure SetProperties(Properties: Props.TProperties); override;
// Returns position of the item in world's coordinate space
function GetAbsLocation: TVector3s; {$I inline.inc}
// Returns orientation of the item in world's coordinate space
function GetAbsOrientation: TQuaternion; {$I inline.inc}
// Transforms a point from local model's coordinate space to world's coordinate space
function ModelToWorld(const APoint: TVector3s): TVector3s; {$I inline.inc}
// Transforms a point from world's coordinate space to local model's coordinate space
function WorldToModel(const APoint: TVector3s): TVector3s; {$I inline.inc}
// Transformation matrix of the item
property Transform: TMatrix4s read GetTransform write SetTransform;
// Transformation matrix pointer to pass to functions which requires a pointer parameter
property TransformPtr: PMatrix4s read GetTransformPtr;
// 4-component position of the item within parent's coordinate space
property Location: TLocation read GetLocation write SetLocation;
// Position of the item within parent's coordinate space
property Position: TVector3s read GetPosition write SetPosition;
// Scale of the item within parent's coordinate space
property Scale: TVector3s read GetScale write SetScale;
// Orientation of the item within parent's coordinate space
property Orientation: TQuaternion read GetOrientation write SetOrientation;
// Forward direction for the item
property ForwardVector: TVector3s read GetForwardVector;
// Right direction for the item
property RightVector: TVector3s read GetRightVector;
// Up direction for the item
property UpVector: TVector3s read GetUpVector;
// Dimensions of the item based on its bounding box (see @Link(BoundingBox))
property Dimensions: TVector3s read GetDimensions;
// The item's bounding sphere radius based on @Link(Dimensions)
property BoundingSphereRadius: Single read GetBoundingSphereRadius;
end;
// Item move operation
TItemMoveOp = class(Models.TOperation)
private
AffectedProcessing: TProcessing;
Location: TLocation;
protected
// Applies the operation
procedure DoApply; override;
// Merges together two move operations
function DoMerge(AOperation: Models.TOperation): Boolean; override;
public
// Inits the operation with the specified processing item and its new location
function Init(AAffectedProcessing: TProcessing; ALocation: TLocation): Boolean;
end;
// Item orientation change operation
TItemRotateOp = class(Models.TOperation)
private
AffectedProcessing: TProcessing;
Orientation: TQuaternion;
protected
// Applies the operation
procedure DoApply; override;
// Merges together two orientation change operations
function DoMerge(AOperation: Models.TOperation): Boolean; override;
public
// Inits the operation with the specified processing item and its new orientation
function Init(AAffectedProcessing: TProcessing; AOrientation: TQuaternion): Boolean;
end;
// Callback function used to traverse through items hierarchy
TTraverseCallback = function(Item: BaseClasses.TItem): TTraverseResult;
// Collection of items
TItemCollection = record
TraverseMask: TTraverseMask;
TotalItems: Integer;
Items: array of BaseClasses.TItem;
end;
{ Specifies clear settings.
<b>ClearFlags</b> - what to clear
<b>ClearColor</b> - clear color
<b>ClearStencil</b> - a stencil value to clear with
<b>ClearZ</b> - a Z value to clear with }
TClearSettings = record
ClearFlags: TClearFlagsSet;
ClearColor: BaseTypes.TColor;
ClearStencil: Longword;
ClearZ: Single;
end;
// Specifies clear settings for each render stage (order)
TStagesClearSettings = array[poPreprocess..poPostProcess] of TClearSettings;
// Camera
TCamera = class(TProcessing)
private
FOrthographic: Boolean;
FCurrentAspectRatio,
FZNear,
FZFar,
FWidth,
FAspectRatio,
FHFoV: Single;
FFrustumPlanes: array[TFrustumPlane] of TPlane;
FRTColorFormat, FRTDepthFormat: Cardinal;
function GetViewMatrix: TMatrix4s;
function GetViewMatrixPtr: PMatrix4s;
function GetProjMatrixPtr: PMatrix4s;
procedure SetViewMatrix(const Value: TMatrix4s);
function GetInvViewMatrix: TMatrix4s;
function GetTotalMatrix: TMatrix4s;
function GetViewOrigin: TVector3s;
function GetLookDir: TVector3s;
function GetRightDir: TVector3s;
function GetUpDir: TVector3s;
procedure SetAspectRatio(const Value: Single);
protected
// Determines if view matrix need recalculating
FViewValid: Boolean;
// View matrix
FViewMatrix,
// Inverse view matrix
FInvViewMatrix,
// Projection matrix
FProjMatrix,
// View * projection matrix
FTotalMatrix: TMatrix4s;
// Current render width
FRenderWidth,
// Current render height
FRenderHeight: Integer;
// Calling this method will tell the engine that @Link(FTransform) became invalid and should be recomputed before next use
procedure InvalidateTransform; override;
// Recalculates frustum planes. Should be called only from ComputeViewMatrix.
procedure ComputeFrustumPlanes;
// Recalculates view matrix when needed
procedure ComputeViewMatrix; virtual;
public
// Default cameras can
// Default: Boolean;
// Default fill mode for the camera
DefaultFillMode: TFillMode;
// Default cull mode for the camera
DefaultCullMode: TCullMode;
// Determines what and when should be cleared
ClearSettings: TClearSettings;
// private
RenderTargetIndex: Integer;
// User-defined clip planes
ClipPlanes: TClipPlanes;
// Determines which passes can be visible through the camera
GroupMask: TPassGroupSet;
// Current rendering color format. Updated by renderer
ColorFormat,
// Current rendering depth format. Updated by renderer
DepthFormat: Integer;
// Width of a render target texture used if the camera will be used as a texture
RenderTargetWidth,
// Height of a render target texture used if the camera will be used as a texture
RenderTargetHeight: Integer;
// Determines how many frames should be skipped between render target texture updates
FrameSkip: Integer;
// Cameras can render scene in higher or lower detail which is controlled by this parameter
LODBias: Single;
// Determines if a depth-stencil surface instead of color surface should be used when the camera applied as a texture
IsDepthTexture: Boolean;
constructor Create(AManager: TItemsManager); override;
destructor Destroy; override;
{ This procedure is called (by editor for example) to retrieve a list of item's properties and their values.
Any TItem descendant class should override this method in order to add its own properties. }
procedure AddProperties(const Result: Props.TProperties); override;
{ This procedure is called (by editor for example) to set values of item's properties.
Any TItem descendant class should override this method to allow its own properties to be set. }
procedure SetProperties(Properties: Props.TProperties); override;
// Sets up the camera's projection matrix with the given near and far Z planes, horizontal field of view and aspect ratio
procedure InitProjMatrix(AZNear, AZFar, AHFoV, AAspectRatio: Single); virtual;
// Sets up the camera's orthographic projection matrix with the given near and far Z planes, width of view and aspect ratio
procedure InitOrthoProjMatrix(AZNear, AZFar, VisibleWidth, AAspectRatio: Single); virtual;
// Sets the @Link(ClearSettings)
procedure SetClearState(AClearFlags: TClearFlagsSet; AClearColor: BaseTypes.TColor; AClearZ: Single; AClearStencil: Cardinal); virtual;
// Sets render dimensions and recalculates projection matrix. Normally called by renderer when render window size changes.
procedure SetScreenDimensions(Width, Height: Integer; AdjustAspectRatio: Boolean);
// Rotates the camera by the specified angles
procedure Rotate(XA, YA, ZA: Single); virtual;
// Moves the camera by the specified distance in camera space
procedure Move(XD, YD, ZD: Single); virtual;
// Returns not normalized direction of a ray in view space which starts from the camera and passes through the given point on screen
function GetPickRay(ScreenX, ScreenY: Single): TVector3s; virtual;
// Returns not normalized direction of a ray in world space which starts from the camera and passes through the given point on screen
function GetPickRayInWorld(ScreenX, ScreenY: Single): TVector3s; virtual;
// Returns the given vector after projection with the camera
function Project(const Vec: TVector3s): TVector4s;
// Renderer calls this event right before the camera apply
procedure OnApply(const OldCamera: TCamera); virtual;
// Performs a frustrum visibility check against a sphere with the given center and radius
function IsSpehereVisible(const Center: TVector3s; Radius: Single): TFrustumCheckResult;
// Near Z plane distance
property ZNear: Single read FZNear;
// Far Z plane distance
property ZFar: Single read FZFar;
// Initial aspect ratio. Can change
property AspectRatio: Single read FAspectRatio write SetAspectRatio;
// Current aspect ratio
property CurrentAspectRatio: Single read FCurrentAspectRatio;
// Horizontal field of view in radians
property HFoV: Single read FHFoV;
// Current render width
property RenderWidth: Integer read FRenderWidth;
// Current render height
property RenderHeight: Integer read FRenderHeight;
// Color format for render target which will be used in case of use of this camera as a texture
property RTColorFormat: Cardinal read FRTColorFormat;
// Depth format for render target which will be used in case of use of this camera as a texture
property RTDepthFormat: Cardinal read FRTDepthFormat;
// View matrix
property ViewMatrix: TMatrix4s read GetViewMatrix write SetViewMatrix;
// Pointer to view matrix
property ViewMatrixPtr: PMatrix4s read GetViewMatrixPtr;
// Inverse view matrix
property InvViewMatrix: TMatrix4s read GetInvViewMatrix;
// Projection matrix
property ProjMatrix: TMatrix4s read FProjMatrix write FProjMatrix;
// Pointer to projection matrix
property ProjMatrixPtr: PMatrix4s read GetProjMatrixPtr;
// View * projection matrix
property TotalMatrix: TMatrix4s read GetTotalMatrix;
// Position of the camera's view point in world space
property ViewOrigin: TVector3s read GetViewOrigin;
// View direction of the camera in world space
property LookDir: TVector3s read GetLookDir;
// Right direction of the camera in world space
property RightDir: TVector3s read GetRightDir;
// Up direction of the camera in world space
property UpDir: TVector3s read GetUpDir;
end;
// An item of this class should be the root of items hierarchy
TCASTRootItem = class(TRootItem)
private
// collection for various sets of items from scene (e.g. renderable, processing etc)
Collections: array of TItemCollection;
TotalCollections: Integer;
Collidings: TUniqueItemCollection;
// ModifyingCollectionIndex: Integer;
// procedure IncludeItem(Item: BaseClasses.TItem; Mask: TTraverseMask);
// procedure ExcludeItem(Item: BaseClasses.TItem; Mask: TTraverseMask);
// Internal function used as callback only
// function AddToCollectionCallback(Item: BaseClasses.TItem): TTraverseResult;
// procedure AddToCollection(CollectionIndex: Integer; Item: BaseClasses.TItem); virtual;
// procedure RemoveFromCollection(CollectionIndex: Integer; Item: BaseClasses.TItem); virtual;
public
// Clear settings for all render stages
StageSettings: TStagesClearSettings;
constructor Create(AManager: TItemsManager); override;
destructor Destroy; override;
function GetItemSize(CountChilds: Boolean): Integer; override;
{ This procedure is called (by editor for example) to retrieve a list of item's properties and their values.
Any TItem descendant class should override this method in order to add its own properties. }
procedure AddProperties(const Result: Props.TProperties); override;
{ This procedure is called (by editor for example) to set values of item's properties.
Any TItem descendant class should override this method to allow its own properties to be set. }
procedure SetProperties(Properties: Props.TProperties); override;
{ Traverses through the items hierarchy and adds to Items all items matching the following: <br>
the item is an instance of the given class or a descendant, its State field has matches Mask and
the item is within the given range from the given origin.
Childs of items with non-matching State are not considered.
Returns number of items in Items. }
function ExtractByMaskClassInRadius(Mask: TItemFlags; AClass: CProcessing; out Items: TItems; Origin: TLocation; Range: Single): Integer;
{ Traverses through the items hierarchy and adds to Items all items matching the following: <br>
the item is an instance of the given class or a descendant, its State field has matches Mask and
the item is within visibility frustum of the given camera.
Childs of items with non-matching State are not considered.
Returns number of items in Items. }
function ExtractByMaskClassInCamera(Mask: TItemFlags; AClass: CProcessing; out Items: TItems; ACamera: TCamera): Integer;
procedure HandleMessage(const Msg: TMessage); override;
// Adds a collection of items with the specified state
function AddCollection(Mask: TTraverseMask): Integer;
// Removes collection specified by the index
procedure DeleteCollection(Index: Integer);
// Traverses through the items hierarchy and calls Callback for all items
procedure TraverseTree(Callback: TTraverseCallback);
// Frees all childs
procedure FreeChilds; override;
end;
{ @Abstract(Camera class for mirror surfaces)
The camera constructs its view matrix as a reflection of view matrix of previous camera by XY plane if the camera's transform}
TMirrorCamera = class(TCamera)
private
FOldCamera: TCamera;
public
// Reflects previous applyed camera view matrix by its own XY plane and assigns the result to view matrix
procedure ComputeViewMatrix; override;
// OnApply event overridden to assign previous camera variable and setup clipping plane
procedure OnApply(const OldCamera: TCamera); override;
end;
{ TRenderParameters = record
MainCamera, ActiveCamera: TCamera;
end;
PRenderParameters = ^TRenderParameters;}
// Returns a location from 3D vector
function GetLocationFromVec3s(V: TVector3s): TLocation;
// Retuns True if the locations are equal
function EqualLocations(V1, V2: TLocation): Boolean;
// Retuns squared distance between the locations
function LocationSqDistance(V1, V2: TLocation): Single;
// Helper functions for adding/setting properties of a certain type
// Adds a string property named "Error" with the value contained in <b>Msg</b>
procedure AddErrorProperty(Properties: Props.TProperties; const Msg: string);
// Adds a 3-component vector and each its component as properties
procedure AddVector3sProperty(Properties: Props.TProperties; const Name: string; const Vec: TVector3s);
// Adds a 4-component vector and each its component as properties
procedure AddVector4sProperty(Properties: Props.TProperties; const Name: string; const Vec: TVector4s);
// Adds a quaternion and each its component as properties
procedure AddQuaternionProperty(Properties: Props.TProperties; const Name: string; const Quat: TQuaternion);
// Reads a 3-component vector from properties. If its not equivalent to the one contained in <b>Res</b> assigns it to <b>Res</b> and returns <b>True</b>.
function SetVector3sProperty(Properties: Props.TProperties; const Name: string; var Res: TVector3s): Boolean;
// Reads a 4-component vector from properties. If its not equivalent to the one contained in <b>Res</b> assigns it to <b>Res</b> and returns <b>True</b>.
function SetVector4sProperty(Properties: Props.TProperties; const Name: string; var Res: TVector4s): Boolean;
// Reads a quaternion from properties. If its not equivalent to the one contained in <b>Res</b> assigns it to <b>Res</b> and returns <b>True</b>.
function SetQuaternionProperty(Properties: Props.TProperties; const Name: string; var Res: TQuaternion): Boolean;
var
CollidingClass: CBaseColliding;
implementation
uses SysUtils;
function GetLocationFromVec3s(V: TVector3s): TLocation;
begin
Result.X := V.X;
Result.Y := V.Y;
Result.Z := V.Z;
Result.W := 1;
end;
function EqualLocations(V1, V2: TLocation): Boolean;
begin
Result := (V1.X = V2.X) and (V1.Y = V2.Y) and (V1.Z = V2.Z) and (V1.W = V2.W);
end;
function LocationSqDistance(V1, V2: TLocation): Single;
begin
Result := Sqr(V2.X-V1.X) + Sqr(V2.Y-V1.Y)+ Sqr(V2.Z-V1.Z);
end;
procedure AddErrorProperty(Properties: Props.TProperties; const Msg: string);
begin
Properties.Add('Error', vtString, [poReadonly], Msg, '');
end;
procedure AddVector3sProperty(Properties: Props.TProperties; const Name: string; const Vec: TVector3s);
begin
Properties.Add(Name, vtString, [poReadOnly], Format('(%3.3F, %3.3F, %3.3F)', [Vec.X, Vec.Y, Vec.Z]), '');
Properties.Add(Name + '\X', vtSingle, [], FloatToStr(Vec.X), '');
Properties.Add(Name + '\Y', vtSingle, [], FloatToStr(Vec.Y), '');
Properties.Add(Name + '\Z', vtSingle, [], FloatToStr(Vec.Z), '');
end;
procedure AddVector4sProperty(Properties: Props.TProperties; const Name: string; const Vec: TVector4s);
begin
AddVector3sProperty(Properties, Name, Vec.XYZ);
Properties.Add(Name + '\W', vtSingle, [], FloatToStr(Vec.W), '');
Properties.Add(Name, vtString, [poReadOnly], Format('(%3.3F, %3.3F, %3.3F, %3.3F)', [Vec.X, Vec.Y, Vec.Z, Vec.W]), '');
end;
procedure AddQuaternionProperty(Properties: Props.TProperties; const Name: string; const Quat: TQuaternion);
var Angle: Single;
begin
AddVector3sProperty(Properties, Name, GetVector3s(Quat[1], Quat[2], Quat[3]));
Angle := ArcTan2(Sqrt(1 - Quat[0] * Quat[0]), Quat[0])*2 * 180/pi;
Properties.Add(Name + '\Angle', vtSingle, [], FloatToStr(Angle), '');
Properties.Add(Name, vtString, [poReadOnly], Format('(%3.3F, (%3.3F, %3.3F, %3.3F))', [Angle, Quat[1], Quat[2], Quat[3]]), '');
end;
function SetVector3sProperty(Properties: Props.TProperties; const Name: string; var Res: TVector3s): Boolean;
var NewVec: TVector3s;
begin
NewVec := Res;
if Properties.Valid(Name + '\X') then NewVec.X := StrToFloatDef(Properties[Name + '\X'], 0);
if Properties.Valid(Name + '\Y') then NewVec.Y := StrToFloatDef(Properties[Name + '\Y'], 0);
if Properties.Valid(Name + '\Z') then NewVec.Z := StrToFloatDef(Properties[Name + '\Z'], 0);
Result := isNan(Res.X) or isNan(Res.Y) or isNan(Res.Z) or
(NewVec.X <> Res.X) or (NewVec.Y <> Res.Y) or (NewVec.Z <> Res.Z);
if Result then Res := NewVec;
end;
function SetVector4sProperty(Properties: Props.TProperties; const Name: string; var Res: TVector4s): Boolean;
var NewVec: TVector3s; W: Single;
begin
NewVec := Res.XYZ;
W := Res.W;
Result := SetVector3sProperty(Properties, Name, NewVec);
if Properties.Valid(Name + '\W') then W := StrToFloatDef(Properties[Name + '\W'], 0);
Result := Result or isNan(Res.W) or (W <> Res.W);
if Result then begin
Res := ExpandVector3s(NewVec);
Res.W := W;
end;
end;
function SetQuaternionProperty(Properties: Props.TProperties; const Name: string; var Res: TQuaternion): Boolean;
var NewVec: TVector3s; Angle: Single;
begin
NewVec.X := Res[1]; NewVec.Y := Res[2]; NewVec.Z := Res[3];
Result := SetVector3sProperty(Properties, Name, NewVec);
if Properties.Valid(Name + '\Angle') then Angle := StrToFloatDef(Properties[Name + '\Angle'], 0)*pi/180 else
Angle := ArcTan2(Sqrt(1 - Res[0] * Res[0]), Res[0])*2;
Result := Result or isNan(Res[0]) or (Angle <> Res[0]);
if Result then Res := GetQuaternion(Angle, NewVec);
end;
{ TBaseColliding }
constructor TBaseColliding.Create(AOwner: TItem);
begin
inherited Create();
FOwner := AOwner;
end;
{ TPerfProfile }
procedure TPerfProfile.SetFramesPerSecond(const Value: Single);
begin
FFramesPerSecond := Value;
if (FMinFramesPerSecond = 0) or (FFramesPerSecond < FMinFramesPerSecond) then FMinFramesPerSecond := FFramesPerSecond;
if FFramesPerSecond > FMaxFramesPerSecond then FMaxFramesPerSecond := FFramesPerSecond;
end;
function TPerfProfile.GetPrimitivesPerSecond: Single;
begin
Result := PrimitivesRendered * FramesPerSecond;
end;
procedure TPerfProfile.OnFrameStart;
var BufType: TTesselationBuffer;
begin
RenderTargetChanges := 0;
PrimitivesRendered := 0;
DrawCalls := 0;
ClearCalls := 0;
FrustumCulledItems := 0;
FrustumPassedItems := 0;
SortedItems := 0;
for BufType := Low(TTesselationBuffer) to High(TTesselationBuffer) do begin
BuffersProfile[BufType].TesselationsPerformed[True] := 0;
BuffersProfile[BufType].BytesWritten[True] := 0;
BuffersProfile[BufType].TesselationsPerformed[False] := 0;
BuffersProfile[BufType].BytesWritten[False] := 0;
BuffersProfile[BufType].BufferResetsCount[True] := 0;
BuffersProfile[BufType].BufferResetsCount[False] := 0;
BuffersProfile[BufType].TesselationsBypassed := 0;
BuffersProfile[BufType].BytesBypassed := 0;
end;
end;
procedure TPerfProfile.OnBuffersReset;
var BufType: TTesselationBuffer;
begin
for BufType := Low(TTesselationBuffer) to High(TTesselationBuffer) do begin
BuffersProfile[BufType].BufferSize[True] := 0;
BuffersProfile[BufType].BufferSize[False] := 0;
end;
end;
procedure TPerfProfile.BeginTiming(Timer: TTimer; PerfTimer: TPerfTimer);
begin
Timer.GetInterval(TimeMarks[PerfTimer], True);
end;
function TPerfProfile.EndTiming(Timer: TTimer; PerfTimer: TPerfTimer): TTimeUnit;
begin
Times[PerfTimer] := Timer.GetInterval(TimeMarks[PerfTimer], True);
Result := Times[PerfTimer];
end;
{ TCASTRootItem }
constructor TCASTRootItem.Create(AManager: TItemsManager);
var i: Integer;
begin
inherited;
Collidings := TUniqueItemCollection.Create;
for i := 0 to High(StageSettings) do StageSettings[i].ClearZ := 1;
end;
destructor TCASTRootItem.Destroy;
var i: Integer;
begin
for i := 0 to High(Collections) do DeleteCollection(i);
inherited;
FreeAndNil(Collidings);
end;
function TCASTRootItem.GetItemSize(CountChilds: Boolean): Integer;
var i: Integer;
begin
Result := inherited GetItemSize(CountChilds);
Inc(Result, TotalCollections * SizeOf(TItemCollection));
for i := 0 to TotalCollections-1 do if Collections[i].Items <> nil then Inc(Result, Collections[i].TotalItems * SizeOf(BaseClasses.TItem));
end;
procedure TCASTRootItem.AddProperties(const Result: Props.TProperties);
var i: Integer; Core: TBaseCore; s: string;
begin
inherited;
if not Assigned(Result) then Exit;
if FManager is TBaseCore then Core := (FManager as TBaseCore) else begin
Log(ClassName + '.AddProperties: Items manager must be an instance of TBaseCore', lkError);
Exit;
end;
if (Parent = nil) and (FManager.Root = Self) then begin
Result.Add('Renderer\Before background\Clear\Frame buffer', vtBoolean, [], OnOffStr[ClearFrameBuffer in StageSettings[poBackground].ClearFlags], '');
Result.Add('Renderer\Before background\Clear\Z buffer', vtBoolean, [], OnOffStr[ClearZBuffer in StageSettings[poBackground].ClearFlags], '');
Result.Add('Renderer\Before background\Clear\Stencil buffer', vtBoolean, [], OnOffStr[ClearStencilBuffer in StageSettings[poBackground].ClearFlags], '');
Result.Add('Renderer\Before background\Clear\Z value', vtSingle, [], FloatToStr(StageSettings[poBackground].ClearZ), '');
Result.Add('Renderer\Before background\Clear\Stencil value', vtNat, [], IntToStr(StageSettings[poBackground].ClearStencil), '');
AddColorProperty(Result, 'Renderer\Before background\Clear\Color value', StageSettings[poBackground].ClearColor);
Result.Add('Renderer\Before nearest\Clear\Frame buffer', vtBoolean, [], OnOffStr[ClearFrameBuffer in StageSettings[poNearest].ClearFlags], '');
Result.Add('Renderer\Before nearest\Clear\Z buffer', vtBoolean, [], OnOffStr[ClearZBuffer in StageSettings[poNearest].ClearFlags], '');
Result.Add('Renderer\Before nearest\Clear\Stencil buffer', vtBoolean, [], OnOffStr[ClearStencilBuffer in StageSettings[poNearest].ClearFlags], '');
Result.Add('Renderer\Before nearest\Clear\Z value', vtSingle, [], FloatToStr(StageSettings[poNearest].ClearZ), '');
Result.Add('Renderer\Before nearest\Clear\Stencil value', vtNat, [], IntToStr(StageSettings[poNearest].ClearStencil), '');
AddColorProperty(Result, 'Renderer\Before nearest\Clear\Color value', StageSettings[poNearest].ClearColor);
Result.Add('Renderer\Before postprocess\Clear\Frame buffer', vtBoolean, [], OnOffStr[ClearFrameBuffer in StageSettings[poPostprocess].ClearFlags], '');
Result.Add('Renderer\Before postprocess\Clear\Z buffer', vtBoolean, [], OnOffStr[ClearZBuffer in StageSettings[poPostprocess].ClearFlags], '');
Result.Add('Renderer\Before postprocess\Clear\Stencil buffer', vtBoolean, [], OnOffStr[ClearStencilBuffer in StageSettings[poPostprocess].ClearFlags], '');
Result.Add('Renderer\Before postprocess\Clear\Z value', vtSingle, [], FloatToStr(StageSettings[poPostprocess].ClearZ), '');
Result.Add('Renderer\Before postprocess\Clear\Stencil value', vtNat, [], IntToStr(StageSettings[poPostprocess].ClearStencil), '');
AddColorProperty(Result, 'Renderer\Before postprocess\Clear\Color value', StageSettings[poPostprocess].ClearColor);
Result.Add('Renderer\Simultaneous light sources', vtInt, [], IntToStr(Core.SimultaneousLightSources), '');
Result.Add('Processing\Number of classes', vtInt, [], IntToStr(Core.TotalProcessingClasses), '');
for i := 0 to Core.TotalProcessingClasses-1 do begin
s := Format('Processing\Class %D\', [i]);
Result.Add(s + 'Interval, ms', vtNat, [], IntToStr(Round(Core.ProcessingClasses[i].Interval*1000)), '');
Result.Add(s + 'Delta time-based', vtBoolean, [], OnOffStr[pfDeltaTimeBased in Core.ProcessingClasses[i].Flags], '');
Result.Add(s + 'Ignore pause', vtBoolean, [], OnOffStr[pfIgnorePause in Core.ProcessingClasses[i].Flags], '');
end;
for i := 0 to High(Core.Subsystems) do if Core.Subsystems[i] is TSubsystem then
(Core.Subsystems[i] as TSubsystem).AddProperties(Result);
end;
end;
procedure TCASTRootItem.SetProperties(Properties: Props.TProperties);
var
i: Integer; Core: TBaseCore; s: string;
NewIgnorePause, NewDeltaTimeMode: Boolean;
begin
inherited;
if FManager is TBaseCore then Core := (FManager as TBaseCore) else begin
Log(ClassName + '.SetProperties: Items manager must be an instance of TBaseCore', lkError);
Exit;
end;
if (Parent = nil) and (FManager.Root = Self) then begin
if Properties.Valid('Renderer\Before background\Clear\Frame buffer') then if Properties.GetAsInteger('Renderer\Before background\Clear\Frame buffer') > 0 then
Include(StageSettings[poBackground].ClearFlags, ClearFrameBuffer) else Exclude(StageSettings[poBackground].ClearFlags, ClearFrameBuffer);
if Properties.Valid('Renderer\Before background\Clear\Z buffer') then if Properties.GetAsInteger('Renderer\Before background\Clear\Z buffer') > 0 then
Include(StageSettings[poBackground].ClearFlags, ClearZBuffer) else Exclude(StageSettings[poBackground].ClearFlags, ClearZBuffer);
if Properties.Valid('Renderer\Before background\Clear\Stencil buffer') then if Properties.GetAsInteger('Renderer\Before background\Clear\Stencil buffer') > 0 then
Include(StageSettings[poBackground].ClearFlags, ClearStencilBuffer) else Exclude(StageSettings[poBackground].ClearFlags, ClearStencilBuffer);
if Properties.Valid('Renderer\Before nearest\Clear\Frame buffer') then if Properties.GetAsInteger('Renderer\Before nearest\Clear\Frame buffer') > 0 then
Include(StageSettings[poNearest].ClearFlags, ClearFrameBuffer) else Exclude(StageSettings[poNearest].ClearFlags, ClearFrameBuffer);
if Properties.Valid('Renderer\Before nearest\Clear\Z buffer') then if Properties.GetAsInteger('Renderer\Before nearest\Clear\Z buffer') > 0 then
Include(StageSettings[poNearest].ClearFlags, ClearZBuffer) else Exclude(StageSettings[poNearest].ClearFlags, ClearZBuffer);
if Properties.Valid('Renderer\Before nearest\Clear\Stencil buffer') then if Properties.GetAsInteger('Renderer\Before nearest\Clear\Stencil buffer') > 0 then
Include(StageSettings[poNearest].ClearFlags, ClearStencilBuffer) else Exclude(StageSettings[poNearest].ClearFlags, ClearStencilBuffer);
if Properties.Valid('Renderer\Before postprocess\Clear\Frame buffer') then if Properties.GetAsInteger('Renderer\Before postprocess\Clear\Frame buffer') > 0 then
Include(StageSettings[poPostprocess].ClearFlags, ClearFrameBuffer) else Exclude(StageSettings[poPostprocess].ClearFlags, ClearFrameBuffer);
if Properties.Valid('Renderer\Before postprocess\Clear\Z buffer') then if Properties.GetAsInteger('Renderer\Before postprocess\Clear\Z buffer') > 0 then
Include(StageSettings[poPostprocess].ClearFlags, ClearZBuffer) else Exclude(StageSettings[poPostprocess].ClearFlags, ClearZBuffer);
if Properties.Valid('Renderer\Before postprocess\Clear\Stencil buffer') then if Properties.GetAsInteger('Renderer\Before postprocess\Clear\Stencil buffer') > 0 then
Include(StageSettings[poPostprocess].ClearFlags, ClearStencilBuffer) else Exclude(StageSettings[poPostprocess].ClearFlags, ClearStencilBuffer);
SetColorProperty(Properties, 'Renderer\Before background\Clear\Color value', StageSettings[poBackground].ClearColor);
if Properties.Valid('Renderer\Before background\Clear\Z value') then StageSettings[poBackground].ClearZ := StrToFloatDef(Properties['Renderer\Before background\Clear\Z value'], 1);
if Properties.Valid('Renderer\Before background\Clear\Stencil value') then StageSettings[poBackground].ClearStencil := Longword(Properties.GetAsInteger('Renderer\Before background\Clear\Stencil value'));
SetColorProperty(Properties, 'Renderer\Before nearest\Clear\Color value', StageSettings[poNearest].ClearColor);
if Properties.Valid('Renderer\Before nearest\Clear\Z value') then StageSettings[poNearest].ClearZ := StrToFloatDef(Properties['Renderer\Before nearest\Clear\Z value'], 1);
if Properties.Valid('Renderer\Before nearest\Clear\Stencil value') then StageSettings[poNearest].ClearStencil := Longword(Properties.GetAsInteger('Renderer\Before nearest\Clear\Stencil value'));
SetColorProperty(Properties, 'Renderer\Before postprocess\Clear\Color value', StageSettings[poPostprocess].ClearColor);
if Properties.Valid('Renderer\Before postprocess\Clear\Z value') then StageSettings[poPostprocess].ClearZ := StrToFloatDef(Properties['Renderer\Before postprocess\Clear\Z value'], 1);
if Properties.Valid('Renderer\Before postprocess\Clear\Stencil value') then StageSettings[poPostprocess].ClearStencil := Longword(Properties.GetAsInteger('Renderer\Before postprocess\Clear\Stencil value'));
if Properties.Valid('Renderer\Simultaneous light sources') then Core.SimultaneousLightSources := Properties.GetAsInteger('Renderer\Simultaneous light sources');
if Properties.Valid('Processing\Number of classes') then begin
Core.TotalProcessingClasses := MaxI(1, StrToIntDef(Properties['Processing\Number of classes'], 1));
end;
for i := 0 to Core.TotalProcessingClasses-1 do begin
s := Format('Processing\Class %D\', [i]);
if Properties.Valid(s + 'Interval, ms') then
Core.ProcessingClasses[i].Interval := Cardinal(StrToIntDef(Properties[s + 'Interval, ms'], 30)) / 1000;
if Properties.Valid(s + 'Ignore pause') then
NewIgnorePause := Properties.GetAsInteger(s + 'Ignore pause') > 0
else
NewIgnorePause := pfIgnorePause in Core.ProcessingClasses[i].Flags;