GLProxyObjects.pas 30 KB

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