GLS.ProxyObjects.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.ProxyObjects;
  5. (* Implements specific proxying classes *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. System.SysUtils,
  12. Stage.OpenGLTokens,
  13. GLS.Scene,
  14. GLS.XCollection,
  15. Stage.PipelineTransform,
  16. Stage.VectorGeometry,
  17. GLS.Texture,
  18. GLS.VectorFileObjects,
  19. Stage.Strings,
  20. GLS.RenderContextInfo,
  21. GLS.BaseClasses,
  22. GLS.Material,
  23. GLS.Context,
  24. GLS.PersistentClasses,
  25. Stage.VectorTypes;
  26. type
  27. EGLProxyException = class(Exception);
  28. (* A proxy object with its own color.
  29. This proxy object can have a unique color. Note that multi-material
  30. objects (Freeforms linked to a material library f.i.) won't honour
  31. the color. *)
  32. TGLColorProxy = class(TGLProxyObject)
  33. private
  34. FFrontColor: TGLFaceProperties;
  35. function GetMasterMaterialObject: TGLCustomSceneObject;
  36. procedure SetMasterMaterialObject(const Value: TGLCustomSceneObject);
  37. procedure SetFrontColor(AValue: TGLFaceProperties);
  38. public
  39. constructor Create(AOwner: TComponent); override;
  40. destructor Destroy; override;
  41. procedure DoRender(var ARci: TGLRenderContextInfo;
  42. ARenderSelf, ARenderChildren: Boolean); override;
  43. published
  44. property FrontColor: TGLFaceProperties read FFrontColor write
  45. SetFrontColor;
  46. // Redeclare as TGLCustomSceneObject.
  47. property MasterObject: TGLCustomSceneObject read GetMasterMaterialObject
  48. write SetMasterMaterialObject;
  49. end;
  50. (* A proxy object with its own material.
  51. This proxy object can take a mesh from one master and a materia from
  52. a material library. *)
  53. TGLMaterialProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
  54. private
  55. FTempLibMaterialName: string;
  56. FMasterLibMaterial: TGLLibMaterial;
  57. FMaterialLibrary: TGLMaterialLibrary;
  58. procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
  59. function GetMasterLibMaterialName: TGLLibMaterialName;
  60. procedure SetMasterLibMaterialName(const Value: TGLLibMaterialName);
  61. function GetMasterMaterialObject: TGLCustomSceneObject;
  62. procedure SetMasterMaterialObject(const Value: TGLCustomSceneObject);
  63. // Implementing IGLMaterialLibrarySupported.
  64. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  65. public
  66. constructor Create(AOwner: TComponent); override;
  67. procedure Notification(AComponent: TComponent; Operation: TOperation);
  68. override;
  69. destructor Destroy; override;
  70. procedure DoRender(var ARci: TGLRenderContextInfo;
  71. ARenderSelf, ARenderChildren: Boolean); override;
  72. (* Specifies the Material, that current master object will use.
  73. Provides a faster way to access FMasterLibMaterial, compared to
  74. MasterLibMaterialName *)
  75. property MasterLibMaterial: TGLLibMaterial read FMasterLibMaterial write
  76. FMasterLibMaterial stored False;
  77. published
  78. property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write
  79. SetMaterialLibrary;
  80. // Specifies the Material, that current master object will use.
  81. property MasterLibMaterialName: TGLLibMaterialName read
  82. GetMasterLibMaterialName write SetMasterLibMaterialName;
  83. // Redeclare as TGLCustomSceneObject.
  84. property MasterObject: TGLCustomSceneObject read GetMasterMaterialObject
  85. write SetMasterMaterialObject;
  86. end;
  87. // A proxy object specialized for FreeForms.
  88. TGLFreeFormProxy = class(TGLProxyObject)
  89. private
  90. function GetMasterFreeFormObject: TGLFreeForm;
  91. procedure SetMasterFreeFormObject(const Value: TGLFreeForm);
  92. public
  93. (* If the MasterObject is a FreeForm, you can raycast against the Octree,
  94. which is alot faster. You must build the octree before using. *)
  95. function OctreeRayCastIntersect(const rayStart, rayVector: TGLVector;
  96. intersectPoint: PGLVector = nil; intersectNormal: PGLVector = nil): Boolean;
  97. // WARNING: This function is not yet 100% reliable with scale+rotation.
  98. function OctreeSphereSweepIntersect(const rayStart, rayVector: TGLVector;
  99. const velocity, radius, modelscale: Single;
  100. intersectPoint: PGLVector = nil; intersectNormal: PGLVector = nil): Boolean;
  101. published
  102. // Redeclare as TGLFreeForm.
  103. property MasterObject: TGLFreeForm read GetMasterFreeFormObject write
  104. SetMasterFreeFormObject;
  105. end;
  106. // An object containing the bone matrix for TGLActorProxy.
  107. TBoneMatrixObj = class
  108. public
  109. Matrix: TGLMatrix;
  110. BoneName: string;
  111. BoneIndex: integer;
  112. end;
  113. (* pamLoop mode was too difficalt to implement, so it was discarded ...for now.
  114. pamPlayOnce only works if Actor.AnimationMode <> aamNone. *)
  115. TGLActorProxyAnimationMode = (pamInherited, pamNone, pamPlayOnce);
  116. // A proxy object specialized for Actors.
  117. TGLActorProxy = class(TGLProxyObject, IGLMaterialLibrarySupported)
  118. private
  119. FCurrentFrame: Integer;
  120. FStartFrame: Integer;
  121. FEndFrame: Integer;
  122. FLastFrame: Integer;
  123. FCurrentFrameDelta: Single;
  124. FCurrentTime: TGLProgressTimes;
  125. FAnimation: TGLActorAnimationName;
  126. FTempLibMaterialName: string;
  127. FMasterLibMaterial: TGLLibMaterial;
  128. FMaterialLibrary: TGLMaterialLibrary;
  129. FBonesMatrices: TStringList;
  130. FStoreBonesMatrix: boolean;
  131. FStoredBoneNames: TStrings;
  132. FOnBeforeRender: TGLProgressEvent;
  133. FAnimationMode: TGLActorProxyAnimationMode;
  134. procedure SetAnimation(const Value: TGLActorAnimationName);
  135. procedure SetMasterActorObject(const Value: TGLActor);
  136. function GetMasterActorObject: TGLActor;
  137. function GetLibMaterialName: TGLLibMaterialName;
  138. procedure SetLibMaterialName(const Value: TGLLibMaterialName);
  139. procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
  140. // Implementing IGLMaterialLibrarySupported.
  141. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  142. procedure SetStoreBonesMatrix(const Value: boolean);
  143. procedure SetStoredBoneNames(const Value: TStrings);
  144. procedure SetOnBeforeRender(const Value: TGLProgressEvent);
  145. protected
  146. procedure DoStoreBonesMatrices; // stores matrices of bones of the current frame rendered
  147. public
  148. constructor Create(AOwner: TComponent); override;
  149. destructor Destroy; override;
  150. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  151. procedure DoRender(var ARci: TGLRenderContextInfo;
  152. ARenderSelf, ARenderChildren: Boolean); override;
  153. procedure DoProgress(const progressTime: TGLProgressTimes); override;
  154. property CurrentFrame: Integer read FCurrentFrame;
  155. property StartFrame: Integer read FStartFrame;
  156. property EndFrame: Integer read FEndFrame;
  157. property CurrentFrameDelta: Single read FCurrentFrameDelta;
  158. property CurrentTime: TGLProgressTimes read FCurrentTime;
  159. (* Gets the Bones Matrix in the current animation frame.
  160. (since the masterobject is shared between all proxies, each proxy will have it's bones matrices) *)
  161. function BoneMatrix(BoneIndex: integer): TGLMatrix; overload;
  162. function BoneMatrix(BoneName: string): TGLMatrix; overload;
  163. procedure BoneMatricesClear;
  164. // A standard version of the RayCastIntersect function.
  165. function RayCastIntersect(const rayStart, rayVector: TGLVector;
  166. intersectPoint: PGLVector = nil;
  167. intersectNormal: PGLVector = nil): Boolean; override;
  168. (* Raycasts on self, but actually on the "RefActor" Actor.
  169. Note that the "RefActor" parameter does not necessarily have to be
  170. the same Actor refernced by the MasterObject property:
  171. This allows to pass a low-low-low-poly Actor to raycast in the "RefActor" parameter,
  172. while using a high-poly Actor in the "MasterObject" property,
  173. of course we assume that the two Masterobject Actors have same animations. *)
  174. function RayCastIntersectEx(RefActor: TGLActor; const rayStart, rayVector:
  175. TGLVector;
  176. intersectPoint: PGLVector = nil;
  177. intersectNormal: PGLVector = nil): Boolean; overload;
  178. published
  179. property AnimationMode: TGLActorProxyAnimationMode read FAnimationMode write FAnimationMode default pamInherited;
  180. property Animation: TGLActorAnimationName read FAnimation write SetAnimation;
  181. // Redeclare as TGLActor.
  182. property MasterObject: TGLActor read GetMasterActorObject write SetMasterActorObject;
  183. (* Redeclare without pooTransformation
  184. (Don't know why it causes the object to be oriented incorrecly.) *)
  185. property ProxyOptions default [pooEffects, pooObjects];
  186. // Specifies the MaterialLibrary, that current proxy will use.
  187. property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  188. // Specifies the Material, that current proxy will use.
  189. property LibMaterialName: TGLLibMaterialName read GetLibMaterialName write SetLibMaterialName;
  190. (* Specifies if it will store the Bones Matrices, accessible via the BoneMatrix function
  191. (since the masterobject is shared between all proxies, each proxy will have it's bones matrices) *)
  192. property StoreBonesMatrix: boolean read FStoreBonesMatrix write SetStoreBonesMatrix;
  193. (* Specifies the names of the bones we want the matrices to be stored. If empty, all bones will be stored
  194. (since the masterobject is shared between all proxies, each proxy will have it's bones matrices) *)
  195. property StoredBoneNames: TStrings read FStoredBoneNames write SetStoredBoneNames;
  196. (* Event allowing to apply extra transformations (f.ex: bone rotations) to the referenced
  197. Actor on order to have the proxy render these changes. *)
  198. property OnBeforeRender: TGLProgressEvent read FOnBeforeRender write SetOnBeforeRender;
  199. end;
  200. //-------------------------------------------------------------
  201. implementation
  202. //-------------------------------------------------------------
  203. // ------------------
  204. // ------------------ TGLColorProxy ------------------
  205. // ------------------
  206. constructor TGLColorProxy.Create(AOwner: TComponent);
  207. begin
  208. inherited Create(AOwner);
  209. FFrontColor := TGLFaceProperties.Create(Self);
  210. end;
  211. destructor TGLColorProxy.Destroy;
  212. begin
  213. FFrontColor.Free;
  214. inherited Destroy;
  215. end;
  216. procedure TGLColorProxy.DoRender(var ARci: TGLRenderContextInfo;
  217. ARenderSelf, ARenderChildren: Boolean);
  218. var
  219. gotMaster, masterGotEffects, oldProxySubObject: Boolean;
  220. begin
  221. if FRendering then
  222. Exit;
  223. FRendering := True;
  224. try
  225. gotMaster := Assigned(MasterObject);
  226. masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
  227. and (MasterObject.Effects.Count > 0);
  228. if gotMaster then
  229. begin
  230. if pooObjects in ProxyOptions then
  231. begin
  232. oldProxySubObject := ARci.proxySubObject;
  233. ARci.proxySubObject := True;
  234. if pooTransformation in ProxyOptions then
  235. gl.MultMatrixf(PGLFloat(MasterObject.Matrix));
  236. GetMasterMaterialObject.Material.FrontProperties.Assign(FFrontColor);
  237. MasterObject.DoRender(ARci, ARenderSelf, MasterObject.Count > 0);
  238. ARci.proxySubObject := oldProxySubObject;
  239. end;
  240. end;
  241. // now render self stuff (our children, our effects, etc.)
  242. if ARenderChildren and (Count > 0) then
  243. Self.RenderChildren(0, Count - 1, ARci);
  244. if masterGotEffects then
  245. MasterObject.Effects.RenderPostEffects(ARci);
  246. finally
  247. FRendering := False;
  248. end;
  249. ClearStructureChanged;
  250. end;
  251. function TGLColorProxy.GetMasterMaterialObject: TGLCustomSceneObject;
  252. begin
  253. Result := TGLCustomSceneObject(inherited MasterObject);
  254. end;
  255. procedure TGLColorProxy.SetFrontColor(AValue: TGLFaceProperties);
  256. begin
  257. FFrontColor.Assign(AValue);
  258. end;
  259. procedure TGLColorProxy.SetMasterMaterialObject(
  260. const Value: TGLCustomSceneObject);
  261. begin
  262. inherited SetMasterObject(Value);
  263. end;
  264. // ------------------
  265. // ------------------ TGLFreeFormProxy ------------------
  266. // ------------------
  267. function TGLFreeFormProxy.OctreeRayCastIntersect(const rayStart, rayVector:
  268. TGLVector;
  269. intersectPoint: PGLVector = nil;
  270. intersectNormal: PGLVector = nil): Boolean;
  271. var
  272. localRayStart, localRayVector: TGLVector;
  273. begin
  274. if Assigned(MasterObject) then
  275. begin
  276. SetVector(localRayStart, AbsoluteToLocal(rayStart));
  277. SetVector(localRayStart, MasterObject.LocalToAbsolute(localRayStart));
  278. SetVector(localRayVector, AbsoluteToLocal(rayVector));
  279. SetVector(localRayVector, MasterObject.LocalToAbsolute(localRayVector));
  280. NormalizeVector(localRayVector);
  281. Result := GetMasterFreeFormObject.OctreeRayCastIntersect(localRayStart,
  282. localRayVector,
  283. intersectPoint, intersectNormal);
  284. if Result then
  285. begin
  286. if Assigned(intersectPoint) then
  287. begin
  288. SetVector(intersectPoint^,
  289. MasterObject.AbsoluteToLocal(intersectPoint^));
  290. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  291. end;
  292. if Assigned(intersectNormal) then
  293. begin
  294. SetVector(intersectNormal^,
  295. MasterObject.AbsoluteToLocal(intersectNormal^));
  296. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  297. end;
  298. end;
  299. end
  300. else
  301. Result := False;
  302. end;
  303. function TGLFreeFormProxy.OctreeSphereSweepIntersect(const rayStart, rayVector:
  304. TGLVector;
  305. const velocity, radius, modelscale: Single;
  306. intersectPoint: PGLVector = nil;
  307. intersectNormal: PGLVector = nil): Boolean;
  308. var
  309. localRayStart, localRayVector: TGLVector;
  310. localVelocity, localRadius: single;
  311. begin
  312. Result := False;
  313. if Assigned(MasterObject) then
  314. begin
  315. localVelocity := velocity * modelscale;
  316. localRadius := radius * modelscale;
  317. SetVector(localRayStart, AbsoluteToLocal(rayStart));
  318. SetVector(localRayStart, MasterObject.LocalToAbsolute(localRayStart));
  319. SetVector(localRayVector, AbsoluteToLocal(rayVector));
  320. SetVector(localRayVector, MasterObject.LocalToAbsolute(localRayVector));
  321. NormalizeVector(localRayVector);
  322. Result := GetMasterFreeFormObject.OctreeSphereSweepIntersect(localRayStart,
  323. localRayVector,
  324. localVelocity, localRadius,
  325. intersectPoint, intersectNormal);
  326. if Result then
  327. begin
  328. if Assigned(intersectPoint) then
  329. begin
  330. SetVector(intersectPoint^,
  331. MasterObject.AbsoluteToLocal(intersectPoint^));
  332. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  333. end;
  334. if Assigned(intersectNormal) then
  335. begin
  336. SetVector(intersectNormal^,
  337. MasterObject.AbsoluteToLocal(intersectNormal^));
  338. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  339. end;
  340. end;
  341. end;
  342. end;
  343. function TGLFreeFormProxy.GetMasterFreeFormObject: TGLFreeForm;
  344. begin
  345. Result := TGLFreeForm(inherited MasterObject);
  346. end;
  347. procedure TGLFreeFormProxy.SetMasterFreeFormObject(
  348. const Value: TGLFreeForm);
  349. begin
  350. inherited SetMasterObject(Value);
  351. end;
  352. // ------------------
  353. // ------------------ TGLActorProxy ------------------
  354. // ------------------
  355. function TGLActorProxy.BoneMatrix(BoneIndex: integer): TGLMatrix;
  356. begin
  357. if BoneIndex < FBonesMatrices.count then
  358. result := TBoneMatrixObj(FBonesMatrices.Objects[BoneIndex]).Matrix;
  359. end;
  360. function TGLActorProxy.BoneMatrix(BoneName: string): TGLMatrix;
  361. var
  362. i: Integer;
  363. begin
  364. i := FBonesMatrices.IndexOf(BoneName);
  365. if i > -1 then
  366. result := TBoneMatrixObj(FBonesMatrices.Objects[i]).Matrix;
  367. end;
  368. procedure TGLActorProxy.BoneMatricesClear;
  369. var
  370. i: Integer;
  371. begin
  372. for i := 0 to FBonesMatrices.Count - 1 do
  373. begin
  374. TBoneMatrixObj(FBonesMatrices.Objects[i]).free;
  375. end;
  376. FBonesMatrices.Clear;
  377. end;
  378. constructor TGLActorProxy.Create(AOwner: TComponent);
  379. begin
  380. inherited;
  381. FAnimationMode := pamInherited;
  382. ProxyOptions := ProxyOptions - [pooTransformation];
  383. FBonesMatrices := TStringList.create;
  384. FStoredBoneNames := TStringList.create;
  385. FStoreBonesMatrix := false;
  386. // default is false to speed up a little if we don't need bones info
  387. end;
  388. destructor TGLActorProxy.Destroy;
  389. begin
  390. BoneMatricesClear;
  391. FBonesMatrices.free;
  392. FStoredBoneNames.free;
  393. inherited;
  394. end;
  395. procedure TGLActorProxy.DoProgress(const progressTime: TGLProgressTimes);
  396. begin
  397. inherited;
  398. FCurrentTime := progressTime;
  399. end;
  400. procedure TGLActorProxy.DoRender(var ARci: TGLRenderContextInfo; ARenderSelf,
  401. ARenderChildren: Boolean);
  402. var
  403. // TGLActorProxy specific
  404. cf, sf, ef: Integer;
  405. cfd: Single;
  406. // General proxy stuff.
  407. gotMaster, masterGotEffects, oldProxySubObject: Boolean;
  408. MasterActor: TGLActor;
  409. begin
  410. try
  411. MasterActor := GetMasterActorObject;
  412. gotMaster := MasterActor <> nil;
  413. masterGotEffects := gotMaster and (pooEffects in ProxyOptions) and
  414. (MasterObject.Effects.Count > 0);
  415. if gotMaster then
  416. begin
  417. if pooObjects in ProxyOptions then
  418. begin
  419. oldProxySubObject := ARci.proxySubObject;
  420. ARci.proxySubObject := True;
  421. if pooTransformation in ProxyOptions then
  422. with ARci.PipelineTransformation do
  423. SetModelMatrix(MatrixMultiply(MasterActor.Matrix^, ModelMatrix^));
  424. // At last TGLActorProxy specific stuff!
  425. with MasterActor do
  426. begin
  427. cfd := CurrentFrameDelta;
  428. cf := CurrentFrame;
  429. sf := startframe;
  430. ef := endframe;
  431. case FAnimationMode of
  432. pamInherited: CurrentFrameDelta := FCurrentFrameDelta;
  433. pamPlayOnce:
  434. begin
  435. if (FLastFrame <> FEndFrame - 1) then
  436. CurrentFrameDelta := FCurrentFrameDelta
  437. else
  438. begin
  439. FCurrentFrameDelta := 0;
  440. FAnimationMode := pamNone;
  441. end;
  442. end;
  443. pamNone: CurrentFrameDelta := 0;
  444. else
  445. Assert(False, strUnknownType);
  446. end;
  447. SetCurrentFrameDirect(FCurrentFrame);
  448. FLastFrame := FCurrentFrame;
  449. StartFrame := FStartFrame;
  450. EndFrame := FEndFrame;
  451. if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
  452. MasterActor.Material.QuickAssignMaterial(
  453. FMaterialLibrary, FMasterLibMaterial);
  454. DoProgress(FCurrentTime);
  455. if Assigned(FOnBeforeRender) then
  456. FOnBeforeRender(self, FCurrentTime.deltaTime, FCurrentTime.newTime);
  457. DoRender(ARci, ARenderSelf, Count > 0);
  458. // Stores Bones matrices of the current frame
  459. if (FStoreBonesMatrix) and (MasterActor.Skeleton <> nil) then
  460. DoStoreBonesMatrices;
  461. FCurrentFrameDelta := CurrentFrameDelta;
  462. FCurrentFrame := CurrentFrame;
  463. CurrentFrameDelta := cfd;
  464. SetCurrentFrameDirect(cf);
  465. startframe := sf;
  466. endframe := ef;
  467. end;
  468. ARci.proxySubObject := oldProxySubObject;
  469. end;
  470. end;
  471. // now render self stuff (our children, our effects, etc.)
  472. oldProxySubObject := ARci.proxySubObject;
  473. ARci.proxySubObject := True;
  474. if ARenderChildren and (Count > 0) then
  475. Self.RenderChildren(0, Count - 1, ARci);
  476. if masterGotEffects then
  477. MasterActor.Effects.RenderPostEffects(ARci);
  478. ARci.proxySubObject := oldProxySubObject;
  479. finally
  480. ClearStructureChanged;
  481. end;
  482. end;
  483. procedure TGLActorProxy.DoStoreBonesMatrices;
  484. var
  485. i, n: integer;
  486. Bmo: TBoneMatrixObj;
  487. Bone: TGLSkeletonBone;
  488. begin
  489. if FStoredBoneNames.count > 0 then
  490. begin
  491. // If we specified some bone names, only those bones matrices will be stored (save some cpu)
  492. if FBonesMatrices.Count < FStoredBoneNames.Count then
  493. begin
  494. n := FBonesMatrices.Count;
  495. for i := n to FStoredBoneNames.Count - 1 do
  496. begin
  497. Bone := MasterObject.Skeleton.BoneByName(FStoredBoneNames[i]);
  498. if Bone <> nil then
  499. begin
  500. Bmo := TBoneMatrixObj.Create;
  501. Bmo.BoneName := Bone.Name;
  502. Bmo.BoneIndex := Bone.BoneID;
  503. FBonesMatrices.AddObject(Bone.Name, Bmo);
  504. end;
  505. end;
  506. end;
  507. end
  508. else
  509. begin
  510. // Add (missing) TBoneMatrixObjects (actually ony 1st time) from all bones in skeleton
  511. if FBonesMatrices.Count < MasterObject.Skeleton.BoneCount - 1 then
  512. // note : BoneCount actually returns 1 count more.
  513. begin
  514. n := FBonesMatrices.Count;
  515. for i := n to MasterObject.Skeleton.BoneCount - 2 do
  516. // note : BoneCount actually returns 1 count more.
  517. begin
  518. Bone := MasterObject.Skeleton.BoneByID(i);
  519. if Bone <> nil then
  520. begin
  521. Bmo := TBoneMatrixObj.Create;
  522. Bmo.BoneName := Bone.Name;
  523. Bmo.BoneIndex := Bone.BoneID;
  524. FBonesMatrices.AddObject(Bone.Name, Bmo);
  525. end;
  526. end;
  527. end;
  528. end;
  529. // fill FBonesMatrices list
  530. for i := 0 to FBonesMatrices.count - 1 do
  531. begin
  532. Bmo := TBoneMatrixObj(FBonesMatrices.Objects[i]);
  533. Bmo.Matrix := MasterObject.Skeleton.BoneByID(Bmo.BoneIndex).GlobalMatrix;
  534. end;
  535. end;
  536. function TGLActorProxy.GetMasterActorObject: TGLActor;
  537. begin
  538. Result := TGLActor(inherited MasterObject);
  539. end;
  540. function TGLActorProxy.GetLibMaterialName: TGLLibMaterialName;
  541. begin
  542. Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
  543. if Result = '' then
  544. Result := FTempLibMaterialName;
  545. end;
  546. function TGLActorProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  547. begin
  548. Result := FMaterialLibrary;
  549. end;
  550. procedure TGLActorProxy.Notification(AComponent: TComponent;
  551. Operation: TOperation);
  552. begin
  553. inherited;
  554. if Operation = opRemove then
  555. begin
  556. if AComponent = FMaterialLibrary then
  557. FMaterialLibrary := nil;
  558. end;
  559. end;
  560. function TGLActorProxy.RayCastIntersect(const rayStart, rayVector: TGLVector;
  561. intersectPoint, intersectNormal: PGLVector): Boolean;
  562. begin
  563. if MasterObject <> nil then
  564. Result := RayCastIntersectEx(GetMasterActorObject, rayStart, rayVector,
  565. intersectPoint, intersectNormal)
  566. else
  567. Result := inherited RayCastIntersect(rayStart, rayVector, intersectPoint,
  568. intersectNormal);
  569. end;
  570. // Gain access to TGLDummyActor.DoAnimate().
  571. type
  572. TGLDummyActor = class(TGLActor);
  573. function TGLActorProxy.RayCastIntersectEx(RefActor: TGLActor; const rayStart,
  574. rayVector: TGLVector; intersectPoint, intersectNormal: PGLVector): Boolean;
  575. var
  576. localRayStart, localRayVector: TGLVector;
  577. cf, sf, ef: Integer;
  578. cfd: Single;
  579. HaspooTransformation: boolean;
  580. begin
  581. // Set RefObject frame as current ActorProxy frame
  582. with RefActor do
  583. begin
  584. // VARS FOR ACTOR TO ASSUME ACTORPROXY CURRENT ANIMATION FRAME
  585. cfd := RefActor.CurrentFrameDelta;
  586. cf := RefActor.CurrentFrame;
  587. sf := RefActor.startframe;
  588. ef := RefActor.endframe;
  589. RefActor.CurrentFrameDelta := self.CurrentFrameDelta;
  590. RefActor.SetCurrentFrameDirect(self.CurrentFrame);
  591. RefActor.StartFrame := self.StartFrame;
  592. RefActor.EndFrame := self.EndFrame;
  593. RefActor.CurrentFrame := self.CurrentFrame;
  594. // FORCE ACTOR TO ASSUME ACTORPROXY CURRENT ANIMATION FRAME
  595. TGLDummyActor(RefActor).DoAnimate();
  596. HaspooTransformation := pooTransformation in self.ProxyOptions;
  597. // transform RAYSTART
  598. SetVector(localRayStart, self.AbsoluteToLocal(rayStart));
  599. if not HaspooTransformation then
  600. SetVector(localRayStart, RefActor.LocalToAbsolute(localRayStart));
  601. // transform RAYVECTOR
  602. SetVector(localRayVector, self.AbsoluteToLocal(rayVector));
  603. if not HaspooTransformation then
  604. SetVector(localRayVector, RefActor.LocalToAbsolute(localRayVector));
  605. NormalizeVector(localRayVector);
  606. Result := RefActor.RayCastIntersect(localRayStart, localRayVector,
  607. intersectPoint, intersectNormal);
  608. if Result then
  609. begin
  610. if Assigned(intersectPoint) then
  611. begin
  612. if not HaspooTransformation then
  613. SetVector(intersectPoint^, RefActor.AbsoluteToLocal(intersectPoint^));
  614. SetVector(intersectPoint^, self.LocalToAbsolute(intersectPoint^));
  615. end;
  616. if Assigned(intersectNormal) then
  617. begin
  618. if not HaspooTransformation then
  619. SetVector(intersectNormal^,
  620. RefActor.AbsoluteToLocal(intersectNormal^));
  621. SetVector(intersectNormal^, self.LocalToAbsolute(intersectNormal^));
  622. end;
  623. end;
  624. // Return RefObject to it's old time
  625. CurrentFrameDelta := cfd;
  626. SetCurrentFrameDirect(cf);
  627. CurrentFrame := cf;
  628. startframe := sf;
  629. endframe := ef;
  630. // REVERT ACTOR TO ASSUME ORIGINAL ANIMATION FRAME
  631. TGLDummyActor(RefActor).DoAnimate();
  632. end;
  633. end;
  634. procedure TGLActorProxy.SetAnimation(const Value: TGLActorAnimationName);
  635. var
  636. anAnimation: TGLActorAnimation;
  637. begin
  638. // We first assign the value (for persistency support), then check it.
  639. FAnimation := Value;
  640. if Assigned(MasterObject) then
  641. begin
  642. anAnimation := GetMasterActorObject.Animations.FindName(Value);
  643. if Assigned(anAnimation) then
  644. begin
  645. FStartFrame := anAnimation.StartFrame;
  646. FEndFrame := anAnimation.EndFrame;
  647. FCurrentFrame := FStartFrame;
  648. FLastFrame := FCurrentFrame;
  649. end;
  650. end;
  651. end;
  652. procedure TGLActorProxy.SetStoredBoneNames(const Value: TStrings);
  653. begin
  654. if value <> nil then
  655. FStoredBoneNames.Assign(Value);
  656. end;
  657. procedure TGLActorProxy.SetMasterActorObject(const Value: TGLActor);
  658. begin
  659. inherited SetMasterObject(Value);
  660. BoneMatricesClear;
  661. end;
  662. procedure TGLActorProxy.SetLibMaterialName(
  663. const Value: TGLLibMaterialName);
  664. begin
  665. if FMaterialLibrary = nil then
  666. begin
  667. FTempLibMaterialName := Value;
  668. if not (csLoading in ComponentState) then
  669. raise ETexture.Create(strErrorEx + strMatLibNotDefined);
  670. end
  671. else
  672. begin
  673. FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
  674. FTempLibMaterialName := '';
  675. end;
  676. end;
  677. procedure TGLActorProxy.SetMaterialLibrary(const Value: TGLMaterialLibrary);
  678. begin
  679. if FMaterialLibrary <> Value then
  680. begin
  681. if FMaterialLibrary <> nil then
  682. FMaterialLibrary.RemoveFreeNotification(Self);
  683. FMaterialLibrary := Value;
  684. if FMaterialLibrary <> nil then
  685. begin
  686. FMaterialLibrary.FreeNotification(Self);
  687. if FTempLibMaterialName <> '' then
  688. SetLibMaterialName(FTempLibMaterialName);
  689. end
  690. else
  691. begin
  692. FTempLibMaterialName := '';
  693. end;
  694. end;
  695. end;
  696. procedure TGLActorProxy.SetOnBeforeRender(const Value: TGLProgressEvent);
  697. begin
  698. FOnBeforeRender := Value;
  699. end;
  700. procedure TGLActorProxy.SetStoreBonesMatrix(const Value: boolean);
  701. begin
  702. FStoreBonesMatrix := Value;
  703. end;
  704. { TGLMaterialProxy }
  705. constructor TGLMaterialProxy.Create(AOwner: TComponent);
  706. begin
  707. inherited;
  708. // Nothing here.
  709. end;
  710. destructor TGLMaterialProxy.Destroy;
  711. begin
  712. // Nothing here.
  713. inherited;
  714. end;
  715. procedure TGLMaterialProxy.DoRender(var ARci: TGLRenderContextInfo;
  716. ARenderSelf, ARenderChildren: Boolean);
  717. var
  718. gotMaster, masterGotEffects, oldProxySubObject: Boolean;
  719. begin
  720. if FRendering then
  721. Exit;
  722. FRendering := True;
  723. try
  724. gotMaster := Assigned(MasterObject);
  725. masterGotEffects := gotMaster and (pooEffects in ProxyOptions)
  726. and (MasterObject.Effects.Count > 0);
  727. if gotMaster then
  728. begin
  729. if pooObjects in ProxyOptions then
  730. begin
  731. oldProxySubObject := ARci.proxySubObject;
  732. ARci.proxySubObject := True;
  733. if pooTransformation in ProxyOptions then
  734. gl.MultMatrixf(PGLFloat(MasterObject.Matrix));
  735. if (FMasterLibMaterial <> nil) and (FMaterialLibrary <> nil) then
  736. GetMasterMaterialObject.Material.QuickAssignMaterial(
  737. FMaterialLibrary, FMasterLibMaterial);
  738. MasterObject.DoRender(ARci, ARenderSelf, MasterObject.Count > 0);
  739. ARci.proxySubObject := oldProxySubObject;
  740. end;
  741. end;
  742. // now render self stuff (our children, our effects, etc.)
  743. if ARenderChildren and (Count > 0) then
  744. Self.RenderChildren(0, Count - 1, ARci);
  745. if masterGotEffects then
  746. MasterObject.Effects.RenderPostEffects(ARci);
  747. finally
  748. FRendering := False;
  749. end;
  750. ClearStructureChanged;
  751. end;
  752. function TGLMaterialProxy.GetMasterLibMaterialName: TGLLibMaterialName;
  753. begin
  754. Result := FMaterialLibrary.GetNameOfLibMaterial(FMasterLibMaterial);
  755. if Result = '' then
  756. Result := FTempLibMaterialName;
  757. end;
  758. function TGLMaterialProxy.GetMasterMaterialObject: TGLCustomSceneObject;
  759. begin
  760. Result := TGLCustomSceneObject(inherited MasterObject);
  761. end;
  762. function TGLMaterialProxy.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  763. begin
  764. Result := FMaterialLibrary;
  765. end;
  766. procedure TGLMaterialProxy.Notification(AComponent: TComponent;
  767. Operation: TOperation);
  768. begin
  769. inherited;
  770. if Operation = opRemove then
  771. begin
  772. if AComponent = FMaterialLibrary then
  773. FMaterialLibrary := nil;
  774. end;
  775. end;
  776. procedure TGLMaterialProxy.SetMasterLibMaterialName(
  777. const Value: TGLLibMaterialName);
  778. begin
  779. if FMaterialLibrary = nil then
  780. begin
  781. FTempLibMaterialName := Value;
  782. if not (csLoading in ComponentState) then
  783. raise ETexture.Create(strErrorEx + strMatLibNotDefined);
  784. end
  785. else
  786. begin
  787. FMasterLibMaterial := FMaterialLibrary.LibMaterialByName(Value);
  788. FTempLibMaterialName := '';
  789. end;
  790. end;
  791. procedure TGLMaterialProxy.SetMasterMaterialObject(
  792. const Value: TGLCustomSceneObject);
  793. begin
  794. inherited SetMasterObject(Value);
  795. end;
  796. procedure TGLMaterialProxy.SetMaterialLibrary(
  797. const Value: TGLMaterialLibrary);
  798. begin
  799. if FMaterialLibrary <> Value then
  800. begin
  801. if FMaterialLibrary <> nil then
  802. FMaterialLibrary.RemoveFreeNotification(Self);
  803. FMaterialLibrary := Value;
  804. if FMaterialLibrary <> nil then
  805. begin
  806. FMaterialLibrary.FreeNotification(Self);
  807. if FTempLibMaterialName <> '' then
  808. SetMasterLibMaterialName(FTempLibMaterialName);
  809. end
  810. else
  811. begin
  812. FTempLibMaterialName := '';
  813. end;
  814. end;
  815. end;
  816. //-------------------------------------------------------------
  817. initialization
  818. //-------------------------------------------------------------
  819. RegisterClasses([TGLColorProxy, TGLFreeFormProxy, TGLActorProxy,
  820. TGLMaterialProxy]);
  821. end.