2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Implements specific proxying classes.
8
16/03/11 - Yar - Fixes after emergence of GLMaterialEx
9
23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
10
25/12/09 - DaStr - Bugfixed TGLActorProxy.RayCastIntersect()
11
in aarMorph mode (thanks Vovik)
12
22/12/09 - DaStr - Added TGLActorProxy.AnimationMode (thanks Vovik)
13
Removed TGLActorProxy.Interval (was not used)
14
18/06/08 - mrqzzz - Don't raise error when setting animation to an
15
ActorProxy and no MasterObject is defined
16
15/03/08 - DaStr - Fixup after previous update: removed all hints and
17
warnings, TGLActorProxy now has two versions of
19
06/02/08 - mrqzzz - Added a "RayCastIntersect" overload for Actorproxy
20
07/11/07 - mrqzzz - Added "OnBeforeRender" event to Actorproxy
21
allowing to apply extra transformations (f.ex: bone rotations)
22
to the referenced Actor in order to have the proxy render these changes.
23
07/11/07 - mrqzzz - Added "StoredBoneNames" property
24
07/11/07 - mrqzzz - Added "BoneMatrix(Boneidndex|boneName)" function and
25
StoreBonesMatrix property for TGLActorProxy
26
(To read each ActorProxy's individual Bone matrices,
27
f.ex to align a weapon in it's hand)
28
06/11/07 - mrqzzz - Added MaterialLibrary and LibMaterialName for TGLActorProxy
29
(allows different materials on proxy actors sharing same master)
30
06/11/07 - mrqzzz - Added public readonly properties for TGLActorProxy
31
(CurrentFrame,StartFrame,Endframe,etc..)
32
05/10/07 - DaStr - Bugfixed TGLMaterialProxy.DoRender
33
(Bugtracker ID = 1808666)
34
04/09/07 - DaStr - Added TGLMaterialProxy
35
Cleaned up this unit a bit
36
10/05/07 - DaStr - Bugfixed TGLColorProxy.DoRender
37
(thanks Paul Robello) (Bugtracker ID = 1716692)
38
28/03/07 - DaStr - Renamed parameters in some methods
39
(thanks Burkhard Carstens) (Bugtracker ID = 1678658)
40
25/02/07 - Made TGLActorProxy.SetAnimation a bit safer
41
20/02/07 - DaStr - Redeclared MasterObject of TGLColorProxy and TGLFreeFormProxy
42
Added TGLActorProxy (based on a demo published
43
on the newsgroup by don't know who...)
44
18/12/03 - Dave - Dropped "Object" from "ProxyObject" class names
45
17/12/03 - Dave - Changed class check in Octree code to Assert
46
17/12/03 - Dave+Dan - Added OctreeSphereSweep
47
06/12/03 - EG - Creation from GLScene.pas split
58
GLScene, GLVectorGeometry, GLTexture, GLVectorFileObjects,
59
GLStrings, GLRenderContextInfo, GLBaseClasses, GLMaterial,
60
OpenGLTokens, GLContext, GLVectorTypes;
63
EGLProxyException = class(Exception);
67
{ A proxy object with its own color.
68
This proxy object can have a unique color. Note that multi-material
69
objects (Freeforms linked to a material library f.i.) won't honour
71
TGLColorProxy = class(TGLProxyObject)
74
FFrontColor: TGLFaceProperties;
75
function GetMasterMaterialObject: TGLCustomSceneObject;
76
procedure SetMasterMaterialObject(const Value: TGLCustomSceneObject);
77
procedure SetFrontColor(AValue: TGLFaceProperties);
80
constructor Create(AOwner: TComponent); override;
81
destructor Destroy; override;
83
procedure DoRender(var ARci: TGLRenderContextInfo;
84
ARenderSelf, ARenderChildren: Boolean); override;
87
property FrontColor: TGLFaceProperties read FFrontColor write
89
// Redeclare as TGLCustomSceneObject.
90
property MasterObject: TGLCustomSceneObject read GetMasterMaterialObject
91
write SetMasterMaterialObject;
96
{ A proxy object with its own material.
97
This proxy object can take a mesh from one master and a materia from
99
TGLMaterialProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
102
FTempLibMaterialName: string;
103
FMasterLibMaterial: TGLLibMaterial;
104
FMaterialLibrary: TGLMaterialLibrary;
105
procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
106
function GetMasterLibMaterialName: TGLLibMaterialName;
107
procedure SetMasterLibMaterialName(const Value: TGLLibMaterialName);
108
function GetMasterMaterialObject: TGLCustomSceneObject;
109
procedure SetMasterMaterialObject(const Value: TGLCustomSceneObject);
110
// Implementing IGLMaterialLibrarySupported.
111
function GetMaterialLibrary: TGLAbstractMaterialLibrary;
114
constructor Create(AOwner: TComponent); override;
115
procedure Notification(AComponent: TComponent; Operation: TOperation);
117
destructor Destroy; override;
119
procedure DoRender(var ARci: TGLRenderContextInfo;
120
ARenderSelf, ARenderChildren: Boolean); override;
121
{ Specifies the Material, that current master object will use.
122
Provides a faster way to access FMasterLibMaterial, compared to
123
MasterLibMaterialName }
124
property MasterLibMaterial: TGLLibMaterial read FMasterLibMaterial write
125
FMasterLibMaterial stored False;
128
property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write
130
{ Specifies the Material, that current master object will use. }
131
property MasterLibMaterialName: TGLLibMaterialName read
132
GetMasterLibMaterialName write SetMasterLibMaterialName;
133
{ Redeclare as TGLCustomSceneObject. }
134
property MasterObject: TGLCustomSceneObject read GetMasterMaterialObject
135
write SetMasterMaterialObject;
140
{ A proxy object specialized for FreeForms. }
141
TGLFreeFormProxy = class(TGLProxyObject)
143
function GetMasterFreeFormObject: TGLFreeForm;
144
procedure SetMasterFreeFormObject(const Value: TGLFreeForm);
151
{ If the MasterObject is a FreeForm, you can raycast against the Octree,
152
which is alot faster. You must build the octree before using. }
153
function OctreeRayCastIntersect(const rayStart, rayVector: TVector;
154
intersectPoint: PVector = nil;
155
intersectNormal: PVector = nil): Boolean;
156
{ WARNING: This function is not yet 100% reliable with scale+rotation. }
157
function OctreeSphereSweepIntersect(const rayStart, rayVector: TVector;
158
const velocity, radius, modelscale: Single;
159
intersectPoint: PVector = nil;
160
intersectNormal: PVector = nil): Boolean;
163
// Redeclare as TGLFreeForm.
164
property MasterObject: TGLFreeForm read GetMasterFreeFormObject write
165
SetMasterFreeFormObject;
170
{ An object containing the bone matrix for TGLActorProxy. }
171
TBoneMatrixObj = class
178
// pamLoop mode was too difficalt to implement, so it was discarded ...for now.
179
// pamPlayOnce only works if Actor.AnimationMode <> aamNone.
180
TGLActorProxyAnimationMode = (pamInherited, pamNone, pamPlayOnce);
184
{ A proxy object specialized for Actors. }
185
TGLActorProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
188
FCurrentFrame: Integer;
189
FStartFrame: Integer;
192
FCurrentFrameDelta: Single;
193
FCurrentTime: TProgressTimes;
194
FAnimation: TActorAnimationName;
196
FTempLibMaterialName: string;
197
FMasterLibMaterial: TGLLibMaterial;
198
FMaterialLibrary: TGLMaterialLibrary;
200
FBonesMatrices: TStringList;
201
FStoreBonesMatrix: boolean;
202
FStoredBoneNames: TStrings;
203
FOnBeforeRender: TGLProgressEvent;
204
FAnimationMode: TGLActorProxyAnimationMode;
206
procedure SetAnimation(const Value: TActorAnimationName);
207
procedure SetMasterActorObject(const Value: TGLActor);
208
function GetMasterActorObject: TGLActor;
209
function GetLibMaterialName: TGLLibMaterialName;
210
procedure SetLibMaterialName(const Value: TGLLibMaterialName);
211
procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
212
// Implementing IGLMaterialLibrarySupported.
213
function GetMaterialLibrary: TGLAbstractMaterialLibrary;
214
procedure SetStoreBonesMatrix(const Value: boolean);
215
procedure SetStoredBoneNames(const Value: TStrings);
216
procedure SetOnBeforeRender(const Value: TGLProgressEvent);
219
procedure DoStoreBonesMatrices;
220
// stores matrices of bones of the current frame rendered
223
constructor Create(AOwner: TComponent); override;
224
destructor Destroy; override;
225
procedure Notification(AComponent: TComponent; Operation: TOperation);
227
procedure DoRender(var ARci: TGLRenderContextInfo;
228
ARenderSelf, ARenderChildren: Boolean); override;
229
procedure DoProgress(const progressTime: TProgressTimes); override;
230
property CurrentFrame: Integer read FCurrentFrame;
231
property StartFrame: Integer read FStartFrame;
232
property EndFrame: Integer read FEndFrame;
233
property CurrentFrameDelta: Single read FCurrentFrameDelta;
234
property CurrentTime: TProgressTimes read FCurrentTime;
235
{ Gets the Bones Matrix in the current animation frame.
236
(since the masterobject is shared between all proxies, each proxy will have it's bones matrices) }
237
function BoneMatrix(BoneIndex: integer): TMatrix; overload;
238
function BoneMatrix(BoneName: string): TMatrix; overload;
239
procedure BoneMatricesClear;
241
{ A standard version of the RayCastIntersect function. }
242
function RayCastIntersect(const rayStart, rayVector: TVector;
243
intersectPoint: PVector = nil;
244
intersectNormal: PVector = nil): Boolean; override;
246
{ Raycasts on self, but actually on the "RefActor" Actor.
247
Note that the "RefActor" parameter does not necessarily have to be
248
the same Actor refernced by the MasterObject property:
249
This allows to pass a low-low-low-poly Actor to raycast in the "RefActor" parameter,
250
while using a high-poly Actor in the "MasterObject" property,
251
of course we assume that the two Masterobject Actors have same animations.
253
function RayCastIntersectEx(RefActor: TGLActor; const rayStart, rayVector:
255
intersectPoint: PVector = nil;
256
intersectNormal: PVector = nil): Boolean; overload;
260
property AnimationMode: TGLActorProxyAnimationMode read FAnimationMode write
261
FAnimationMode default pamInherited;
262
property Animation: TActorAnimationName read FAnimation write SetAnimation;
263
// Redeclare as TGLActor.
264
property MasterObject: TGLActor read GetMasterActorObject write
265
SetMasterActorObject;
266
// Redeclare without pooTransformation
267
// (Don't know why it causes the object to be oriented incorrecly.)
268
property ProxyOptions default [pooEffects, pooObjects];
269
{ Specifies the MaterialLibrary, that current proxy will use. }
270
property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write
272
{ Specifies the Material, that current proxy will use. }
273
property LibMaterialName: TGLLibMaterialName read GetLibMaterialName write
275
{ Specifies if it will store the Bones Matrices, accessible via the BoneMatrix function
276
(since the masterobject is shared between all proxies, each proxy will have it's bones matrices) }
277
property StoreBonesMatrix: boolean read FStoreBonesMatrix write
279
{ Specifies the names of the bones we want the matrices to be stored. If empty, all bones will be stored
280
(since the masterobject is shared between all proxies, each proxy will have it's bones matrices) }
281
property StoredBoneNames: TStrings read FStoredBoneNames write
283
{ Event allowing to apply extra transformations (f.ex: bone rotations) to the referenced
284
Actor on order to have the proxy render these changes. }
285
property OnBeforeRender: TGLProgressEvent read FOnBeforeRender write
289
//-------------------------------------------------------------
290
//-------------------------------------------------------------
291
//-------------------------------------------------------------
293
//-------------------------------------------------------------
294
//-------------------------------------------------------------
295
//-------------------------------------------------------------
298
// ------------------ TGLColorProxy ------------------
304
constructor TGLColorProxy.Create(AOwner: TComponent);
306
inherited Create(AOwner);
307
FFrontColor := TGLFaceProperties.Create(Self);
313
destructor TGLColorProxy.Destroy;
323
procedure TGLColorProxy.DoRender(var ARci: TGLRenderContextInfo;
324
ARenderSelf, ARenderChildren: Boolean);
326
gotMaster, masterGotEffects, oldProxySubObject: Boolean;
332
gotMaster := Assigned(MasterObject);
333
masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
334
and (MasterObject.Effects.Count > 0);
337
if pooObjects in ProxyOptions then
339
oldProxySubObject := ARci.proxySubObject;
340
ARci.proxySubObject := True;
341
if pooTransformation in ProxyOptions then
342
GL.MultMatrixf(PGLFloat(MasterObject.MatrixAsAddress));
343
GetMasterMaterialObject.Material.FrontProperties.Assign(FFrontColor);
344
MasterObject.DoRender(ARci, ARenderSelf, MasterObject.Count > 0);
345
ARci.proxySubObject := oldProxySubObject;
348
// now render self stuff (our children, our effects, etc.)
349
if ARenderChildren and (Count > 0) then
350
Self.RenderChildren(0, Count - 1, ARci);
351
if masterGotEffects then
352
MasterObject.Effects.RenderPostEffects(ARci);
356
ClearStructureChanged;
359
// GetMasterMaterialObject
362
function TGLColorProxy.GetMasterMaterialObject: TGLCustomSceneObject;
364
Result := TGLCustomSceneObject(inherited MasterObject);
367
// SetMasterMaterialObject
370
procedure TGLColorProxy.SetFrontColor(AValue: TGLFaceProperties);
372
FFrontColor.Assign(AValue);
375
procedure TGLColorProxy.SetMasterMaterialObject(
376
const Value: TGLCustomSceneObject);
378
inherited SetMasterObject(Value);
382
// ------------------ TGLFreeFormProxy ------------------
385
// OctreeRayCastIntersect
388
function TGLFreeFormProxy.OctreeRayCastIntersect(const rayStart, rayVector:
390
intersectPoint: PVector = nil;
391
intersectNormal: PVector = nil): Boolean;
393
localRayStart, localRayVector: TVector;
395
if Assigned(MasterObject) then
397
SetVector(localRayStart, AbsoluteToLocal(rayStart));
398
SetVector(localRayStart, MasterObject.LocalToAbsolute(localRayStart));
399
SetVector(localRayVector, AbsoluteToLocal(rayVector));
400
SetVector(localRayVector, MasterObject.LocalToAbsolute(localRayVector));
401
NormalizeVector(localRayVector);
403
Result := GetMasterFreeFormObject.OctreeRayCastIntersect(localRayStart,
405
intersectPoint, intersectNormal);
408
if Assigned(intersectPoint) then
410
SetVector(intersectPoint^,
411
MasterObject.AbsoluteToLocal(intersectPoint^));
412
SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
414
if Assigned(intersectNormal) then
416
SetVector(intersectNormal^,
417
MasterObject.AbsoluteToLocal(intersectNormal^));
418
SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
426
// OctreeSphereSweepIntersect
429
function TGLFreeFormProxy.OctreeSphereSweepIntersect(const rayStart, rayVector:
431
const velocity, radius, modelscale: Single;
432
intersectPoint: PVector = nil;
433
intersectNormal: PVector = nil): Boolean;
435
localRayStart, localRayVector: TVector;
436
localVelocity, localRadius: single;
439
if Assigned(MasterObject) then
441
localVelocity := velocity * modelscale;
442
localRadius := radius * modelscale;
444
SetVector(localRayStart, AbsoluteToLocal(rayStart));
445
SetVector(localRayStart, MasterObject.LocalToAbsolute(localRayStart));
446
SetVector(localRayVector, AbsoluteToLocal(rayVector));
447
SetVector(localRayVector, MasterObject.LocalToAbsolute(localRayVector));
448
NormalizeVector(localRayVector);
450
Result := GetMasterFreeFormObject.OctreeSphereSweepIntersect(localRayStart,
452
localVelocity, localRadius,
453
intersectPoint, intersectNormal);
456
if Assigned(intersectPoint) then
458
SetVector(intersectPoint^,
459
MasterObject.AbsoluteToLocal(intersectPoint^));
460
SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
462
if Assigned(intersectNormal) then
464
SetVector(intersectNormal^,
465
MasterObject.AbsoluteToLocal(intersectNormal^));
466
SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
473
// GetMasterFreeFormObject
476
function TGLFreeFormProxy.GetMasterFreeFormObject: TGLFreeForm;
478
Result := TGLFreeForm(inherited MasterObject);
481
// SetMasterFreeFormObject
484
procedure TGLFreeFormProxy.SetMasterFreeFormObject(
485
const Value: TGLFreeForm);
487
inherited SetMasterObject(Value);
491
// ------------------ TGLActorProxy ------------------
497
function TGLActorProxy.BoneMatrix(BoneIndex: integer): TMatrix;
499
if BoneIndex < FBonesMatrices.count then
500
result := TBoneMatrixObj(FBonesMatrices.Objects[BoneIndex]).Matrix;
503
function TGLActorProxy.BoneMatrix(BoneName: string): TMatrix;
507
i := FBonesMatrices.IndexOf(BoneName);
509
result := TBoneMatrixObj(FBonesMatrices.Objects[i]).Matrix;
512
procedure TGLActorProxy.BoneMatricesClear;
516
for i := 0 to FBonesMatrices.Count - 1 do
518
TBoneMatrixObj(FBonesMatrices.Objects[i]).free;
520
FBonesMatrices.Clear;
523
constructor TGLActorProxy.Create(AOwner: TComponent);
526
FAnimationMode := pamInherited;
527
ProxyOptions := ProxyOptions - [pooTransformation];
528
FBonesMatrices := TStringList.create;
529
FStoredBoneNames := TStringList.create;
530
FStoreBonesMatrix := false;
531
// default is false to speed up a little if we don't need bones info
537
destructor TGLActorProxy.Destroy;
541
FStoredBoneNames.free;
545
procedure TGLActorProxy.DoProgress(const progressTime: TProgressTimes);
548
FCurrentTime := progressTime;
554
procedure TGLActorProxy.DoRender(var ARci: TGLRenderContextInfo; ARenderSelf,
555
ARenderChildren: Boolean);
557
// TGLActorProxy specific
560
// General proxy stuff.
561
gotMaster, masterGotEffects, oldProxySubObject: Boolean;
562
MasterActor: TGLActor;
565
MasterActor := GetMasterActorObject;
566
gotMaster := MasterActor <> nil;
567
masterGotEffects := gotMaster and (pooEffects in ProxyOptions) and
568
(MasterObject.Effects.Count > 0);
571
if pooObjects in ProxyOptions then
573
oldProxySubObject := ARci.proxySubObject;
574
ARci.proxySubObject := True;
575
if pooTransformation in ProxyOptions then
576
with ARci.PipelineTransformation do
577
ModelMatrix := MatrixMultiply(MasterActor.Matrix, ModelMatrix);
579
// At last TGLActorProxy specific stuff!
582
cfd := CurrentFrameDelta;
587
case FAnimationMode of
588
pamInherited: CurrentFrameDelta := FCurrentFrameDelta;
591
if (FLastFrame <> FEndFrame - 1) then
592
CurrentFrameDelta := FCurrentFrameDelta
595
FCurrentFrameDelta := 0;
596
FAnimationMode := pamNone;
599
pamNone: CurrentFrameDelta := 0;
601
Assert(False, glsUnknownType);
604
SetCurrentFrameDirect(FCurrentFrame);
605
FLastFrame := FCurrentFrame;
606
StartFrame := FStartFrame;
607
EndFrame := FEndFrame;
609
if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
610
MasterActor.Material.QuickAssignMaterial(
611
FMaterialLibrary, FMasterLibMaterial);
613
DoProgress(FCurrentTime);
615
if Assigned(FOnBeforeRender) then
616
FOnBeforeRender(self, FCurrentTime.deltaTime, FCurrentTime.newTime);
618
DoRender(ARci, ARenderSelf, Count > 0);
620
// Stores Bones matrices of the current frame
621
if (FStoreBonesMatrix) and (MasterActor.Skeleton <> nil) then
622
DoStoreBonesMatrices;
624
FCurrentFrameDelta := CurrentFrameDelta;
625
FCurrentFrame := CurrentFrame;
626
CurrentFrameDelta := cfd;
627
SetCurrentFrameDirect(cf);
632
ARci.proxySubObject := oldProxySubObject;
635
// now render self stuff (our children, our effects, etc.)
636
oldProxySubObject := ARci.proxySubObject;
637
ARci.proxySubObject := True;
638
if ARenderChildren and (Count > 0) then
639
Self.RenderChildren(0, Count - 1, ARci);
640
if masterGotEffects then
641
MasterActor.Effects.RenderPostEffects(ARci);
642
ARci.proxySubObject := oldProxySubObject;
644
ClearStructureChanged;
648
procedure TGLActorProxy.DoStoreBonesMatrices;
652
Bone: TGLSkeletonBone;
654
if FStoredBoneNames.count > 0 then
656
// If we specified some bone names, only those bones matrices will be stored (save some cpu)
657
if FBonesMatrices.Count < FStoredBoneNames.Count then
659
n := FBonesMatrices.Count;
660
for i := n to FStoredBoneNames.Count - 1 do
662
Bone := MasterObject.Skeleton.BoneByName(FStoredBoneNames[i]);
665
Bmo := TBoneMatrixObj.Create;
666
Bmo.BoneName := Bone.Name;
667
Bmo.BoneIndex := Bone.BoneID;
668
FBonesMatrices.AddObject(Bone.Name, Bmo);
676
// Add (missing) TBoneMatrixObjects (actually ony 1st time) from all bones in skeleton
677
if FBonesMatrices.Count < MasterObject.Skeleton.BoneCount - 1 then
678
// note : BoneCount actually returns 1 count more.
680
n := FBonesMatrices.Count;
681
for i := n to MasterObject.Skeleton.BoneCount - 2 do
682
// note : BoneCount actually returns 1 count more.
684
Bone := MasterObject.Skeleton.BoneByID(i);
687
Bmo := TBoneMatrixObj.Create;
688
Bmo.BoneName := Bone.Name;
689
Bmo.BoneIndex := Bone.BoneID;
690
FBonesMatrices.AddObject(Bone.Name, Bmo);
697
// fill FBonesMatrices list
698
for i := 0 to FBonesMatrices.count - 1 do
700
Bmo := TBoneMatrixObj(FBonesMatrices.Objects[i]);
701
Bmo.Matrix := MasterObject.Skeleton.BoneByID(Bmo.BoneIndex).GlobalMatrix;
708
function TGLActorProxy.GetMasterActorObject: TGLActor;
710
Result := TGLActor(inherited MasterObject);
713
function TGLActorProxy.GetLibMaterialName: TGLLibMaterialName;
715
Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
717
Result := FTempLibMaterialName;
720
function TGLActorProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
722
Result := FMaterialLibrary;
725
procedure TGLActorProxy.Notification(AComponent: TComponent;
726
Operation: TOperation);
729
if Operation = opRemove then
731
if AComponent = FMaterialLibrary then
732
FMaterialLibrary := nil;
736
function TGLActorProxy.RayCastIntersect(const rayStart, rayVector: TVector;
737
intersectPoint, intersectNormal: PVector): Boolean;
739
if MasterObject <> nil then
740
Result := RayCastIntersectEx(GetMasterActorObject, rayStart, rayVector,
741
intersectPoint, intersectNormal)
743
Result := inherited RayCastIntersect(rayStart, rayVector, intersectPoint,
747
// Gain access to TGLDummyActor.DoAnimate().
749
TGLDummyActor = class(TGLActor);
751
function TGLActorProxy.RayCastIntersectEx(RefActor: TGLActor; const rayStart,
752
rayVector: TVector; intersectPoint, intersectNormal: PVector): Boolean;
754
localRayStart, localRayVector: TVector;
757
HaspooTransformation: boolean;
759
// Set RefObject frame as current ActorProxy frame
762
// VARS FOR ACTOR TO ASSUME ACTORPROXY CURRENT ANIMATION FRAME
763
cfd := RefActor.CurrentFrameDelta;
764
cf := RefActor.CurrentFrame;
765
sf := RefActor.startframe;
766
ef := RefActor.endframe;
767
RefActor.CurrentFrameDelta := self.CurrentFrameDelta;
768
RefActor.SetCurrentFrameDirect(self.CurrentFrame);
769
RefActor.StartFrame := self.StartFrame;
770
RefActor.EndFrame := self.EndFrame;
771
RefActor.CurrentFrame := self.CurrentFrame;
773
// FORCE ACTOR TO ASSUME ACTORPROXY CURRENT ANIMATION FRAME
774
TGLDummyActor(RefActor).DoAnimate();
776
HaspooTransformation := pooTransformation in self.ProxyOptions;
778
// transform RAYSTART
779
SetVector(localRayStart, self.AbsoluteToLocal(rayStart));
780
if not HaspooTransformation then
781
SetVector(localRayStart, RefActor.LocalToAbsolute(localRayStart));
783
// transform RAYVECTOR
784
SetVector(localRayVector, self.AbsoluteToLocal(rayVector));
785
if not HaspooTransformation then
786
SetVector(localRayVector, RefActor.LocalToAbsolute(localRayVector));
788
NormalizeVector(localRayVector);
790
Result := RefActor.RayCastIntersect(localRayStart, localRayVector,
791
intersectPoint, intersectNormal);
794
if Assigned(intersectPoint) then
796
if not HaspooTransformation then
797
SetVector(intersectPoint^, RefActor.AbsoluteToLocal(intersectPoint^));
798
SetVector(intersectPoint^, self.LocalToAbsolute(intersectPoint^));
800
if Assigned(intersectNormal) then
802
if not HaspooTransformation then
803
SetVector(intersectNormal^,
804
RefActor.AbsoluteToLocal(intersectNormal^));
805
SetVector(intersectNormal^, self.LocalToAbsolute(intersectNormal^));
809
// Return RefObject to it's old time
810
CurrentFrameDelta := cfd;
811
SetCurrentFrameDirect(cf);
816
// REVERT ACTOR TO ASSUME ORIGINAL ANIMATION FRAME
817
TGLDummyActor(RefActor).DoAnimate();
824
procedure TGLActorProxy.SetAnimation(const Value: TActorAnimationName);
826
anAnimation: TActorAnimation;
828
// We first assign the value (for persistency support), then check it.
831
if Assigned(MasterObject) then
833
anAnimation := GetMasterActorObject.Animations.FindName(Value);
834
if Assigned(anAnimation) then
836
FStartFrame := anAnimation.StartFrame;
837
FEndFrame := anAnimation.EndFrame;
838
FCurrentFrame := FStartFrame;
839
FLastFrame := FCurrentFrame;
844
procedure TGLActorProxy.SetStoredBoneNames(const Value: TStrings);
847
FStoredBoneNames.Assign(Value);
853
procedure TGLActorProxy.SetMasterActorObject(const Value: TGLActor);
855
inherited SetMasterObject(Value);
859
procedure TGLActorProxy.SetLibMaterialName(
860
const Value: TGLLibMaterialName);
862
if FMaterialLibrary = nil then
864
FTempLibMaterialName := Value;
865
if not (csLoading in ComponentState) then
866
raise ETexture.Create(glsErrorEx + glsMatLibNotDefined);
870
FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
871
FTempLibMaterialName := '';
875
procedure TGLActorProxy.SetMaterialLibrary(const Value: TGLMaterialLibrary);
877
if FMaterialLibrary <> Value then
879
if FMaterialLibrary <> nil then
880
FMaterialLibrary.RemoveFreeNotification(Self);
881
FMaterialLibrary := Value;
883
if FMaterialLibrary <> nil then
885
FMaterialLibrary.FreeNotification(Self);
886
if FTempLibMaterialName <> '' then
887
SetLibMaterialName(FTempLibMaterialName);
891
FTempLibMaterialName := '';
896
procedure TGLActorProxy.SetOnBeforeRender(const Value: TGLProgressEvent);
898
FOnBeforeRender := Value;
901
procedure TGLActorProxy.SetStoreBonesMatrix(const Value: boolean);
903
FStoreBonesMatrix := Value;
908
constructor TGLMaterialProxy.Create(AOwner: TComponent);
914
destructor TGLMaterialProxy.Destroy;
920
procedure TGLMaterialProxy.DoRender(var ARci: TGLRenderContextInfo;
921
ARenderSelf, ARenderChildren: Boolean);
923
gotMaster, masterGotEffects, oldProxySubObject: Boolean;
929
gotMaster := Assigned(MasterObject);
930
masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
931
and (MasterObject.Effects.Count > 0);
934
if pooObjects in ProxyOptions then
936
oldProxySubObject := ARci.proxySubObject;
937
ARci.proxySubObject := True;
938
if pooTransformation in ProxyOptions then
939
GL.MultMatrixf(PGLFloat(MasterObject.MatrixAsAddress));
941
if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
942
GetMasterMaterialObject.Material.QuickAssignMaterial(
943
FMaterialLibrary, FMasterLibMaterial);
945
MasterObject.DoRender(ARci, ARenderSelf, MasterObject.Count > 0);
946
ARci.proxySubObject := oldProxySubObject;
949
// now render self stuff (our children, our effects, etc.)
950
if ARenderChildren and (Count > 0) then
951
Self.RenderChildren(0, Count - 1, ARci);
952
if masterGotEffects then
953
MasterObject.Effects.RenderPostEffects(ARci);
957
ClearStructureChanged;
960
function TGLMaterialProxy.GetMasterLibMaterialName: TGLLibMaterialName;
962
Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
964
Result := FTempLibMaterialName;
967
function TGLMaterialProxy.GetMasterMaterialObject: TGLCustomSceneObject;
969
Result := TGLCustomSceneObject(inherited MasterObject);
972
function TGLMaterialProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
974
Result := FMaterialLibrary;
977
procedure TGLMaterialProxy.Notification(AComponent: TComponent;
978
Operation: TOperation);
981
if Operation = opRemove then
983
if AComponent = FMaterialLibrary then
984
FMaterialLibrary := nil;
988
procedure TGLMaterialProxy.SetMasterLibMaterialName(
989
const Value: TGLLibMaterialName);
991
if FMaterialLibrary = nil then
993
FTempLibMaterialName := Value;
994
if not (csLoading in ComponentState) then
995
raise ETexture.Create(glsErrorEx + glsMatLibNotDefined);
999
FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
1000
FTempLibMaterialName := '';
1004
procedure TGLMaterialProxy.SetMasterMaterialObject(
1005
const Value: TGLCustomSceneObject);
1007
inherited SetMasterObject(Value);
1010
procedure TGLMaterialProxy.SetMaterialLibrary(
1011
const Value: TGLMaterialLibrary);
1013
if FMaterialLibrary <> Value then
1015
if FMaterialLibrary <> nil then
1016
FMaterialLibrary.RemoveFreeNotification(Self);
1017
FMaterialLibrary := Value;
1019
if FMaterialLibrary <> nil then
1021
FMaterialLibrary.FreeNotification(Self);
1022
if FTempLibMaterialName <> '' then
1023
SetMasterLibMaterialName(FTempLibMaterialName);
1027
FTempLibMaterialName := '';
1032
//-------------------------------------------------------------
1033
//-------------------------------------------------------------
1034
//-------------------------------------------------------------
1036
//-------------------------------------------------------------
1037
//-------------------------------------------------------------
1038
//-------------------------------------------------------------
1040
RegisterClasses([TGLColorProxy, TGLFreeFormProxy, TGLActorProxy,