LZScene

Форк
0
/
GLProxyObjects.pas 
1043 строки · 33.9 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   Implements specific proxying classes.
6

7
  History :  
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
18
                              RayCastIntersect()
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
48
    
49
}
50
unit GLProxyObjects;
51

52
interface
53

54
{$I GLScene.inc}
55

56
uses
57
  Classes, SysUtils,
58
  GLScene,  GLVectorGeometry,  GLTexture,  GLVectorFileObjects,
59
  GLStrings,  GLRenderContextInfo,  GLBaseClasses, GLMaterial,
60
  OpenGLTokens,  GLContext,  GLVectorTypes;
61

62
type
63
  EGLProxyException = class(Exception);
64

65
  // TGLColorProxy
66
  //
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
70
     the color. }
71
  TGLColorProxy = class(TGLProxyObject)
72
  private
73
     
74
    FFrontColor: TGLFaceProperties;
75
    function GetMasterMaterialObject: TGLCustomSceneObject;
76
    procedure SetMasterMaterialObject(const Value: TGLCustomSceneObject);
77
    procedure SetFrontColor(AValue: TGLFaceProperties);
78
  public
79
     
80
    constructor Create(AOwner: TComponent); override;
81
    destructor Destroy; override;
82

83
    procedure DoRender(var ARci: TGLRenderContextInfo;
84
      ARenderSelf, ARenderChildren: Boolean); override;
85
  published
86
     
87
    property FrontColor: TGLFaceProperties read FFrontColor write
88
      SetFrontColor;
89
    // Redeclare as TGLCustomSceneObject.
90
    property MasterObject: TGLCustomSceneObject read GetMasterMaterialObject
91
      write SetMasterMaterialObject;
92
  end;
93

94
  // TGLMaterialProxy
95
  //
96
  { A proxy object with its own material.
97
     This proxy object can take a mesh from one master and a materia from
98
     a material library. }
99
  TGLMaterialProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
100
  private
101
     
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;
112
  public
113
     
114
    constructor Create(AOwner: TComponent); override;
115
    procedure Notification(AComponent: TComponent; Operation: TOperation);
116
      override;
117
    destructor Destroy; override;
118

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;
126
  published
127
     
128
    property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write
129
      SetMaterialLibrary;
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;
136
  end;
137

138
  // TGLFreeFormProxy
139
  //
140
  { A proxy object specialized for FreeForms. }
141
  TGLFreeFormProxy = class(TGLProxyObject)
142
  private
143
    function GetMasterFreeFormObject: TGLFreeForm;
144
    procedure SetMasterFreeFormObject(const Value: TGLFreeForm);
145
  protected
146
     
147

148
  public
149
     
150

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;
161
  published
162
     
163
   // Redeclare as TGLFreeForm.
164
    property MasterObject: TGLFreeForm read GetMasterFreeFormObject write
165
      SetMasterFreeFormObject;
166
  end;
167

168
  // TBoneMatrixObj
169
  //
170
  { An object containing the bone matrix for TGLActorProxy. }
171
  TBoneMatrixObj = class
172
  public
173
    Matrix: TMatrix;
174
    BoneName: string;
175
    BoneIndex: integer;
176
  end;
177

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);
181

182
  // TGLActorProxy
183
  //
184
  { A proxy object specialized for Actors. }
185
  TGLActorProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
186
  private
187
     
188
    FCurrentFrame: Integer;
189
    FStartFrame: Integer;
190
    FEndFrame: Integer;
191
    FLastFrame: Integer;
192
    FCurrentFrameDelta: Single;
193
    FCurrentTime: TProgressTimes;
194
    FAnimation: TActorAnimationName;
195

196
    FTempLibMaterialName: string;
197
    FMasterLibMaterial: TGLLibMaterial;
198
    FMaterialLibrary: TGLMaterialLibrary;
199

200
    FBonesMatrices: TStringList;
201
    FStoreBonesMatrix: boolean;
202
    FStoredBoneNames: TStrings;
203
    FOnBeforeRender: TGLProgressEvent;
204
    FAnimationMode: TGLActorProxyAnimationMode;
205

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);
217
  protected
218
     
219
    procedure DoStoreBonesMatrices;
220
      // stores matrices of bones of the current frame rendered
221
  public
222
     
223
    constructor Create(AOwner: TComponent); override;
224
    destructor Destroy; override;
225
    procedure Notification(AComponent: TComponent; Operation: TOperation);
226
      override;
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;
240

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;
245

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.
252
      }
253
    function RayCastIntersectEx(RefActor: TGLActor; const rayStart, rayVector:
254
      TVector;
255
      intersectPoint: PVector = nil;
256
      intersectNormal: PVector = nil): Boolean; overload;
257

258
  published
259
     
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
271
      SetMaterialLibrary;
272
    { Specifies the Material, that current proxy will use. }
273
    property LibMaterialName: TGLLibMaterialName read GetLibMaterialName write
274
      SetLibMaterialName;
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
278
      SetStoreBonesMatrix;
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
282
      SetStoredBoneNames;
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
286
      SetOnBeforeRender;
287
  end;
288

289
  //-------------------------------------------------------------
290
  //-------------------------------------------------------------
291
  //-------------------------------------------------------------
292
implementation
293
//-------------------------------------------------------------
294
//-------------------------------------------------------------
295
//-------------------------------------------------------------
296

297
// ------------------
298
// ------------------ TGLColorProxy ------------------
299
// ------------------
300

301
// Create
302
//
303

304
constructor TGLColorProxy.Create(AOwner: TComponent);
305
begin
306
  inherited Create(AOwner);
307
  FFrontColor := TGLFaceProperties.Create(Self);
308
end;
309

310
// Destroy
311
//
312

313
destructor TGLColorProxy.Destroy;
314
begin
315
  FFrontColor.Free;
316

317
  inherited Destroy;
318
end;
319

320
// Render
321
//
322

323
procedure TGLColorProxy.DoRender(var ARci: TGLRenderContextInfo;
324
  ARenderSelf, ARenderChildren: Boolean);
325
var
326
  gotMaster, masterGotEffects, oldProxySubObject: Boolean;
327
begin
328
  if FRendering then
329
    Exit;
330
  FRendering := True;
331
  try
332
    gotMaster := Assigned(MasterObject);
333
    masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
334
      and (MasterObject.Effects.Count > 0);
335
    if gotMaster then
336
    begin
337
      if pooObjects in ProxyOptions then
338
      begin
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;
346
      end;
347
    end;
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);
353
  finally
354
    FRendering := False;
355
  end;
356
  ClearStructureChanged;
357
end;
358

359
// GetMasterMaterialObject
360
//
361

362
function TGLColorProxy.GetMasterMaterialObject: TGLCustomSceneObject;
363
begin
364
  Result := TGLCustomSceneObject(inherited MasterObject);
365
end;
366

367
// SetMasterMaterialObject
368
//
369

370
procedure TGLColorProxy.SetFrontColor(AValue: TGLFaceProperties);
371
begin
372
  FFrontColor.Assign(AValue);
373
end;
374

375
procedure TGLColorProxy.SetMasterMaterialObject(
376
  const Value: TGLCustomSceneObject);
377
begin
378
  inherited SetMasterObject(Value);
379
end;
380

381
// ------------------
382
// ------------------ TGLFreeFormProxy ------------------
383
// ------------------
384

385
// OctreeRayCastIntersect
386
//
387

388
function TGLFreeFormProxy.OctreeRayCastIntersect(const rayStart, rayVector:
389
  TVector;
390
  intersectPoint: PVector = nil;
391
  intersectNormal: PVector = nil): Boolean;
392
var
393
  localRayStart, localRayVector: TVector;
394
begin
395
  if Assigned(MasterObject) then
396
  begin
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);
402

403
    Result := GetMasterFreeFormObject.OctreeRayCastIntersect(localRayStart,
404
      localRayVector,
405
      intersectPoint, intersectNormal);
406
    if Result then
407
    begin
408
      if Assigned(intersectPoint) then
409
      begin
410
        SetVector(intersectPoint^,
411
          MasterObject.AbsoluteToLocal(intersectPoint^));
412
        SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
413
      end;
414
      if Assigned(intersectNormal) then
415
      begin
416
        SetVector(intersectNormal^,
417
          MasterObject.AbsoluteToLocal(intersectNormal^));
418
        SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
419
      end;
420
    end;
421
  end
422
  else
423
    Result := False;
424
end;
425

426
// OctreeSphereSweepIntersect
427
//
428

429
function TGLFreeFormProxy.OctreeSphereSweepIntersect(const rayStart, rayVector:
430
  TVector;
431
  const velocity, radius, modelscale: Single;
432
  intersectPoint: PVector = nil;
433
  intersectNormal: PVector = nil): Boolean;
434
var
435
  localRayStart, localRayVector: TVector;
436
  localVelocity, localRadius: single;
437
begin
438
  Result := False;
439
  if Assigned(MasterObject) then
440
  begin
441
    localVelocity := velocity * modelscale;
442
    localRadius := radius * modelscale;
443

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);
449

450
    Result := GetMasterFreeFormObject.OctreeSphereSweepIntersect(localRayStart,
451
      localRayVector,
452
      localVelocity, localRadius,
453
      intersectPoint, intersectNormal);
454
    if Result then
455
    begin
456
      if Assigned(intersectPoint) then
457
      begin
458
        SetVector(intersectPoint^,
459
          MasterObject.AbsoluteToLocal(intersectPoint^));
460
        SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
461
      end;
462
      if Assigned(intersectNormal) then
463
      begin
464
        SetVector(intersectNormal^,
465
          MasterObject.AbsoluteToLocal(intersectNormal^));
466
        SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
467
      end;
468
    end;
469

470
  end;
471
end;
472

473
// GetMasterFreeFormObject
474
//
475

476
function TGLFreeFormProxy.GetMasterFreeFormObject: TGLFreeForm;
477
begin
478
  Result := TGLFreeForm(inherited MasterObject);
479
end;
480

481
// SetMasterFreeFormObject
482
//
483

484
procedure TGLFreeFormProxy.SetMasterFreeFormObject(
485
  const Value: TGLFreeForm);
486
begin
487
  inherited SetMasterObject(Value);
488
end;
489

490
// ------------------
491
// ------------------ TGLActorProxy ------------------
492
// ------------------
493

494
// Create
495
//
496

497
function TGLActorProxy.BoneMatrix(BoneIndex: integer): TMatrix;
498
begin
499
  if BoneIndex < FBonesMatrices.count then
500
    result := TBoneMatrixObj(FBonesMatrices.Objects[BoneIndex]).Matrix;
501
end;
502

503
function TGLActorProxy.BoneMatrix(BoneName: string): TMatrix;
504
var
505
  i: Integer;
506
begin
507
  i := FBonesMatrices.IndexOf(BoneName);
508
  if i > -1 then
509
    result := TBoneMatrixObj(FBonesMatrices.Objects[i]).Matrix;
510
end;
511

512
procedure TGLActorProxy.BoneMatricesClear;
513
var
514
  i: Integer;
515
begin
516
  for i := 0 to FBonesMatrices.Count - 1 do
517
  begin
518
    TBoneMatrixObj(FBonesMatrices.Objects[i]).free;
519
  end;
520
  FBonesMatrices.Clear;
521
end;
522

523
constructor TGLActorProxy.Create(AOwner: TComponent);
524
begin
525
  inherited;
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
532
end;
533

534
// DoProgress
535
//
536

537
destructor TGLActorProxy.Destroy;
538
begin
539
  BoneMatricesClear;
540
  FBonesMatrices.free;
541
  FStoredBoneNames.free;
542
  inherited;
543
end;
544

545
procedure TGLActorProxy.DoProgress(const progressTime: TProgressTimes);
546
begin
547
  inherited;
548
  FCurrentTime := progressTime;
549
end;
550

551
// DoRender
552
//
553

554
procedure TGLActorProxy.DoRender(var ARci: TGLRenderContextInfo; ARenderSelf,
555
  ARenderChildren: Boolean);
556
var
557
  // TGLActorProxy specific
558
  cf, sf, ef: Integer;
559
  cfd: Single;
560
  // General proxy stuff.
561
  gotMaster, masterGotEffects, oldProxySubObject: Boolean;
562
  MasterActor: TGLActor;
563
begin
564
  try
565
    MasterActor := GetMasterActorObject;
566
    gotMaster := MasterActor <> nil;
567
    masterGotEffects := gotMaster and (pooEffects in ProxyOptions) and
568
      (MasterObject.Effects.Count > 0);
569
    if gotMaster then
570
    begin
571
      if pooObjects in ProxyOptions then
572
      begin
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);
578

579
        // At last TGLActorProxy specific stuff!
580
        with MasterActor do
581
        begin
582
          cfd := CurrentFrameDelta;
583
          cf := CurrentFrame;
584
          sf := startframe;
585
          ef := endframe;
586

587
          case FAnimationMode of
588
            pamInherited: CurrentFrameDelta := FCurrentFrameDelta;
589
            pamPlayOnce:
590
              begin
591
                if (FLastFrame <> FEndFrame - 1) then
592
                  CurrentFrameDelta := FCurrentFrameDelta
593
                else
594
                begin
595
                  FCurrentFrameDelta := 0;
596
                  FAnimationMode := pamNone;
597
                end;
598
              end;
599
            pamNone: CurrentFrameDelta := 0;
600
          else
601
            Assert(False, glsUnknownType);
602
          end;
603

604
          SetCurrentFrameDirect(FCurrentFrame);
605
          FLastFrame := FCurrentFrame;
606
          StartFrame := FStartFrame;
607
          EndFrame := FEndFrame;
608

609
          if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
610
            MasterActor.Material.QuickAssignMaterial(
611
              FMaterialLibrary, FMasterLibMaterial);
612

613
          DoProgress(FCurrentTime);
614

615
          if Assigned(FOnBeforeRender) then
616
            FOnBeforeRender(self, FCurrentTime.deltaTime, FCurrentTime.newTime);
617

618
          DoRender(ARci, ARenderSelf, Count > 0);
619

620
          // Stores Bones matrices of the current frame
621
          if (FStoreBonesMatrix) and (MasterActor.Skeleton <> nil) then
622
            DoStoreBonesMatrices;
623

624
          FCurrentFrameDelta := CurrentFrameDelta;
625
          FCurrentFrame := CurrentFrame;
626
          CurrentFrameDelta := cfd;
627
          SetCurrentFrameDirect(cf);
628
          startframe := sf;
629
          endframe := ef;
630
        end;
631

632
        ARci.proxySubObject := oldProxySubObject;
633
      end;
634
    end;
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;
643
  finally
644
    ClearStructureChanged;
645
  end;
646
end;
647

648
procedure TGLActorProxy.DoStoreBonesMatrices;
649
var
650
  i, n: integer;
651
  Bmo: TBoneMatrixObj;
652
  Bone: TGLSkeletonBone;
653
begin
654
  if FStoredBoneNames.count > 0 then
655
  begin
656
    // If we specified some bone names, only those bones matrices will be stored (save some cpu)
657
    if FBonesMatrices.Count < FStoredBoneNames.Count then
658
    begin
659
      n := FBonesMatrices.Count;
660
      for i := n to FStoredBoneNames.Count - 1 do
661
      begin
662
        Bone := MasterObject.Skeleton.BoneByName(FStoredBoneNames[i]);
663
        if Bone <> nil then
664
        begin
665
          Bmo := TBoneMatrixObj.Create;
666
          Bmo.BoneName := Bone.Name;
667
          Bmo.BoneIndex := Bone.BoneID;
668
          FBonesMatrices.AddObject(Bone.Name, Bmo);
669
        end;
670

671
      end;
672
    end;
673
  end
674
  else
675
  begin
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.
679
    begin
680
      n := FBonesMatrices.Count;
681
      for i := n to MasterObject.Skeleton.BoneCount - 2 do
682
        // note : BoneCount actually returns 1 count more.
683
      begin
684
        Bone := MasterObject.Skeleton.BoneByID(i);
685
        if Bone <> nil then
686
        begin
687
          Bmo := TBoneMatrixObj.Create;
688
          Bmo.BoneName := Bone.Name;
689
          Bmo.BoneIndex := Bone.BoneID;
690
          FBonesMatrices.AddObject(Bone.Name, Bmo);
691
        end;
692

693
      end;
694
    end;
695
  end;
696

697
  // fill FBonesMatrices list
698
  for i := 0 to FBonesMatrices.count - 1 do
699
  begin
700
    Bmo := TBoneMatrixObj(FBonesMatrices.Objects[i]);
701
    Bmo.Matrix := MasterObject.Skeleton.BoneByID(Bmo.BoneIndex).GlobalMatrix;
702
  end;
703
end;
704

705
// GetMasterObject
706
//
707

708
function TGLActorProxy.GetMasterActorObject: TGLActor;
709
begin
710
  Result := TGLActor(inherited MasterObject);
711
end;
712

713
function TGLActorProxy.GetLibMaterialName: TGLLibMaterialName;
714
begin
715
  Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
716
  if Result = '' then
717
    Result := FTempLibMaterialName;
718
end;
719

720
function TGLActorProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
721
begin
722
  Result := FMaterialLibrary;
723
end;
724

725
procedure TGLActorProxy.Notification(AComponent: TComponent;
726
  Operation: TOperation);
727
begin
728
  inherited;
729
  if Operation = opRemove then
730
  begin
731
    if AComponent = FMaterialLibrary then
732
      FMaterialLibrary := nil;
733
  end;
734
end;
735

736
function TGLActorProxy.RayCastIntersect(const rayStart, rayVector: TVector;
737
  intersectPoint, intersectNormal: PVector): Boolean;
738
begin
739
  if MasterObject <> nil then
740
    Result := RayCastIntersectEx(GetMasterActorObject, rayStart, rayVector,
741
      intersectPoint, intersectNormal)
742
  else
743
    Result := inherited RayCastIntersect(rayStart, rayVector, intersectPoint,
744
      intersectNormal);
745
end;
746

747
// Gain access to TGLDummyActor.DoAnimate().
748
type
749
  TGLDummyActor = class(TGLActor);
750

751
function TGLActorProxy.RayCastIntersectEx(RefActor: TGLActor; const rayStart,
752
  rayVector: TVector; intersectPoint, intersectNormal: PVector): Boolean;
753
var
754
  localRayStart, localRayVector: TVector;
755
  cf, sf, ef: Integer;
756
  cfd: Single;
757
  HaspooTransformation: boolean;
758
begin
759
  // Set RefObject frame as current ActorProxy frame
760
  with RefActor do
761
  begin
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;
772

773
    // FORCE ACTOR TO ASSUME ACTORPROXY CURRENT ANIMATION FRAME
774
    TGLDummyActor(RefActor).DoAnimate();
775

776
    HaspooTransformation := pooTransformation in self.ProxyOptions;
777

778
    // transform RAYSTART
779
    SetVector(localRayStart, self.AbsoluteToLocal(rayStart));
780
    if not HaspooTransformation then
781
      SetVector(localRayStart, RefActor.LocalToAbsolute(localRayStart));
782

783
    // transform RAYVECTOR
784
    SetVector(localRayVector, self.AbsoluteToLocal(rayVector));
785
    if not HaspooTransformation then
786
      SetVector(localRayVector, RefActor.LocalToAbsolute(localRayVector));
787

788
    NormalizeVector(localRayVector);
789

790
    Result := RefActor.RayCastIntersect(localRayStart, localRayVector,
791
      intersectPoint, intersectNormal);
792
    if Result then
793
    begin
794
      if Assigned(intersectPoint) then
795
      begin
796
        if not HaspooTransformation then
797
          SetVector(intersectPoint^, RefActor.AbsoluteToLocal(intersectPoint^));
798
        SetVector(intersectPoint^, self.LocalToAbsolute(intersectPoint^));
799
      end;
800
      if Assigned(intersectNormal) then
801
      begin
802
        if not HaspooTransformation then
803
          SetVector(intersectNormal^,
804
            RefActor.AbsoluteToLocal(intersectNormal^));
805
        SetVector(intersectNormal^, self.LocalToAbsolute(intersectNormal^));
806
      end;
807
    end;
808

809
    // Return RefObject to it's old time
810
    CurrentFrameDelta := cfd;
811
    SetCurrentFrameDirect(cf);
812
    CurrentFrame := cf;
813
    startframe := sf;
814
    endframe := ef;
815

816
    // REVERT ACTOR TO ASSUME ORIGINAL ANIMATION FRAME
817
    TGLDummyActor(RefActor).DoAnimate();
818
  end;
819
end;
820

821
// SetAnimation
822
//
823

824
procedure TGLActorProxy.SetAnimation(const Value: TActorAnimationName);
825
var
826
  anAnimation: TActorAnimation;
827
begin
828
  // We first assign the value (for persistency support), then check it.
829
  FAnimation := Value;
830

831
  if Assigned(MasterObject) then
832
  begin
833
    anAnimation := GetMasterActorObject.Animations.FindName(Value);
834
    if Assigned(anAnimation) then
835
    begin
836
      FStartFrame := anAnimation.StartFrame;
837
      FEndFrame := anAnimation.EndFrame;
838
      FCurrentFrame := FStartFrame;
839
      FLastFrame := FCurrentFrame;
840
    end;
841
  end;
842
end;
843

844
procedure TGLActorProxy.SetStoredBoneNames(const Value: TStrings);
845
begin
846
  if value <> nil then
847
    FStoredBoneNames.Assign(Value);
848
end;
849

850
// SetMasterObject
851
//
852

853
procedure TGLActorProxy.SetMasterActorObject(const Value: TGLActor);
854
begin
855
  inherited SetMasterObject(Value);
856
  BoneMatricesClear;
857
end;
858

859
procedure TGLActorProxy.SetLibMaterialName(
860
  const Value: TGLLibMaterialName);
861
begin
862
  if FMaterialLibrary = nil then
863
  begin
864
    FTempLibMaterialName := Value;
865
    if not (csLoading in ComponentState) then
866
      raise ETexture.Create(glsErrorEx + glsMatLibNotDefined);
867
  end
868
  else
869
  begin
870
    FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
871
    FTempLibMaterialName := '';
872
  end;
873
end;
874

875
procedure TGLActorProxy.SetMaterialLibrary(const Value: TGLMaterialLibrary);
876
begin
877
  if FMaterialLibrary <> Value then
878
  begin
879
    if FMaterialLibrary <> nil then
880
      FMaterialLibrary.RemoveFreeNotification(Self);
881
    FMaterialLibrary := Value;
882

883
    if FMaterialLibrary <> nil then
884
    begin
885
      FMaterialLibrary.FreeNotification(Self);
886
      if FTempLibMaterialName <> '' then
887
        SetLibMaterialName(FTempLibMaterialName);
888
    end
889
    else
890
    begin
891
      FTempLibMaterialName := '';
892
    end;
893
  end;
894
end;
895

896
procedure TGLActorProxy.SetOnBeforeRender(const Value: TGLProgressEvent);
897
begin
898
  FOnBeforeRender := Value;
899
end;
900

901
procedure TGLActorProxy.SetStoreBonesMatrix(const Value: boolean);
902
begin
903
  FStoreBonesMatrix := Value;
904
end;
905

906
{ TGLMaterialProxy }
907

908
constructor TGLMaterialProxy.Create(AOwner: TComponent);
909
begin
910
  inherited;
911
  // Nothing here.
912
end;
913

914
destructor TGLMaterialProxy.Destroy;
915
begin
916
  // Nothing here.
917
  inherited;
918
end;
919

920
procedure TGLMaterialProxy.DoRender(var ARci: TGLRenderContextInfo;
921
  ARenderSelf, ARenderChildren: Boolean);
922
var
923
  gotMaster, masterGotEffects, oldProxySubObject: Boolean;
924
begin
925
  if FRendering then
926
    Exit;
927
  FRendering := True;
928
  try
929
    gotMaster := Assigned(MasterObject);
930
    masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
931
      and (MasterObject.Effects.Count > 0);
932
    if gotMaster then
933
    begin
934
      if pooObjects in ProxyOptions then
935
      begin
936
        oldProxySubObject := ARci.proxySubObject;
937
        ARci.proxySubObject := True;
938
        if pooTransformation in ProxyOptions then
939
          GL.MultMatrixf(PGLFloat(MasterObject.MatrixAsAddress));
940

941
        if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
942
          GetMasterMaterialObject.Material.QuickAssignMaterial(
943
            FMaterialLibrary, FMasterLibMaterial);
944

945
        MasterObject.DoRender(ARci, ARenderSelf, MasterObject.Count > 0);
946
        ARci.proxySubObject := oldProxySubObject;
947
      end;
948
    end;
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);
954
  finally
955
    FRendering := False;
956
  end;
957
  ClearStructureChanged;
958
end;
959

960
function TGLMaterialProxy.GetMasterLibMaterialName: TGLLibMaterialName;
961
begin
962
  Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
963
  if Result = '' then
964
    Result := FTempLibMaterialName;
965
end;
966

967
function TGLMaterialProxy.GetMasterMaterialObject: TGLCustomSceneObject;
968
begin
969
  Result := TGLCustomSceneObject(inherited MasterObject);
970
end;
971

972
function TGLMaterialProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
973
begin
974
  Result := FMaterialLibrary;
975
end;
976

977
procedure TGLMaterialProxy.Notification(AComponent: TComponent;
978
  Operation: TOperation);
979
begin
980
  inherited;
981
  if Operation = opRemove then
982
  begin
983
    if AComponent = FMaterialLibrary then
984
      FMaterialLibrary := nil;
985
  end;
986
end;
987

988
procedure TGLMaterialProxy.SetMasterLibMaterialName(
989
  const Value: TGLLibMaterialName);
990
begin
991
  if FMaterialLibrary = nil then
992
  begin
993
    FTempLibMaterialName := Value;
994
    if not (csLoading in ComponentState) then
995
      raise ETexture.Create(glsErrorEx + glsMatLibNotDefined);
996
  end
997
  else
998
  begin
999
    FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
1000
    FTempLibMaterialName := '';
1001
  end;
1002
end;
1003

1004
procedure TGLMaterialProxy.SetMasterMaterialObject(
1005
  const Value: TGLCustomSceneObject);
1006
begin
1007
  inherited SetMasterObject(Value);
1008
end;
1009

1010
procedure TGLMaterialProxy.SetMaterialLibrary(
1011
  const Value: TGLMaterialLibrary);
1012
begin
1013
  if FMaterialLibrary <> Value then
1014
  begin
1015
    if FMaterialLibrary <> nil then
1016
      FMaterialLibrary.RemoveFreeNotification(Self);
1017
    FMaterialLibrary := Value;
1018

1019
    if FMaterialLibrary <> nil then
1020
    begin
1021
      FMaterialLibrary.FreeNotification(Self);
1022
      if FTempLibMaterialName <> '' then
1023
        SetMasterLibMaterialName(FTempLibMaterialName);
1024
    end
1025
    else
1026
    begin
1027
      FTempLibMaterialName := '';
1028
    end;
1029
  end;
1030
end;
1031

1032
//-------------------------------------------------------------
1033
//-------------------------------------------------------------
1034
//-------------------------------------------------------------
1035
initialization
1036
  //-------------------------------------------------------------
1037
  //-------------------------------------------------------------
1038
  //-------------------------------------------------------------
1039

1040
  RegisterClasses([TGLColorProxy, TGLFreeFormProxy, TGLActorProxy,
1041
    TGLMaterialProxy]);
1042

1043
end.
1044

1045

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.