GLProxyObjects.pas 30 KB

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