GXS.File3DS.pas 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.File3DS;
  5. (* 3DStudio 3DS vector file format implementation *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. System.Math,
  12. Stage.Strings,
  13. Stage.OpenGL4,
  14. GXS.Scene,
  15. GXS.Objects,
  16. GXS.VectorFileObjects,
  17. GXS.Texture,
  18. GXS.ApplicationFileIO,
  19. Stage.VectorGeometry,
  20. GXS.Context,
  21. GXS.PersistentClasses,
  22. GXS.File3DSSceneObjects,
  23. Stage.VectorTypes,
  24. GXS.VectorLists,
  25. GXS.RenderContextInfo,
  26. GXS.Material,
  27. Formatx.m3DS,
  28. Formatx.m3DSTypes;
  29. type
  30. EGLFile3DS = class(Exception);
  31. // A record that holds all the information that is used during 3ds animation.
  32. TgxFile3DSAnimationData = packed record
  33. ModelMatrix: TMatrix4f;
  34. Color: TVector4f; // Omni Light.
  35. TargetPos: TAffineVector; // Spot Light.
  36. SpotLightCutOff: single;
  37. HotSpot: single;
  38. Roll: single;
  39. end;
  40. // An abstract class that describes how to interpolate animation keys.
  41. TgxFile3DSAnimationKeys = class(TgxPersistentObject)
  42. private
  43. FNumKeys: integer;
  44. FKeys: array of TKeyHeader3DS;
  45. procedure InterpolateFrame(var I: integer; var w: real; const AFrame: real);
  46. protected
  47. function InterpolateValue(const AValues: array of single; const AFrame: real): single; overload;
  48. function InterpolateValue(const AValues: array of TAffineVector; const AFrame: real): TAffineVector; overload;
  49. function InterpolateValue(const AValues: array of TKFRotKey3DS; const AFrame: real): TMatrix4f; overload;
  50. public
  51. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); virtual;
  52. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); virtual; abstract;
  53. procedure Assign(Source: TPersistent); override;
  54. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  55. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  56. end;
  57. TgxFile3DSScaleAnimationKeys = class(TgxFile3DSAnimationKeys)
  58. private
  59. FScale: array of TAffineVector;
  60. public
  61. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  62. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  63. procedure Assign(Source: TPersistent); override;
  64. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  65. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  66. end;
  67. TgxFile3DSRotationAnimationKeys = class(TgxFile3DSAnimationKeys)
  68. private
  69. FRot: array of TKFRotKey3DS;
  70. public
  71. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  72. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  73. procedure Assign(Source: TPersistent); override;
  74. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  75. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  76. end;
  77. TgxFile3DSPositionAnimationKeys = class(TgxFile3DSAnimationKeys)
  78. private
  79. FPos: array of TAffineVector;
  80. public
  81. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  82. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  83. procedure Assign(Source: TPersistent); override;
  84. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  85. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  86. end;
  87. TgxFile3DSColorAnimationKeys = class(TgxFile3DSAnimationKeys)
  88. private
  89. FCol: array of TAffineVector;
  90. public
  91. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  92. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  93. procedure Assign(Source: TPersistent); override;
  94. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  95. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  96. end;
  97. TTgxFile3DSPositionAnimationKeys = class(TgxFile3DSAnimationKeys)
  98. private
  99. FTPos: array of TAffineVector;
  100. public
  101. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  102. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  103. procedure Assign(Source: TPersistent); override;
  104. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  105. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  106. end;
  107. TgxFile3DSSpotLightCutOffAnimationKeys = class(TgxFile3DSAnimationKeys)
  108. private
  109. FFall: array of single;
  110. public
  111. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  112. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  113. procedure Assign(Source: TPersistent); override;
  114. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  115. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  116. end;
  117. TgxFile3DSLightHotSpotAnimationKeys = class(TgxFile3DSAnimationKeys)
  118. private
  119. FHot: array of single;
  120. public
  121. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  122. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  123. procedure Assign(Source: TPersistent); override;
  124. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  125. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  126. end;
  127. TgxFile3DSRollAnimationKeys = class(TgxFile3DSAnimationKeys)
  128. private
  129. FRoll: array of single;
  130. public
  131. procedure LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer); override;
  132. procedure Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real); override;
  133. procedure Assign(Source: TPersistent); override;
  134. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  135. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  136. end;
  137. TgxFile3DSAnimationKeyList = class(TgxPersistentObject)
  138. private
  139. FAnimKeysList: array of TgxFile3DSAnimationKeys;
  140. protected
  141. procedure ApplyAnimKeys(var DataTransf: TgxFile3DSAnimationData; const AFrame: real);
  142. public
  143. procedure AddKeys(const AItem: TgxFile3DSAnimationKeys);
  144. procedure ClearKeys;
  145. procedure Assign(Source: TPersistent); override;
  146. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  147. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  148. destructor Destroy; override;
  149. end;
  150. // Used only for serialization. There probably is a more efficient way to do it.
  151. TgxFile3DSAnimKeysClassType = (ctScale, ctRot, ctPos, ctCol, ctTPos, ctFall, ctHot, ctRoll);
  152. // A 3ds-specific TgxMorphableMeshObject.
  153. TgxFile3DSDummyObject = class(TgxMorphableMeshObject)
  154. private
  155. FAnimList: TgxFile3DSAnimationKeyList;
  156. FAnimData: Pointer;
  157. FRefTranf, FAnimTransf: TgxFile3DSAnimationData;
  158. FParent: TgxFile3DSDummyObject;
  159. FParentName: String64;
  160. FStatic : Boolean; // Static tag used in BuildList to not apply animation matrix
  161. public
  162. procedure LoadAnimation(const AData: Pointer); virtual;
  163. procedure SetFrame(const AFrame: real); virtual;
  164. procedure MorphTo(morphTargetIndex: integer); override;
  165. procedure Lerp(morphTargetIndex1, morphTargetIndex2: integer; lerpFactor: single); override;
  166. procedure GetExtents(out min, max: TAffineVector); override;
  167. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList;
  168. override;
  169. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  170. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  171. procedure Assign(Source: TPersistent); override;
  172. constructor Create; override;
  173. destructor Destroy; override;
  174. property AnimList: TgxFile3DSAnimationKeyList read FAnimList;
  175. property Parent: TgxFile3DSDummyObject read FParent write FParent;
  176. property RefrenceTransf: TgxFile3DSAnimationData read FRefTranf write FRefTranf;
  177. end;
  178. // A 3ds-specific mesh object.
  179. TgxFile3DSMeshObject = class(TgxFile3DSDummyObject)
  180. public
  181. procedure LoadAnimation(const AData: Pointer); override;
  182. procedure BuildList(var ARci: TgxRenderContextInfo); override;
  183. end;
  184. { A 3ds-specific omni light. }
  185. TgxFile3DSOmniLightObject = class(TgxFile3DSDummyObject)
  186. private
  187. FLightSrc: TgxFile3DSLight;
  188. FLightSrcName: String64;
  189. public
  190. constructor Create; override;
  191. procedure LoadData(const AOwner: TgxBaseMesh; const AData: PLight3DS); virtual;
  192. procedure LoadAnimation(const AData: Pointer); override;
  193. procedure SetFrame(const AFrame: real); override;
  194. procedure Assign(Source: TPersistent); override;
  195. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  196. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  197. destructor Destroy; override;
  198. end;
  199. // A 3ds-specific spot light.
  200. TgxFile3DSSpotLightObject = class(TgxFile3DSOmniLightObject)
  201. public
  202. procedure LoadData(const AOwner: TgxBaseMesh; const AData: PLight3DS); override;
  203. procedure LoadAnimation(const AData: Pointer); override;
  204. procedure SetFrame(const AFrame: real); override;
  205. end;
  206. // A 3ds-specific camera.
  207. TgxFile3DSCameraObject = class(TgxFile3DSDummyObject)
  208. private
  209. FTargetObj: TgxDummyCube;
  210. FCameraSrc: TgxFile3DSCamera;
  211. FCameraSrcName: String64;
  212. public
  213. constructor Create; override;
  214. procedure LoadData(Owner: TgxBaseMesh; AData: PCamera3DS);
  215. procedure LoadAnimation(const AData: Pointer); override;
  216. procedure SetFrame(const AFrame: real); override;
  217. procedure WriteToFiler(Writer: TgxVirtualWriter); override;
  218. procedure ReadFromFiler(Reader: TgxVirtualReader); override;
  219. destructor Destroy; override;
  220. end;
  221. (* The 3DStudio vector file.
  222. A 3DS file may contain material
  223. information and require textures when loading. *)
  224. Tgx3DSVectorFile = class(TgxVectorFile)
  225. public
  226. class function Capabilities: TDataFileCapabilities; override;
  227. procedure LoadFromStream(aStream: TStream); override;
  228. end;
  229. var
  230. (* If enabled, advanced parameters will be loaded from a 3ds file
  231. (TextureScale, TextureOffset), but it might break backwards compatibility.
  232. If disabled, it won't break anything, but some parameters will not be
  233. loaded correctly from a 3ds file.
  234. Also there is a significant drop in FPS when this option is on
  235. (for unknown reasons), so it is off by default. *)
  236. vFile3DS_UseTextureEx: boolean = False;
  237. (* If enabled, allows 3ds animation and fixes loading of some 3ds models,
  238. but has a few bugs:
  239. - TgxFreeForm.AutoCentering does now work correctly.
  240. - TgxMeshObject.vertices return values different from
  241. TgxMeshObject.ExtractTriangles() *)
  242. vFile3DS_EnableAnimation: boolean = False;
  243. (* If enabled, a -90 degrees (-PI/2) rotation will occured on X Axis.
  244. By design 3dsmax has a Z Up-Axis, after the rotation the Up axis will
  245. be Y. (Note: you need vFile3DS_EnableAnimation = true) *)
  246. vFile3DS_FixDefaultUpAxisY: boolean = False;
  247. (* If >= 0, then the vertices list will be updated with selected frame
  248. animation data. (Note: you need vFile3DS_EnableAnimation = true).
  249. Be aware that in that case animation will not be usable, it is made
  250. to be used with a static mesh like GLFreeForm. *)
  251. vFile3DS_LoadedStaticFrame: integer = -1;
  252. // ------------------------------------------------------------------
  253. implementation
  254. // ------------------------------------------------------------------
  255. const
  256. cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE = PI/2;
  257. CGLFILE3DS_DEFAULT_FRAME = 0;
  258. function AnimKeysClassTypeToClass(const AAnimKeysClassType: TgxFile3DSAnimKeysClassType): TClass;
  259. begin
  260. case AAnimKeysClassType of
  261. ctScale: Result := TgxFile3DSScaleAnimationKeys;
  262. ctRot: Result := TgxFile3DSRotationAnimationKeys;
  263. ctPos: Result := TgxFile3DSPositionAnimationKeys;
  264. ctCol: Result := TgxFile3DSColorAnimationKeys;
  265. ctTPos: Result := TTgxFile3DSPositionAnimationKeys;
  266. ctFall: Result := TgxFile3DSSpotLightCutOffAnimationKeys;
  267. ctHot: Result := TgxFile3DSLightHotSpotAnimationKeys;
  268. ctRoll: Result := TgxFile3DSRollAnimationKeys;
  269. else
  270. begin
  271. Result := nil;
  272. Assert(False, strErrorEx + strUnknownType);
  273. end;
  274. end;
  275. end;
  276. function ClassToAnimKeysClassType(const AAnimKeysClass: TClass): TgxFile3DSAnimKeysClassType;
  277. begin
  278. if AAnimKeysClass.InheritsFrom(TgxFile3DSScaleAnimationKeys) then
  279. Result := ctScale
  280. else if AAnimKeysClass.InheritsFrom(TgxFile3DSRotationAnimationKeys) then
  281. Result := ctRot
  282. else if AAnimKeysClass.InheritsFrom(TgxFile3DSPositionAnimationKeys) then
  283. Result := ctPos
  284. else if AAnimKeysClass.InheritsFrom(TgxFile3DSColorAnimationKeys) then
  285. Result := ctCol
  286. else if AAnimKeysClass.InheritsFrom(TTgxFile3DSPositionAnimationKeys) then
  287. Result := ctTPos
  288. else if AAnimKeysClass.InheritsFrom(TgxFile3DSSpotLightCutOffAnimationKeys) then
  289. Result := ctFall
  290. else if AAnimKeysClass.InheritsFrom(TgxFile3DSLightHotSpotAnimationKeys) then
  291. Result := ctHot
  292. else if AAnimKeysClass.InheritsFrom(TgxFile3DSRollAnimationKeys) then
  293. Result := ctRoll
  294. else
  295. begin
  296. Result := ctScale;
  297. Assert(False, strErrorEx + strUnknownType);
  298. end;
  299. end;
  300. function MakeRotationQuaternion(const axis: TAffineVector; angle: single): TQuaternion;
  301. var
  302. v: TVector4f;
  303. halfAngle, invAxisLengthMult: single;
  304. begin
  305. halfAngle := (angle) / 2;
  306. invAxisLengthMult := 1 / VectorLength(axis) * sin(halfAngle);
  307. v.X := axis.X * invAxisLengthMult;
  308. v.Y := axis.Y * invAxisLengthMult;
  309. v.Z := axis.Z * invAxisLengthMult;
  310. v.W := cos(halfAngle);
  311. Result.ImagPart := AffineVectorMake(v);
  312. Result.RealPart := v.W;
  313. end;
  314. function QuaternionToRotateMatrix(const Quaternion: TQuaternion): TMatrix4f;
  315. var
  316. wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2: single;
  317. quat: TVector4f;
  318. m: TMatrix4f;
  319. begin
  320. quat := VectorMake(Quaternion.ImagPart);
  321. quat.W := Quaternion.RealPart;
  322. x2 := quat.X + quat.X;
  323. y2 := quat.Y + quat.Y;
  324. z2 := quat.Z + quat.Z;
  325. xx := quat.X * x2;
  326. xy := quat.X * y2;
  327. xz := quat.X * z2;
  328. yy := quat.Y * y2;
  329. yz := quat.Y * z2;
  330. zz := quat.Z * z2;
  331. wx := quat.W * x2;
  332. wy := quat.W * y2;
  333. wz := quat.W * z2;
  334. m.X.X := 1.0 - (yy + zz);
  335. m.X.Y := xy - wz;
  336. m.X.Z := xz + wy;
  337. m.Y.X := xy + wz;
  338. m.Y.Y := 1.0 - (xx + zz);
  339. m.Y.Z := yz - wx;
  340. m.Z.X := xz - wy;
  341. m.Z.Y := yz + wx;
  342. m.Z.Z := 1.0 - (xx + yy);
  343. m.X.W := 0;
  344. m.Y.W := 0;
  345. m.Z.W := 0;
  346. m.W.X := 0;
  347. m.W.Y := 0;
  348. m.W.Z := 0;
  349. m.W.W := 1;
  350. Result := m;
  351. end;
  352. // ------------------
  353. // ------------------ Support classes ------------------
  354. // ------------------
  355. procedure TgxFile3DSAnimationKeys.InterpolateFrame(var I: integer; var w: real; const AFrame: real);
  356. begin
  357. w := 1;
  358. I := 0;
  359. if FNumKeys > 1 then
  360. begin
  361. while (FNumKeys > I) and ((FKeys[I].Time) <= AFrame) do
  362. Inc(I);
  363. if (FNumKeys > I) and ((FKeys[I - 1].Time) <= AFrame) then
  364. w := (AFrame - FKeys[I - 1].Time) / (FKeys[I].Time - FKeys[I - 1].Time);
  365. // Don't allow keys to go our of range.
  366. if I = FNumKeys then
  367. I := FNumKeys - 1;
  368. end;
  369. end;
  370. function TgxFile3DSAnimationKeys.InterpolateValue(const AValues: array of single; const AFrame: real): single;
  371. var
  372. I: integer;
  373. w: real;
  374. start, stop: single;
  375. begin
  376. InterpolateFrame(I, w, AFrame);
  377. if I > 0 then
  378. start := AValues[I - 1]
  379. else
  380. start := 0;
  381. if FNumKeys > I then
  382. stop := AValues[I]
  383. else
  384. stop := 0;
  385. Result := Lerp(start, stop, w);
  386. end;
  387. function TgxFile3DSAnimationKeys.InterpolateValue(const AValues: array of TAffineVector; const AFrame: real): TAffineVector;
  388. var
  389. I: integer;
  390. w: real;
  391. start, stop: TAffineVector;
  392. begin
  393. InterpolateFrame(I, w, AFrame);
  394. if I > 0 then
  395. start := AValues[I - 1]
  396. else
  397. start := NullVector;
  398. if FNumKeys > I then
  399. stop := AValues[I]
  400. else
  401. stop := NullVector;
  402. Result := VectorLerp(start, stop, w);
  403. end;
  404. function TgxFile3DSAnimationKeys.InterpolateValue(const AValues: array of TKFRotKey3DS; const AFrame: real): TMatrix4f;
  405. var
  406. I: integer;
  407. w: real;
  408. begin
  409. Result := IdentityHmgMatrix;
  410. // First find the final matrix for this frame.
  411. I := 0;
  412. while (FNumKeys > I) and ((FKeys[I].Time) <= AFrame) do
  413. begin
  414. with AValues[I] do
  415. Result := MatrixMultiply(Result, CreateRotationMatrix(AffineVectorMake(X, Y, Z), Angle));
  416. Inc(I);
  417. end;
  418. InterpolateFrame(I, w, AFrame);
  419. // Then interpolate this matrix
  420. if (FNumKeys > I) and ((FKeys[I].Time) > AFrame) and ((FKeys[I - 1].Time) < AFrame) then
  421. begin
  422. with AValues[I] do
  423. Result := MatrixMultiply(Result, CreateRotationMatrix(AffineVectorMake(X, Y, Z), AngleLerp(0, Angle, w)));
  424. end;
  425. end;
  426. procedure TgxFile3DSAnimationKeys.LoadData(const ANumKeys: integer; const Keys: PKeyHeaderList; const AData: Pointer);
  427. var
  428. I: integer;
  429. begin
  430. FNumKeys := ANumKeys;
  431. SetLength(FKeys, FNumKeys);
  432. for I := 0 to FNumKeys - 1 do
  433. FKeys[I] := Keys[I];
  434. end;
  435. procedure TgxFile3DSAnimationKeys.Assign(Source: TPersistent);
  436. var
  437. I: integer;
  438. begin
  439. if Source is TgxFile3DSAnimationKeys then
  440. begin
  441. FNumKeys := TgxFile3DSAnimationKeys(Source).FNumKeys;
  442. SetLength(FKeys, FNumKeys);
  443. for I := 0 to FNumKeys - 1 do
  444. FKeys[I] := TgxFile3DSAnimationKeys(Source).FKeys[I];
  445. end
  446. else
  447. inherited Assign(Source);
  448. end;
  449. procedure TgxFile3DSAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  450. begin
  451. Writer.WriteInteger(FNumKeys);
  452. if FNumKeys > 0 then
  453. Writer.Write(FKeys[0], FNumKeys * SizeOf(TKeyHeader3DS));
  454. end;
  455. procedure TgxFile3DSAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  456. begin
  457. FNumKeys := Reader.ReadInteger;
  458. SetLength(FKeys, FNumKeys);
  459. if FNumKeys > 0 then
  460. Reader.Read(FKeys[0], FNumKeys * SizeOf(TKeyHeader3DS));
  461. end;
  462. procedure TgxFile3DSScaleAnimationKeys.LoadData(const ANumKeys: integer;
  463. const Keys: PKeyHeaderList; const AData: Pointer);
  464. var
  465. I: integer;
  466. AffVect : TAffineVector;
  467. Sign : ShortInt;
  468. begin
  469. inherited;
  470. SetLength(FScale, FNumKeys);
  471. for I := 0 to FNumKeys - 1 do
  472. begin
  473. FScale[I] := TAffineVector(PPointList(AData)[I]);
  474. if vFile3DS_FixDefaultUpAxisY then
  475. begin
  476. AffVect := FScale[I];
  477. if (AffVect.X < 0) or (AffVect.Y < 0) or (AffVect.Z < 0) then
  478. Sign := -1
  479. else
  480. Sign:= 1;
  481. AffVect := VectorRotateAroundX(AffVect, cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  482. FScale[I].X := Sign * Abs(AffVect.X);
  483. FScale[I].Y := Sign * Abs(AffVect.Y);
  484. FScale[I].Z := Sign * Abs(AffVect.Z);
  485. end;
  486. end;
  487. end;
  488. procedure TgxFile3DSScaleAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData;
  489. const AFrame: real);
  490. begin
  491. if FNumKeys > 0 then
  492. DataTransf.ModelMatrix := MatrixMultiply(DataTransf.ModelMatrix,
  493. CreateScaleMatrix(InterpolateValue(FScale, AFrame)));
  494. end;
  495. procedure TgxFile3DSScaleAnimationKeys.Assign(Source: TPersistent);
  496. var
  497. I: integer;
  498. begin
  499. inherited;
  500. SetLength(FScale, FNumKeys);
  501. for I := 0 to FNumKeys - 1 do
  502. FScale[I] := (Source as TgxFile3DSScaleAnimationKeys).Fscale[I];
  503. end;
  504. procedure TgxFile3DSScaleAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  505. begin
  506. inherited;
  507. if FNumKeys > 0 then
  508. Writer.Write(FScale[0], FNumKeys * SizeOf(TPoint3DS));
  509. end;
  510. procedure TgxFile3DSScaleAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  511. begin
  512. inherited;
  513. SetLength(FScale, FNumKeys);
  514. if FNumKeys > 0 then
  515. Reader.Read(FScale[0], FNumKeys * SizeOf(TPoint3DS));
  516. end;
  517. procedure TgxFile3DSRotationAnimationKeys.LoadData(const ANumKeys: integer;
  518. const Keys: PKeyHeaderList; const AData: Pointer);
  519. var
  520. I: integer;
  521. Rot: PKFRotKeyList;
  522. AffVect : TAffineVector;
  523. begin
  524. inherited;
  525. SetLength(FRot, FNumKeys);
  526. Rot := PKFRotKeyList(AData);
  527. for I := 0 to FNumKeys - 1 do
  528. begin
  529. // The initial values do not contain any turns, that's why we have to make one.
  530. if (Rot[I].X = 0) and (Rot[I].Y = 0) and (Rot[I].Z = 0) then
  531. Rot[I].X := 1;
  532. // One quartalion can't describe a big angle (>180), that's why we have to subtract it from 2*pi
  533. if Rot[I].Angle > pi then
  534. begin
  535. Rot[I].Angle := 2 * pi - Rot[I].Angle;
  536. Rot[I].X := -Rot[I].X;
  537. Rot[I].Y := -Rot[I].Y;
  538. Rot[I].Z := -Rot[I].Z;
  539. end;
  540. FRot[I] := Rot[I];
  541. if vFile3DS_FixDefaultUpAxisY then
  542. begin
  543. AffVect.X := FRot[I].X;
  544. AffVect.Y := FRot[I].Y;
  545. AffVect.Z := FRot[I].Z;
  546. AffVect := VectorRotateAroundX(AffVect, cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  547. FRot[I].X := AffVect.X;
  548. FRot[I].Y := AffVect.Y;
  549. FRot[I].Z := AffVect.Z;
  550. end;
  551. end;
  552. end;
  553. procedure TgxFile3DSRotationAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData; const AFrame: real);
  554. begin
  555. if FNumKeys > 0 then
  556. DataTransf.ModelMatrix := MatrixMultiply(DataTransf.ModelMatrix,
  557. InterpolateValue(FRot, AFrame));
  558. end;
  559. procedure TgxFile3DSRotationAnimationKeys.Assign(Source: TPersistent);
  560. var
  561. I: integer;
  562. begin
  563. inherited;
  564. SetLength(FRot, FNumKeys);
  565. for I := 0 to FNumKeys - 1 do
  566. FRot[I] := (Source as TgxFile3DSRotationAnimationKeys).FRot[I];
  567. end;
  568. procedure TgxFile3DSRotationAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  569. begin
  570. inherited;
  571. if FNumKeys > 0 then
  572. Writer.Write(FRot[0], FNumKeys * SizeOf(TKFRotKey3DS));
  573. end;
  574. procedure TgxFile3DSRotationAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  575. begin
  576. inherited;
  577. SetLength(FRot, FNumKeys);
  578. if FNumKeys > 0 then
  579. Reader.Read(FRot[0], FNumKeys * SizeOf(TKFRotKey3DS));
  580. end;
  581. procedure TgxFile3DSPositionAnimationKeys.LoadData(const ANumKeys: integer;
  582. const Keys: PKeyHeaderList; const AData: Pointer);
  583. var
  584. I: integer;
  585. begin
  586. inherited;
  587. SetLength(FPos, FNumKeys);
  588. for I := 0 to FNumKeys - 1 do
  589. begin
  590. FPos[I] := TAffineVector(PPointList(AData)[I]);
  591. if vFile3DS_FixDefaultUpAxisY then
  592. begin
  593. FPos[I] := VectorRotateAroundX(FPos[I], cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  594. end;
  595. end;
  596. end;
  597. procedure TgxFile3DSPositionAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData;
  598. const AFrame: real);
  599. begin
  600. if FNumKeys > 0 then
  601. DataTransf.ModelMatrix.W :=
  602. VectorAdd(DataTransf.ModelMatrix.W, VectorMake(InterpolateValue(FPos, AFrame)));
  603. end;
  604. procedure TgxFile3DSPositionAnimationKeys.Assign(Source: TPersistent);
  605. var
  606. I: integer;
  607. begin
  608. inherited;
  609. SetLength(FPos, FNumKeys);
  610. for I := 0 to FNumKeys - 1 do
  611. FPos[I] := (Source as TgxFile3DSPositionAnimationKeys).FPos[I];
  612. end;
  613. procedure TgxFile3DSPositionAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  614. begin
  615. inherited;
  616. if FNumKeys > 0 then
  617. Writer.Write(FPos[0], FNumKeys * SizeOf(TPoint3DS));
  618. end;
  619. procedure TgxFile3DSPositionAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  620. begin
  621. inherited;
  622. SetLength(FPos, FNumKeys);
  623. if FNumKeys > 0 then
  624. Reader.Read(FPos[0], FNumKeys * SizeOf(TPoint3DS));
  625. end;
  626. procedure TgxFile3DSColorAnimationKeys.LoadData(const ANumKeys: integer;
  627. const Keys: PKeyHeaderList; const AData: Pointer);
  628. var
  629. I: integer;
  630. begin
  631. inherited;
  632. SetLength(FCol, FNumKeys);
  633. for I := 0 to FNumKeys - 1 do
  634. FCol[I] := TaffineVector(PFColorList(AData)[I]);
  635. end;
  636. procedure TgxFile3DSColorAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData;
  637. const AFrame: real);
  638. begin
  639. if FNumKeys > 0 then
  640. DataTransf.Color := VectorAdd(DataTransf.Color,
  641. VectorMake(InterpolateValue(FCol, AFrame)));
  642. end;
  643. procedure TgxFile3DSColorAnimationKeys.Assign(Source: TPersistent);
  644. var
  645. I: integer;
  646. begin
  647. inherited;
  648. SetLength(FCol, FNumKeys);
  649. for I := 0 to FNumKeys - 1 do
  650. FCol[I] := (Source as TgxFile3DSColorAnimationKeys).FCol[I];
  651. end;
  652. procedure TgxFile3DSColorAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  653. begin
  654. inherited;
  655. if FNumKeys > 0 then
  656. Writer.Write(FCol[0], FNumKeys * SizeOf(TFColor3DS));
  657. end;
  658. procedure TgxFile3DSColorAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  659. begin
  660. inherited;
  661. SetLength(FCol, FNumKeys);
  662. if FNumKeys > 0 then
  663. Reader.Read(FCol[0], FNumKeys * SizeOf(TFColor3DS));
  664. end;
  665. procedure TTgxFile3DSPositionAnimationKeys.LoadData(const ANumKeys: integer;
  666. const Keys: PKeyHeaderList; const AData: Pointer);
  667. var
  668. I: integer;
  669. begin
  670. inherited;
  671. SetLength(FTPos, FNumKeys);
  672. for I := 0 to FNumKeys - 1 do
  673. begin
  674. FTPos[I] := TaffineVector(PPointList(AData)[I]);
  675. if vFile3DS_FixDefaultUpAxisY then
  676. begin
  677. FTPos[I] := VectorRotateAroundX(FTPos[I], cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  678. end;
  679. end;
  680. end;
  681. procedure TTgxFile3DSPositionAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData;
  682. const AFrame: real);
  683. begin
  684. if FNumKeys > 0 then
  685. DataTransf.TargetPos := VectorAdd(DataTransf.TargetPos,
  686. InterpolateValue(FTPos, AFrame));
  687. end;
  688. procedure TTgxFile3DSPositionAnimationKeys.Assign(Source: TPersistent);
  689. var
  690. I: integer;
  691. begin
  692. inherited;
  693. SetLength(FTPos, FNumKeys);
  694. for I := 0 to FNumKeys - 1 do
  695. FTPos[I] := (Source as TTgxFile3DSPositionAnimationKeys).FTPos[I];
  696. end;
  697. procedure TTgxFile3DSPositionAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  698. begin
  699. inherited;
  700. if FNumKeys > 0 then
  701. Writer.Write(FTPos[0], FNumKeys * SizeOf(TPoint3DS));
  702. end;
  703. procedure TTgxFile3DSPositionAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  704. begin
  705. inherited;
  706. SetLength(FTPos, FNumKeys);
  707. if FNumKeys > 0 then
  708. Reader.Read(FTPos[0], FNumKeys * SizeOf(TPoint3DS));
  709. end;
  710. procedure TgxFile3DSSpotLightCutOffAnimationKeys.LoadData(const ANumKeys: integer;
  711. const Keys: PKeyHeaderList; const AData: Pointer);
  712. var
  713. I: integer;
  714. begin
  715. inherited;
  716. SetLength(FFall, FNumKeys);
  717. for I := 0 to FNumKeys - 1 do
  718. FFall[I] := PSingleList(AData)[I];
  719. end;
  720. procedure TgxFile3DSSpotLightCutOffAnimationKeys.Apply(
  721. var DataTransf: TgxFile3DSAnimationData; const AFrame: real);
  722. begin
  723. if FNumKeys > 0 then
  724. DataTransf.SpotLightCutOff :=
  725. DataTransf.SpotLightCutOff + InterpolateValue(FFall, AFrame);
  726. end;
  727. procedure TgxFile3DSSpotLightCutOffAnimationKeys.Assign(Source: TPersistent);
  728. var
  729. I: integer;
  730. begin
  731. inherited;
  732. SetLength(FFall, FNumKeys);
  733. for I := 0 to FNumKeys - 1 do
  734. FFall[I] := (Source as TgxFile3DSSpotLightCutOffAnimationKeys).FFall[I];
  735. end;
  736. procedure TgxFile3DSSpotLightCutOffAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  737. begin
  738. inherited;
  739. if FNumKeys > 0 then
  740. Writer.Write(FFall[0], FNumKeys * SizeOf(single));
  741. end;
  742. procedure TgxFile3DSSpotLightCutOffAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  743. begin
  744. inherited;
  745. SetLength(FFall, FNumKeys);
  746. if FNumKeys > 0 then
  747. Reader.Read(FFall[0], FNumKeys * SizeOf(single));
  748. end;
  749. procedure TgxFile3DSLightHotSpotAnimationKeys.LoadData(const ANumKeys: integer;
  750. const Keys: PKeyHeaderList; const AData: Pointer);
  751. var
  752. I: integer;
  753. begin
  754. inherited;
  755. SetLength(FHot, FNumKeys);
  756. for I := 0 to FNumKeys - 1 do
  757. FHot[I] := PSingleList(AData)[I];
  758. end;
  759. procedure TgxFile3DSLightHotSpotAnimationKeys.Apply(
  760. var DataTransf: TgxFile3DSAnimationData; const AFrame: real);
  761. begin
  762. if FNumKeys > 0 then
  763. DataTransf.HotSpot := DataTransf.HotSpot + InterpolateValue(FHot, AFrame);
  764. end;
  765. procedure TgxFile3DSLightHotSpotAnimationKeys.Assign(Source: TPersistent);
  766. var
  767. I: integer;
  768. begin
  769. inherited;
  770. SetLength(FHot, FNumKeys);
  771. for I := 0 to FNumKeys - 1 do
  772. FHot[I] := (Source as TgxFile3DSLightHotSpotAnimationKeys).FHot[I];
  773. end;
  774. procedure TgxFile3DSLightHotSpotAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  775. begin
  776. inherited;
  777. if FNumKeys > 0 then
  778. Writer.Write(FHot[0], FNumKeys * SizeOf(single));
  779. end;
  780. procedure TgxFile3DSLightHotSpotAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  781. begin
  782. inherited;
  783. SetLength(FHot, FNumKeys);
  784. if FNumKeys > 0 then
  785. Reader.Read(FHot[0], FNumKeys * SizeOf(single));
  786. end;
  787. procedure TgxFile3DSRollAnimationKeys.LoadData(const ANumKeys: integer;
  788. const Keys: PKeyHeaderList; const AData: Pointer);
  789. var
  790. I: integer;
  791. begin
  792. inherited;
  793. SetLength(FRoll, FNumKeys);
  794. for I := 0 to FNumKeys - 1 do
  795. FRoll[I] := PSingleList(AData)[I];
  796. end;
  797. procedure TgxFile3DSRollAnimationKeys.Apply(var DataTransf: TgxFile3DSAnimationData;
  798. const AFrame: real);
  799. begin
  800. if FNumKeys > 0 then
  801. DataTransf.Roll := DataTransf.Roll + InterpolateValue(FRoll, AFrame);
  802. end;
  803. procedure TgxFile3DSRollAnimationKeys.Assign(Source: TPersistent);
  804. var
  805. I: integer;
  806. begin
  807. inherited;
  808. SetLength(FRoll, FNumKeys);
  809. for I := 0 to FNumKeys - 1 do
  810. FRoll[I] := (Source as TgxFile3DSRollAnimationKeys).FRoll[I];
  811. end;
  812. procedure TgxFile3DSRollAnimationKeys.WriteToFiler(Writer: TgxVirtualWriter);
  813. begin
  814. inherited;
  815. if FNumKeys > 0 then
  816. Writer.Write(FRoll[0], FNumKeys * SizeOf(single));
  817. end;
  818. procedure TgxFile3DSRollAnimationKeys.ReadFromFiler(Reader: TgxVirtualReader);
  819. begin
  820. inherited;
  821. SetLength(FRoll, FNumKeys);
  822. if FNumKeys > 0 then
  823. Reader.Read(FRoll[0], FNumKeys * SizeOf(single));
  824. end;
  825. procedure TgxFile3DSAnimationKeyList.AddKeys(const AItem: TgxFile3DSAnimationKeys);
  826. var
  827. ind: integer;
  828. begin
  829. if AItem = nil then
  830. Exit;
  831. ind := Length(FAnimKeysList);
  832. SetLength(FAnimKeysList, ind + 1);
  833. FAnimKeysList[ind] := AItem;
  834. end;
  835. procedure TgxFile3DSAnimationKeyList.ApplyAnimKeys(
  836. var DataTransf: TgxFile3DSAnimationData; const AFrame: real);
  837. var
  838. I: integer;
  839. begin
  840. for I := 0 to Length(FAnimKeysList) - 1 do
  841. FAnimKeysList[I].Apply(DataTransf, AFrame);
  842. end;
  843. procedure TgxFile3DSAnimationKeyList.ClearKeys;
  844. var
  845. I: integer;
  846. begin
  847. for I := 0 to Length(FAnimKeysList) - 1 do
  848. FAnimKeysList[I].Free;
  849. SetLength(FAnimKeysList, 0);
  850. end;
  851. procedure TgxFile3DSAnimationKeyList.Assign(Source: TPersistent);
  852. var
  853. I: integer;
  854. item: TgxFile3DSAnimationKeys;
  855. begin
  856. if Source is TgxFile3DSAnimationKeyList then
  857. begin
  858. ClearKeys;
  859. for I := 0 to Length(TgxFile3DSAnimationKeyList(Source).FAnimKeysList) - 1 do
  860. begin
  861. item := (TgxFile3DSAnimationKeyList(Source).FAnimKeysList[I].ClassType.Create as
  862. TgxFile3DSAnimationKeys);
  863. item.Assign(TgxFile3DSAnimationKeyList(Source).FAnimKeysList[I]);
  864. AddKeys(item);
  865. end;
  866. end
  867. else
  868. inherited Assign(Source);
  869. end;
  870. procedure TgxFile3DSAnimationKeyList.WriteToFiler(Writer: TgxVirtualWriter);
  871. var
  872. I: integer;
  873. Val: TgxFile3DSAnimKeysClassType;
  874. begin
  875. Writer.WriteInteger(Length(FAnimKeysList));
  876. for I := 0 to Length(FAnimKeysList) - 1 do
  877. begin
  878. Val := ClassToAnimKeysClassType(FAnimKeysList[I].ClassType);
  879. Writer.Write(Val, SizeOf(Val));
  880. FAnimKeysList[I].WriteToFiler(Writer);
  881. end;
  882. end;
  883. procedure TgxFile3DSAnimationKeyList.ReadFromFiler(Reader: TgxVirtualReader);
  884. var
  885. I, cnt: integer;
  886. Val: TgxFile3DSAnimKeysClassType;
  887. begin
  888. ClearKeys;
  889. cnt := Reader.ReadInteger;
  890. SetLength(FAnimKeysList, cnt);
  891. for I := 0 to Length(FAnimKeysList) - 1 do
  892. begin
  893. Reader.Read(Val, SizeOf(Val));
  894. FAnimKeysList[I] := AnimKeysClassTypeToClass(Val).Create as TgxFile3DSAnimationKeys;
  895. FAnimKeysList[I].ReadFromFiler(Reader);
  896. end;
  897. end;
  898. destructor TgxFile3DSAnimationKeyList.Destroy;
  899. begin
  900. ClearKeys;
  901. inherited Destroy;
  902. end;
  903. constructor TgxFile3DSDummyObject.Create;
  904. begin
  905. inherited;
  906. FAnimList := TgxFile3DSAnimationKeyList.Create;
  907. FRefTranf.ModelMatrix := IdentityHmgMatrix;
  908. FAnimTransf.ModelMatrix := IdentityHmgMatrix;
  909. FStatic := False;
  910. end;
  911. procedure TgxFile3DSDummyObject.LoadAnimation(const AData: Pointer);
  912. begin
  913. FAnimList.ClearKeys;
  914. FAnimData := AData;
  915. end;
  916. procedure TgxFile3DSDummyObject.SetFrame(const AFrame: real);
  917. var
  918. p: TgxFile3DSDummyObject;
  919. lAnimationData: TgxFile3DSAnimationData;
  920. begin
  921. if not vFile3DS_EnableAnimation then
  922. Exit;
  923. if (FParentName <> '') then
  924. begin
  925. FParent := Owner.FindMeshByName(string(FParentName)) as TgxFile3DSDummyObject;
  926. FParentName := '';
  927. end;
  928. lAnimationData := FRefTranf;
  929. p := self;
  930. while p <> nil do
  931. begin
  932. p.FAnimList.ApplyAnimKeys(lAnimationData, AFrame);
  933. p := p.FParent;
  934. end;
  935. FAnimTransf := lAnimationData;
  936. end;
  937. procedure TgxFile3DSDummyObject.MorphTo(morphTargetIndex: integer);
  938. begin
  939. SetFrame(morphTargetIndex);
  940. end;
  941. procedure TgxFile3DSDummyObject.Lerp(morphTargetIndex1, morphTargetIndex2: integer;
  942. lerpFactor: single);
  943. begin
  944. if (Owner.Owner is TgxActor) and ((Owner.Owner as TgxActor).AnimationMode in
  945. [aamBounceBackward, aamLoopBackward]) then
  946. SetFrame(morphTargetIndex1 - lerpFactor)
  947. else
  948. SetFrame(morphTargetIndex1 + lerpFactor);
  949. end;
  950. procedure TgxFile3DSDummyObject.Assign(Source: TPersistent);
  951. begin
  952. inherited; // Assign all published properties here.
  953. if Source is TgxFile3DSDummyObject then
  954. begin
  955. FRefTranf := (Source as TgxFile3DSDummyObject).FRefTranf;
  956. FParent := (Source as TgxFile3DSDummyObject).FParent;
  957. FAnimList.Assign((Source as TgxFile3DSDummyObject).FAnimList);
  958. SetFrame(0);
  959. end;
  960. end;
  961. procedure TgxFile3DSDummyObject.GetExtents(out min, max: TAffineVector);
  962. begin
  963. inherited GetExtents(min, max);
  964. if not FStatic then
  965. begin
  966. if not IsInfinite(min.X) then
  967. min := VectorTransform(min, FAnimTransf.ModelMatrix);
  968. if not IsInfinite(max.X) then
  969. max := VectorTransform(max, FAnimTransf.ModelMatrix);
  970. end;
  971. end;
  972. function TgxFile3DSDummyObject.ExtractTriangles(texCoords, normals: TgxAffineVectorList):
  973. TgxAffineVectorList;
  974. var
  975. I: integer;
  976. begin
  977. Result := inherited ExtractTriangles(texCoords, normals);
  978. if not FStatic then
  979. begin
  980. if (Result.Count <> 0) and not MatrixEquals(FAnimTransf.ModelMatrix,
  981. IdentityHmgMatrix) then
  982. for I := 0 to Result.Count - 1 do
  983. Result[I] := VectorTransform(Result[I], FAnimTransf.ModelMatrix);
  984. end;
  985. end;
  986. procedure TgxFile3DSDummyObject.WriteToFiler(Writer: TgxVirtualWriter);
  987. var
  988. str: string;
  989. begin
  990. inherited;
  991. Writer.Write(FRefTranf, SizeOf(FRefTranf));
  992. if FParent <> nil then
  993. str := Copy(FParent.Name, 1, 32)
  994. else
  995. str := 'nil';
  996. Writer.WriteString(str);
  997. FAnimList.WriteToFiler(Writer);
  998. end;
  999. procedure TgxFile3DSDummyObject.ReadFromFiler(Reader: TgxVirtualReader);
  1000. begin
  1001. inherited;
  1002. Reader.Read(FRefTranf, SizeOf(FRefTranf));
  1003. FParentName := String64(Copy(Reader.ReadString, 1, 64));
  1004. if FParentName = 'nil' then
  1005. FParentName := '';
  1006. FAnimList.ReadFromFiler(Reader);
  1007. end;
  1008. destructor TgxFile3DSDummyObject.Destroy;
  1009. begin
  1010. FAnimList.Free;
  1011. inherited;
  1012. end;
  1013. procedure TgxFile3DSMeshObject.LoadAnimation(const AData: Pointer);
  1014. var
  1015. aScale: TgxFile3DSScaleAnimationKeys;
  1016. aRot: TgxFile3DSRotationAnimationKeys;
  1017. aPos: TgxFile3DSPositionAnimationKeys;
  1018. Mat : TMatrix4f;
  1019. RotMat : TMatrix4f;
  1020. AffVect : TAffineVector;
  1021. begin
  1022. inherited;
  1023. with PKFMesh3DS(AData)^, FAnimList do
  1024. begin
  1025. aScale := TgxFile3DSScaleAnimationKeys.Create;
  1026. aScale.LoadData(NSKeys, SKeys, Scale);
  1027. AddKeys(aScale);
  1028. aRot := TgxFile3DSRotationAnimationKeys.Create;
  1029. aRot.LoadData(NRKeys, RKeys, Rot);
  1030. AddKeys(aRot);
  1031. aPos := TgxFile3DSPositionAnimationKeys.Create;
  1032. aPos.LoadData(NPKeys, PKeys, Pos);
  1033. AddKeys(aPos);
  1034. if ParentStr <> '' then
  1035. FParent := TgxFile3DSDummyObject(Owner.FindMeshByName(string(ParentStr)));
  1036. with FRefTranf do
  1037. begin
  1038. if vFile3DS_FixDefaultUpAxisY then
  1039. begin
  1040. RotMat := CreateRotationMatrixX(cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  1041. InvertMatrix(RotMat);
  1042. Mat := ModelMatrix;
  1043. ModelMatrix := MatrixMultiply(Mat, RotMat);
  1044. AffVect.X := Pivot.X;
  1045. AffVect.Y := Pivot.Y;
  1046. AffVect.Z := Pivot.Z;
  1047. AffVect := VectorRotateAroundX(AffVect, cGLFILE3DS_FIXDEFAULTUPAXISY_ROTATIONVALUE);
  1048. Pivot.X := AffVect.X;
  1049. Pivot.Y := AffVect.Y;
  1050. Pivot.Z := AffVect.Z;
  1051. end;
  1052. ModelMatrix.W.X := ModelMatrix.W.X - Pivot.X;
  1053. ModelMatrix.W.Y := ModelMatrix.W.Y - Pivot.Y;
  1054. ModelMatrix.W.Z := ModelMatrix.W.Z - Pivot.Z;
  1055. end;
  1056. end;
  1057. if vFile3DS_LoadedStaticFrame = -1 then
  1058. SetFrame(CGLFILE3DS_DEFAULT_FRAME)
  1059. else
  1060. SetFrame(vFile3DS_LoadedStaticFrame);
  1061. end;
  1062. procedure TgxFile3DSMeshObject.BuildList(var ARci: TgxRenderContextInfo);
  1063. begin
  1064. glPushMatrix;
  1065. if not FStatic then
  1066. glMultMatrixf(@FAnimTransf.ModelMatrix);
  1067. inherited;
  1068. glPopMatrix;
  1069. end;
  1070. constructor TgxFile3DSOmniLightObject.Create;
  1071. begin
  1072. inherited;
  1073. FLightSrc := TgxFile3DSLight.Create(nil);
  1074. end;
  1075. procedure TgxFile3DSOmniLightObject.LoadData(const AOwner: TgxBaseMesh;
  1076. const AData: PLight3DS);
  1077. begin
  1078. FLightSrc.Parent := AOwner;
  1079. FLightSrc.LightStyle := lsOmni;
  1080. FLightSrc.Name := string(AData.NameStr);
  1081. Name := string(AData.NameStr);
  1082. FLightSrc.Position.SetPoint(PAffineVector(@AData.Pos)^);
  1083. FLightSrc.Diffuse.Color := VectorMake(AData.Color.R, AData.Color.G, AData.Color.B);
  1084. FLightSrc.Specular.Color := VectorMake(AData.Color.R, AData.Color.G, AData.Color.B);
  1085. FLightSrc.Diffuse.Color := VectorScale(FLightSrc.Diffuse.Color, AData.Multiplier);
  1086. //íàäî ïîòåñòèòü
  1087. FLightSrc.Shining := not AData.DLOff;
  1088. FLightSrc.Multipler := AData.Multiplier;
  1089. FLightSrc.ConstAttenuation := 1;
  1090. FLightSrc.LinearAttenuation := 0;
  1091. FLightSrc.QuadraticAttenuation := 0;
  1092. end;
  1093. procedure TgxFile3DSOmniLightObject.LoadAnimation(const AData: Pointer);
  1094. var
  1095. aPos: TgxFile3DSPositionAnimationKeys;
  1096. aCol: TgxFile3DSColorAnimationKeys;
  1097. begin
  1098. inherited;
  1099. with PKFOmni3DS(AData)^, FAnimList do
  1100. begin
  1101. aPos := TgxFile3DSPositionAnimationKeys.Create;
  1102. aPos.LoadData(NPKeys, PKeys, Pos);
  1103. AddKeys(aPos);
  1104. aCol := TgxFile3DSColorAnimationKeys.Create;
  1105. aCol.LoadData(NCKeys, CKeys, Color);
  1106. AddKeys(aCol);
  1107. if Parent <> '' then
  1108. FParent := TgxFile3DSDummyObject(Owner.FindMeshByName(string(Parent)));
  1109. end;
  1110. if vFile3DS_LoadedStaticFrame = -1 then
  1111. SetFrame(CGLFILE3DS_DEFAULT_FRAME)
  1112. else
  1113. SetFrame(vFile3DS_LoadedStaticFrame);
  1114. end;
  1115. procedure TgxFile3DSOmniLightObject.SetFrame(const AFrame: real);
  1116. var
  1117. obj: TComponent;
  1118. begin
  1119. if FLightSrcName <> '' then
  1120. begin
  1121. obj := Owner.Owner.FindChild(string(FLightSrcName), True);
  1122. if obj is TgxFile3DSLight then
  1123. begin
  1124. FLightSrc.Free;
  1125. FLightSrc := obj as TgxFile3DSLight;
  1126. end;
  1127. FLightSrcName := '';
  1128. end;
  1129. inherited;
  1130. FLightSrc.Position.SetPoint(FAnimTransf.ModelMatrix.W);
  1131. FLightSrc.Diffuse.Color := FAnimTransf.Color;
  1132. end;
  1133. procedure TgxFile3DSOmniLightObject.Assign(Source: TPersistent);
  1134. begin
  1135. inherited;
  1136. if Source is TgxFile3DSOmniLightObject then
  1137. FlightSrc.Assign((Source as TgxFile3DSOmniLightObject).FLightSrc);
  1138. end;
  1139. procedure TgxFile3DSOmniLightObject.WriteToFiler(Writer: TgxVirtualWriter);
  1140. var
  1141. str: string;
  1142. begin
  1143. inherited;
  1144. if FLightSrc.Name = '' then
  1145. str := 'nil'
  1146. else
  1147. str := Copy(FLightSrc.Name, 1, 64);
  1148. Writer.WriteString(str);
  1149. end;
  1150. procedure TgxFile3DSOmniLightObject.ReadFromFiler(Reader: TgxVirtualReader);
  1151. begin
  1152. inherited;
  1153. FLightSrcName := String64(Copy(Reader.ReadString, 1, 64));
  1154. if FLightSrcName = 'nil' then
  1155. FLightSrcName := '';
  1156. end;
  1157. destructor TgxFile3DSOmniLightObject.Destroy;
  1158. begin
  1159. FLightSrc.Free;
  1160. inherited;
  1161. end;
  1162. procedure TgxFile3DSSpotLightObject.LoadData(const AOwner: TgxBaseMesh;
  1163. const AData: PLight3DS);
  1164. begin
  1165. inherited;
  1166. FLightSrc.LightStyle := lsSpot;
  1167. FLightSrc.SpotTargetPos.SetPoint(TAffineVector(AData.Spot.Target));
  1168. FLightSrc.SpotCutOff := AData.Spot.FallOff / 2;
  1169. FLightSrc.HotSpot := AData.Spot.Hotspot / 2;
  1170. end;
  1171. procedure TgxFile3DSSpotLightObject.LoadAnimation(const AData: Pointer);
  1172. var
  1173. aTPos: TTgxFile3DSPositionAnimationKeys;
  1174. aFall: TgxFile3DSSpotLightCutOffAnimationKeys;
  1175. aHot: TgxFile3DSLightHotSpotAnimationKeys;
  1176. begin
  1177. inherited;
  1178. with PKFSpot3DS(AData)^, FAnimList do
  1179. begin
  1180. aTPos := TTgxFile3DSPositionAnimationKeys.Create;
  1181. aTPos.LoadData(NTKeys, TKeys, TPos);
  1182. AddKeys(aTPos);
  1183. aFall := TgxFile3DSSpotLightCutOffAnimationKeys.Create;
  1184. aFall.LoadData(NFKeys, FKeys, Fall);
  1185. AddKeys(aFall);
  1186. aHot := TgxFile3DSLightHotSpotAnimationKeys.Create;
  1187. aHot.LoadData(NHKeys, HKeys, Hot);
  1188. AddKeys(aHot);
  1189. if Parent <> '' then
  1190. FParent := TgxFile3DSDummyObject(Owner.FindMeshByName(string(Parent)));
  1191. end;
  1192. if vFile3DS_LoadedStaticFrame = -1 then
  1193. SetFrame(CGLFILE3DS_DEFAULT_FRAME)
  1194. else
  1195. SetFrame(vFile3DS_LoadedStaticFrame);
  1196. end;
  1197. procedure TgxFile3DSSpotLightObject.SetFrame(const AFrame: real);
  1198. begin
  1199. inherited;
  1200. FLightSrc.SpotTargetPos.SetPoint(FAnimTransf.TargetPos);
  1201. FLightSrc.SpotCutOff := FAnimTransf.SpotLightCutOff / 2;
  1202. FLightSrc.HotSpot := FAnimTransf.HotSpot / 2;
  1203. end;
  1204. constructor TgxFile3DSCameraObject.Create;
  1205. begin
  1206. inherited;
  1207. FCameraSrc := TgxFile3DSCamera.Create(nil);
  1208. FTargetObj := TgxDummyCube.Create(nil);
  1209. FCameraSrc.TargetObject := FTargetObj;
  1210. end;
  1211. procedure TgxFile3DSCameraObject.LoadData(Owner: TgxBaseMesh; AData: PCamera3DS);
  1212. begin
  1213. FCameraSrc.Parent := Owner;
  1214. FTargetObj.Parent := Owner;
  1215. FCameraSrc.Name := string(AData.NameStr);
  1216. Name := string(AData.NameStr);
  1217. FCameraSrc.Position.AsAffineVector := TAffineVector(AData.Position);
  1218. FTargetObj.Position.SetPoint(TAffineVector(AData.Target));
  1219. FCameraSrc.RollAngle := AData.Roll;
  1220. FCameraSrc.FocalLength := AData.FOV;
  1221. end;
  1222. procedure TgxFile3DSCameraObject.LoadAnimation(const AData: Pointer);
  1223. var
  1224. aPos: TgxFile3DSPositionAnimationKeys;
  1225. aRoll: TgxFile3DSRollAnimationKeys;
  1226. aTPos: TTgxFile3DSPositionAnimationKeys;
  1227. begin
  1228. inherited;
  1229. with PKFCamera3DS(AData)^, FAnimList do
  1230. begin
  1231. aPos := TgxFile3DSPositionAnimationKeys.Create;
  1232. aPos.LoadData(NPKeys, PKeys, Pos);
  1233. AddKeys(aPos);
  1234. aRoll := TgxFile3DSRollAnimationKeys.Create;
  1235. aRoll.LoadData(NRKeys, RKeys, Roll);
  1236. AddKeys(aRoll);
  1237. aTPos := TTgxFile3DSPositionAnimationKeys.Create;
  1238. aTPos.LoadData(NTKeys, TKeys, TPos);
  1239. AddKeys(aTPos);
  1240. end;
  1241. if vFile3DS_LoadedStaticFrame = -1 then
  1242. SetFrame(CGLFILE3DS_DEFAULT_FRAME)
  1243. else
  1244. SetFrame(vFile3DS_LoadedStaticFrame);
  1245. end;
  1246. procedure TgxFile3DSCameraObject.SetFrame(const AFrame: real);
  1247. var
  1248. obj: TComponent;
  1249. begin
  1250. inherited;
  1251. if FCameraSrcName <> '' then
  1252. begin
  1253. obj := Owner.Owner.FindChild(string(FCameraSrcName), True);
  1254. if obj is TgxFile3DSCamera then
  1255. begin
  1256. FCameraSrc.Free;
  1257. FCameraSrc := obj as TgxFile3DSCamera;
  1258. end;
  1259. FCameraSrcName := '';
  1260. end;
  1261. FCameraSrc.Position.SetPoint(FAnimTransf.ModelMatrix.W);
  1262. FCameraSrc.RollAngle := FAnimTransf.Roll;
  1263. FTargetObj.Position.SetPoint(FAnimTransf.TargetPos);
  1264. end;
  1265. procedure TgxFile3DSCameraObject.WriteToFiler(Writer: TgxVirtualWriter);
  1266. var
  1267. str: string;
  1268. begin
  1269. inherited;
  1270. if FCameraSrc.Name = '' then
  1271. str := 'nil'
  1272. else
  1273. str := Copy(FCameraSrc.Name, 1, 64);
  1274. Writer.WriteString(str);
  1275. end;
  1276. procedure TgxFile3DSCameraObject.ReadFromFiler(Reader: TgxVirtualReader);
  1277. begin
  1278. inherited;
  1279. FCameraSrcName := String64(Copy(Reader.ReadString, 1, 64));
  1280. if FCameraSrcName = 'nil' then
  1281. FCameraSrcName := '';
  1282. end;
  1283. destructor TgxFile3DSCameraObject.Destroy;
  1284. begin
  1285. FCameraSrc.Free;
  1286. FTargetObj.Free;
  1287. inherited;
  1288. end;
  1289. // ------------------
  1290. // ------------------ TGL3DSVectorFile ------------------
  1291. // ------------------
  1292. class function Tgx3DSVectorFile.Capabilities: TDataFileCapabilities;
  1293. begin
  1294. Result := [dfcRead];
  1295. end;
  1296. procedure Tgx3DSVectorFile.LoadFromStream(aStream: TStream);
  1297. type
  1298. TSmoothIndexEntry = array[0..31] of cardinal;
  1299. PSmoothIndexArray = ^TSmoothIndexArray;
  1300. TSmoothIndexArray = array[0..MaxInt shr 8] of TSmoothIndexEntry;
  1301. var
  1302. Marker: PByteArray;
  1303. CurrentVertexCount: integer;
  1304. SmoothIndices: PSmoothIndexArray;
  1305. mesh: TgxFile3DSMeshObject;
  1306. hasLightmap: boolean;
  1307. //--------------- local functions -------------------------------------------
  1308. function GetOrAllocateMaterial(materials: TMaterialList; const Name: string): string;
  1309. var
  1310. material: PMaterial3DS;
  1311. specColor: TVector4f;
  1312. matLib: TgxMaterialLibrary;
  1313. libMat, SecondMaterial: TgxLibMaterial;
  1314. begin
  1315. material := Materials.MaterialByName[Name];
  1316. Assert(Assigned(material));
  1317. if GetOwner is TgxBaseMesh then
  1318. begin
  1319. matLib := TgxBaseMesh(GetOwner).MaterialLibrary;
  1320. if Assigned(matLib) then
  1321. begin
  1322. Result := Name;
  1323. libMat := matLib.Materials.GetLibMaterialByName(Name);
  1324. if not Assigned(libMat) then
  1325. begin
  1326. libMat := matLib.Materials.Add;
  1327. libMat.Name := Name;
  1328. with libMat.Material.FrontProperties do
  1329. begin
  1330. Ambient.Color := VectorMake(material.Ambient.R, material.Ambient.G,
  1331. material.Ambient.B, 1);
  1332. // Material transparency can be stored as a positive or negative value.
  1333. Diffuse.Color := VectorMake(material.Diffuse.R, material.Diffuse.G,
  1334. material.Diffuse.B, 1 - Abs(material.Transparency));
  1335. specColor := VectorMake(material.Specular.R, material.Specular.G,
  1336. material.Specular.B, 1);
  1337. Specular.Color := VectorScale(specColor, material.ShinStrength);
  1338. Shininess := MaxInteger(0, integer(round((material.Shininess) * 128)));
  1339. if material.Transparency <> 0 then
  1340. libMat.Material.BlendingMode := bmTransparency;
  1341. end;
  1342. if Trim(string(material.Texture.Map.NameStr)) <> '' then
  1343. try
  1344. if vFile3DS_UseTextureEx then
  1345. with libMat.Material.TextureEx.Add do
  1346. begin
  1347. Texture.Image.LoadFromFile(string(material.Texture.Map.NameStr));
  1348. Texture.Disabled := False;
  1349. Texture.TextureMode := tmModulate;
  1350. TextureIndex := 0;
  1351. with material.Texture.Map do
  1352. begin
  1353. TextureScale.SetPoint(UScale, VScale, 0);
  1354. TextureOffset.SetPoint((1 - frac(UOffset)) *
  1355. UScale, (frac(VOffset)) * VScale, 0);
  1356. end;
  1357. end
  1358. else
  1359. with libMat.Material.Texture do
  1360. begin
  1361. Image.LoadFromFile(string(material.Texture.Map.NameStr));
  1362. Disabled := False;
  1363. TextureMode := tmModulate;
  1364. end
  1365. except
  1366. on E: ETexture do
  1367. begin
  1368. if not Owner.IgnoreMissingTextures then
  1369. raise EGLFile3DS.CreateFmt(str3DSMapNotFound,['diffuse', e.Message, matLib.TexturePaths]);
  1370. end
  1371. else
  1372. raise;
  1373. end;
  1374. if Trim(string(material.Opacity.Map.NameStr)) <> '' then
  1375. try
  1376. if vFile3DS_UseTextureEx then
  1377. with libMat.Material.TextureEx.Add do
  1378. begin
  1379. libMat.Material.BlendingMode := bmTransparency;
  1380. Texture.ImageAlpha := tiaAlphaFromIntensity;
  1381. Texture.TextureMode := tmModulate;
  1382. Texture.Image.LoadFromFile(string(material.Opacity.Map.NameStr));
  1383. Texture.Disabled := False;
  1384. TextureIndex := 1;
  1385. with material.Opacity.Map do
  1386. begin
  1387. TextureScale.SetPoint(UScale, VScale, 0);
  1388. TextureOffset.SetPoint((1 - frac(UOffset)) *
  1389. UScale, (frac(VOffset)) * VScale, 0);
  1390. end;
  1391. end
  1392. else
  1393. with libMat.Material.Texture do
  1394. begin
  1395. SecondMaterial := matLib.Materials.Add;
  1396. SecondMaterial.Material.Texture.Image.LoadFromFile(string(
  1397. material.Opacity.Map.NameStr));
  1398. SecondMaterial.Material.Texture.Disabled := False;
  1399. SecondMaterial.Material.Texture.ImageAlpha := tiaAlphaFromIntensity;
  1400. SecondMaterial.Material.Texture.TextureMode := tmModulate;
  1401. SecondMaterial.Name := string(material.Opacity.Map.NameStr);
  1402. LibMat.Texture2Name := SecondMaterial.Name;
  1403. Disabled := False;
  1404. end;
  1405. except
  1406. on E: ETexture do
  1407. begin
  1408. if not Owner.IgnoreMissingTextures then
  1409. raise EGLFile3DS.CreateFmt(str3DSMapNotFound,['opacity', e.Message, matLib.TexturePaths]);
  1410. end
  1411. else
  1412. raise;
  1413. end;
  1414. if Trim(string(material.Bump.Map.NameStr)) <> '' then
  1415. try
  1416. if vFile3DS_UseTextureEx then
  1417. with libMat.Material.TextureEx.Add do
  1418. begin
  1419. Texture.Image.LoadFromFile(string(material.Bump.Map.NameStr));
  1420. Texture.Disabled := False;
  1421. Texture.TextureMode := tmModulate;
  1422. // You need a hight map for this parameter (like in 3d Max).
  1423. // Texture.TextureFormat := tfNormalMap;
  1424. TextureIndex := 2;
  1425. with material.Bump.Map do
  1426. begin
  1427. TextureScale.SetPoint(UScale, VScale, 0);
  1428. TextureOffset.SetPoint((1 - frac(UOffset)) *
  1429. UScale, (frac(VOffset)) * VScale, 0);
  1430. end;
  1431. end
  1432. else
  1433. with libMat.Material.Texture do
  1434. begin
  1435. SecondMaterial := matLib.Materials.Add;
  1436. SecondMaterial.Material.Texture.Image.LoadFromFile(string(
  1437. material.Bump.Map.NameStr));
  1438. SecondMaterial.Material.Texture.Disabled := False;
  1439. SecondMaterial.Material.Texture.ImageAlpha := tiaAlphaFromIntensity;
  1440. SecondMaterial.Material.Texture.TextureMode := tmModulate;
  1441. SecondMaterial.Name := string(material.Opacity.Map.NameStr);
  1442. Disabled := False;
  1443. end;
  1444. except
  1445. on E: ETexture do
  1446. begin
  1447. if not Owner.IgnoreMissingTextures then
  1448. raise EGLFile3DS.CreateFmt(str3DSMapNotFound,['bump', e.Message, matLib.TexturePaths]);
  1449. end
  1450. else
  1451. raise;
  1452. end;
  1453. end;
  1454. end
  1455. else
  1456. Result := '';
  1457. end
  1458. else
  1459. Result := '';
  1460. end;
  1461. function GetOrAllocateLightMap(materials: TMaterialList; const Name: string): integer;
  1462. var
  1463. material: PMaterial3DS;
  1464. matLib: TgxMaterialLibrary;
  1465. libMat: TgxLibMaterial;
  1466. begin
  1467. Result := -1;
  1468. material := Materials.MaterialByName[Name];
  1469. Assert(Assigned(material));
  1470. if GetOwner is TgxBaseMesh then
  1471. begin
  1472. matLib := TgxBaseMesh(GetOwner).LightmapLibrary;
  1473. if Assigned(matLib) then
  1474. begin
  1475. if Trim(string(material.IllumMap.Map.NameStr)) <> '' then
  1476. begin
  1477. libMat := matLib.Materials.GetLibMaterialByName(string(
  1478. material.IllumMap.Map.NameStr));
  1479. if not Assigned(libMat) then
  1480. begin
  1481. libMat := matLib.Materials.Add;
  1482. libMat.Name := string(material.IllumMap.Map.NameStr);
  1483. try
  1484. with libMat.Material.Texture do
  1485. begin
  1486. Image.LoadFromFile(string(material.IllumMap.Map.NameStr));
  1487. Disabled := False;
  1488. TextureMode := tmModulate;
  1489. end;
  1490. except
  1491. on E: ETexture do
  1492. begin
  1493. if not Owner.IgnoreMissingTextures then
  1494. raise EGLFile3DS.CreateFmt(str3DSMapNotFound,['light', e.Message, matLib.TexturePaths]);
  1495. end
  1496. else
  1497. raise;
  1498. end;
  1499. end;
  1500. Result := libmat.Index;
  1501. hasLightMap := True;
  1502. end;
  1503. end;
  1504. end;
  1505. end;
  1506. //----------------------------------------------------------------------
  1507. function InvertMeshMatrix(Objects: TObjectList; const Name: string): TMatrix4f;
  1508. // constructs a 4x4 matrix from 3x4 local mesh matrix given by Name and
  1509. // inverts it so it can be used for the keyframer stuff
  1510. var
  1511. I, Index: integer;
  1512. boolY: boolean;
  1513. m: TMatrix4f;
  1514. v4: TVector4f;
  1515. factor: single;
  1516. begin
  1517. with Objects do
  1518. begin
  1519. Index := -1;
  1520. for I := 0 to MeshCount - 1 do
  1521. if CompareText(string(Mesh[I].NameStr), Name) = 0 then
  1522. begin
  1523. Index := I;
  1524. Break;
  1525. end;
  1526. if Index > -1 then
  1527. begin
  1528. with Mesh[Index]^ do
  1529. begin
  1530. Result.X.X := LocMatrix[0];
  1531. Result.X.Y := LocMatrix[1];
  1532. Result.X.Z := LocMatrix[2];
  1533. Result.X.W := 0;
  1534. Result.Y.X := LocMatrix[3];
  1535. Result.Y.Y := LocMatrix[4];
  1536. Result.Y.Z := LocMatrix[5];
  1537. Result.Y.W := 0;
  1538. Result.Z.X := LocMatrix[6];
  1539. Result.Z.Y := LocMatrix[7];
  1540. Result.Z.Z := LocMatrix[8];
  1541. Result.Z.W := 0;
  1542. Result.W.X := LocMatrix[9];
  1543. Result.W.Y := LocMatrix[10];
  1544. Result.W.Z := LocMatrix[11];
  1545. Result.W.W := 1;
  1546. end;
  1547. InvertMatrix(Result);
  1548. // If the matrix is not normalized, ie the third column is not equal to the vector product of the first two columns,
  1549. // it means that it is necessary to turn to-pi around the axis Y.
  1550. m := Result;
  1551. v4 := m.W;
  1552. factor := VectorLength(m.X);
  1553. NormalizeMatrix(m);
  1554. ScaleMatrix(m, factor);
  1555. m.W := v4;
  1556. v4 := VectorAbs(VectorSubtract(Result.Z, m.Z));
  1557. boolY := (v4.X > abs(Result.Z.X)) and
  1558. (v4.Y > abs(Result.Z.Y)) and
  1559. (v4.Z > abs(Result.Z.Z));
  1560. if boolY then
  1561. Result := MatrixMultiply(Result, CreateRotationMatrix(AffineVectorMake(0, 1, 0), -pi));
  1562. end
  1563. else
  1564. Result := IdentityHmgMatrix;
  1565. end;
  1566. end;
  1567. //----------------------------------------------------------------------
  1568. {$IFDEF USE_NO_ASM}
  1569. function IsVertexMarked(P: PByteArray; Index: word): boolean; inline;
  1570. // tests the Index-th bit, returns True if set else False
  1571. var
  1572. mi: word;
  1573. begin
  1574. DivMod(index, 8, mi, index);
  1575. Result := (((p^[mi] shr Index) and 1) = 1);
  1576. end;
  1577. {$ELSE}
  1578. function IsVertexMarked(P: Pointer; Index: integer): boolean; assembler;
  1579. // tests the Index-th bit, returns True if set else False
  1580. asm
  1581. BT [EAX], EDX
  1582. SETC AL
  1583. end;
  1584. {$ENDIF}
  1585. //---------------------------------------------------------------------------
  1586. {$IFDEF USE_NO_ASM}
  1587. function MarkVertex(P: PByteArray; Index: word): boolean; inline;
  1588. // sets the Index-th bit and return True if it was already set else False
  1589. var
  1590. mi: word;
  1591. begin
  1592. DivMod(index, 8, mi, index);
  1593. Result := (((p^[mi] shr Index) and 1) = 1);
  1594. if not (Result) then
  1595. p^[mi] := p^[mi] or (1 shl index);
  1596. end;
  1597. {$ELSE}
  1598. function MarkVertex(P: Pointer; Index: integer): boolean; assembler;
  1599. // sets the Index-th bit and return True if it was already set else False
  1600. asm
  1601. BTS [EAX], EDX
  1602. SETC AL
  1603. end;
  1604. {$ENDIF}
  1605. //---------------------------------------------------------------------------
  1606. // Stores new vertex index (NewIndex) into the smooth index array of vertex ThisIndex
  1607. // using field SmoothingGroup, which must not be 0.
  1608. // For each vertex in the vertex array (also for duplicated vertices) an array of 32 cardinals
  1609. // is maintained (each for one possible smoothing group. If a vertex must be duplicated because
  1610. // it has no smoothing group or a different one then the index of the newly created vertex is
  1611. // stored in the SmoothIndices to avoid loosing the conjunction between not yet processed vertices
  1612. // and duplicated vertices.
  1613. // Note: Only one smoothing must be assigned per vertex. Some available models break this rule and
  1614. // have more than one group assigned to a face. To make the code fail safe the group ID
  1615. // is scanned for the lowest bit set.
  1616. {$IFDEF USE_ASM}
  1617. procedure StoreSmoothIndex(ThisIndex, SmoothingGroup, NewIndex: cardinal; P: Pointer);
  1618. asm
  1619. PUSH EBX
  1620. BSF EBX, EDX
  1621. // determine smoothing group index (convert flag into an index)
  1622. MOV EDX, [P] // get address of index array
  1623. SHL EAX, 7 // ThisIndex * SizeOf(TSmoothIndexEntry)
  1624. ADD EAX, EDX
  1625. LEA EDX, [4 * EBX + EAX]
  1626. // Address of array + vertex index + smoothing group index
  1627. MOV [EDX], ECX
  1628. POP EBX
  1629. end;
  1630. {$ELSE}
  1631. procedure StoreSmoothIndex(ThisIndex, SmoothingGroup, NewIndex: cardinal;
  1632. P: PSmoothIndexArray);
  1633. var
  1634. i: word;
  1635. begin
  1636. i := 0;
  1637. while SmoothingGroup and (1 shl i) = 0 do
  1638. Inc(i);
  1639. p^[ThisIndex, i] := NewIndex;
  1640. end;
  1641. {$ENDIF}
  1642. //---------------------------------------------------------------------------
  1643. {$IFDEF USE_ASM}
  1644. function GetSmoothIndex(ThisIndex, SmoothingGroup: cardinal; P: Pointer): integer;
  1645. // Retrieves the vertex index for the given index and smoothing group.
  1646. // This redirection is necessary because a vertex might have been duplicated.
  1647. asm
  1648. PUSH EBX
  1649. BSF EBX, EDX // determine smoothing group index
  1650. SHL EAX, 7 // ThisIndex * SizeOf(TSmoothIndexEntry)
  1651. ADD EAX, ECX
  1652. LEA ECX, [4 * EBX + EAX]
  1653. // Address of array + vertex index + smoothing group index
  1654. MOV EAX, [ECX]
  1655. POP EBX
  1656. end;
  1657. {$ELSE}
  1658. function GetSmoothIndex(ThisIndex, SmoothingGroup: cardinal;
  1659. P: PSmoothIndexArray): integer; inline;
  1660. // Retrieves the vertex index for the given index and smoothing group.
  1661. // This redirection is necessary because a vertex might have been duplicated.
  1662. var
  1663. i: word;
  1664. begin
  1665. i := 0;
  1666. while SmoothingGroup and (1 shl i) = 0 do
  1667. Inc(i);
  1668. Result := integer(p^[ThisIndex, i]);
  1669. end;
  1670. {$ENDIF}
  1671. //---------------------------------------------------------------------------
  1672. procedure DuplicateVertex(Index: integer);
  1673. // extends the vector and normal array by one entry and duplicates the vertex AData given by Index
  1674. // the marker and texture arrays will be extended too, if necessary
  1675. begin
  1676. // enhance vertex array
  1677. with mesh.Vertices do
  1678. Add(Items[index]);
  1679. mesh.Normals.Add(NullVector);
  1680. // enhance smooth index array
  1681. ReallocMem(SmoothIndices, (CurrentVertexCount + 1) * SizeOf(TSmoothIndexEntry));
  1682. FillChar(SmoothIndices[CurrentVertexCount], SizeOf(TSmoothIndexEntry), $FF);
  1683. // enhance marker array
  1684. if (CurrentVertexCount div 8) <> ((CurrentVertexCount + 1) div 8) then
  1685. begin
  1686. ReallocMem(Marker, ((CurrentVertexCount + 1) div 8) + 1);
  1687. Marker[(CurrentVertexCount div 8) + 1] := 0;
  1688. end;
  1689. with mesh.TexCoords do
  1690. if Count > 0 then
  1691. Add(Items[index]);
  1692. Inc(CurrentVertexCount);
  1693. end;
  1694. //---------------------------------------------------------------------------
  1695. function FindMotionIndex(KeyFramer: TKeyFramer; const ObjectName: AnsiString): integer;
  1696. // Looks through the motion list for the object "ObjectName" and returns its index
  1697. // or -1 if the name is not it the list
  1698. var
  1699. I: integer;
  1700. begin
  1701. Result := -1;
  1702. with KeyFramer do
  1703. for I := 0 to MeshMotionCount - 1 do
  1704. if CompareText(string(MeshMotion[I].NameStr), string(ObjectName)) = 0 then
  1705. begin
  1706. Result := I;
  1707. Break;
  1708. end;
  1709. end;
  1710. var
  1711. CurrentMotionIndex, iMaterial, i, j, x: integer;
  1712. aFaceGroup: TgxFGVertexIndexList;
  1713. Face, Vertex, TargetVertex: integer;
  1714. SmoothingGroup: cardinal;
  1715. CurrentIndex: word;
  1716. Vector1, Vector2, Normal: TAffineVector;
  1717. standardNormalsOrientation: boolean;
  1718. lights_mesh: TgxFile3DSOmniLightObject;
  1719. camera_mesh: TgxFile3DSCameraObject;
  1720. basemesh: TgxBaseMesh;
  1721. begin
  1722. with TFile3DS.Create do
  1723. try
  1724. LoadFromStream(aStream);
  1725. // determine front face winding
  1726. { TODO : better face winding }
  1727. standardNormalsOrientation := not (NormalsOrientation = mnoDefault);
  1728. for i := 0 to Objects.MeshCount - 1 do
  1729. with PMesh3DS(Objects.Mesh[I])^ do
  1730. begin
  1731. hasLightMap := False;
  1732. mesh := TgxFile3DSMeshObject.CreateOwned(Owner.MeshObjects);
  1733. mesh.Name := string(PMesh3DS(Objects.Mesh[I])^.NameStr);
  1734. //dummy targets
  1735. for x := KeyFramer.Settings.Seg.SegBegin to KeyFramer.Settings.Seg.SegEnd do
  1736. TgxMeshMorphTarget.CreateOwned(mesh.MorphTargets);
  1737. with mesh do
  1738. begin
  1739. Mode := momFaceGroups;
  1740. // make a copy of the vertex data, this must always be available
  1741. Vertices.Capacity := NVertices;
  1742. Normals.AddNulls(NVertices);
  1743. if NTextVerts > 0 then
  1744. begin
  1745. TexCoords.Capacity := NVertices;
  1746. for j := 0 to NVertices - 1 do
  1747. begin
  1748. Vertices.Add(PAffineVector(@VertexArray[j])^);
  1749. TexCoords.Add(PTexPoint(@TextArray[j])^);
  1750. end;
  1751. end
  1752. else
  1753. begin
  1754. for j := 0 to NVertices - 1 do
  1755. Vertices.Add(PAffineVector(@VertexArray[j])^);
  1756. end;
  1757. end;
  1758. // allocate memory for the smoothindices and the marker array
  1759. CurrentVertexCount := NVertices;
  1760. Marker := AllocMem((NVertices div 8) + 1); // one bit for each vertex
  1761. GetMem(SmoothIndices, NVertices * SizeOf(TSmoothIndexEntry));
  1762. if SmoothArray = nil then
  1763. begin
  1764. // no smoothing groups to consider
  1765. for face := 0 to NFaces - 1 do
  1766. with FaceArray^[Face] do
  1767. begin
  1768. // normal vector for the face
  1769. with mesh.Vertices do
  1770. begin
  1771. VectorSubtract(Items[V1], Items[V2], vector1);
  1772. VectorSubtract(Items[V3], Items[V2], vector2);
  1773. end;
  1774. if standardNormalsOrientation then
  1775. Normal := VectorCrossProduct(Vector1, Vector2)
  1776. else
  1777. Normal := VectorCrossProduct(Vector2, Vector1);
  1778. // go for each vertex in the current face
  1779. for Vertex := 0 to 2 do
  1780. begin
  1781. // copy current index for faster access
  1782. CurrentIndex := FaceRec[Vertex];
  1783. // already been touched?
  1784. if IsVertexMarked(Marker, CurrentIndex) and (CurrentVertexCount < High(FaceRec[Vertex])) then
  1785. begin
  1786. // already touched vertex must be duplicated
  1787. DuplicateVertex(CurrentIndex);
  1788. FaceRec[Vertex] := CurrentVertexCount - 1;
  1789. mesh.Normals[CurrentVertexCount - 1] := Normal;
  1790. end
  1791. else
  1792. begin
  1793. // not yet touched, so just store the normal
  1794. mesh.Normals[CurrentIndex] := Normal;
  1795. MarkVertex(Marker, CurrentIndex);
  1796. end;
  1797. end;
  1798. end;
  1799. end
  1800. else
  1801. begin
  1802. // smoothing groups are to be considered
  1803. for Face := 0 to NFaces - 1 do
  1804. with FaceArray^[Face] do
  1805. begin
  1806. // normal vector for the face
  1807. with mesh.Vertices do
  1808. begin
  1809. VectorSubtract(Items[V1], Items[V2], vector1);
  1810. VectorSubtract(Items[V3], Items[V2], vector2);
  1811. end;
  1812. if standardNormalsOrientation then
  1813. Normal := VectorCrossProduct(Vector1, Vector2)
  1814. else
  1815. Normal := VectorCrossProduct(Vector2, Vector1);
  1816. SmoothingGroup := SmoothArray^[Face];
  1817. // go for each vertex in the current face
  1818. for Vertex := 0 to 2 do
  1819. begin
  1820. // copy current index for faster access
  1821. currentIndex := FaceRec[Vertex];
  1822. // Has vertex already been touched?
  1823. if IsVertexMarked(Marker, currentIndex) then
  1824. begin
  1825. // check smoothing group
  1826. if (SmoothingGroup = 0) then
  1827. begin
  1828. if (CurrentVertexCount < High(FaceRec[Vertex])) then
  1829. begin
  1830. // no smoothing then just duplicate vertex
  1831. DuplicateVertex(CurrentIndex);
  1832. FaceRec[Vertex] := CurrentVertexCount - 1;
  1833. mesh.Normals[CurrentVertexCount - 1] := Normal;
  1834. // mark new vertex also as touched
  1835. MarkVertex(Marker, CurrentVertexCount - 1);
  1836. end;
  1837. end
  1838. else
  1839. begin
  1840. // this vertex must be smoothed, check if there's already
  1841. // a (duplicated) vertex for this smoothing group
  1842. TargetVertex := GetSmoothIndex(CurrentIndex, SmoothingGroup, SmoothIndices);
  1843. if (TargetVertex < 0) then
  1844. begin
  1845. if (CurrentVertexCount < High(FaceRec[Vertex])) then
  1846. begin
  1847. // vertex has not yet been duplicated for this smoothing
  1848. // group, so do it now
  1849. DuplicateVertex(CurrentIndex);
  1850. FaceRec[Vertex] := CurrentVertexCount - 1;
  1851. mesh.Normals[CurrentVertexCount - 1] := Normal;
  1852. StoreSmoothIndex(CurrentIndex, SmoothingGroup,
  1853. CurrentVertexCount - 1, SmoothIndices);
  1854. StoreSmoothIndex(CurrentVertexCount - 1,
  1855. SmoothingGroup, CurrentVertexCount - 1, SmoothIndices);
  1856. // mark new vertex also as touched
  1857. MarkVertex(Marker, CurrentVertexCount - 1);
  1858. end;
  1859. end
  1860. else
  1861. begin
  1862. // vertex has already been duplicated,
  1863. // so just add normal vector to other vertex...
  1864. mesh.Normals[TargetVertex] :=
  1865. VectorAdd(mesh.Normals[TargetVertex], Normal);
  1866. // ...and tell which new vertex has to be used from now on
  1867. FaceRec[Vertex] := TargetVertex;
  1868. end;
  1869. end;
  1870. end
  1871. else
  1872. begin
  1873. // vertex not yet touched, so just store the normal
  1874. mesh.Normals[CurrentIndex] := Normal;
  1875. // initialize smooth indices for this vertex
  1876. FillChar(SmoothIndices[CurrentIndex],
  1877. SizeOf(TSmoothIndexEntry), $FF);
  1878. if SmoothingGroup <> 0 then
  1879. StoreSmoothIndex(CurrentIndex, SmoothingGroup,
  1880. CurrentIndex, SmoothIndices);
  1881. MarkVertex(Marker, CurrentIndex);
  1882. end;
  1883. end;
  1884. end;
  1885. end;
  1886. FreeMem(Marker);
  1887. FreeMem(SmoothIndices);
  1888. Assert(mesh.Vertices.Count = CurrentVertexCount);
  1889. // and normalize the Normals array
  1890. mesh.Normals.Normalize;
  1891. // now go for each material group
  1892. // if there's no face to material assignment then just copy the
  1893. // face definitions and rely on the default texture of the scene object
  1894. if (NMats = 0) or (not vVectorFileObjectsAllocateMaterials) then
  1895. begin
  1896. aFaceGroup := TgxFGVertexIndexList.CreateOwned(mesh.FaceGroups);
  1897. with aFaceGroup do
  1898. begin
  1899. basemesh := TgxBaseMesh(Self.GetOwner);
  1900. if basemesh.MaterialLibrary <> nil then
  1901. MaterialName := basemesh.MaterialLibrary.Materials.Add.Name;
  1902. // copy the face list
  1903. for j := 0 to NFaces - 1 do
  1904. begin
  1905. Add(FaceArray[J].V1);
  1906. Add(FaceArray[J].V2);
  1907. Add(FaceArray[J].V3);
  1908. end;
  1909. end;
  1910. end
  1911. else
  1912. begin
  1913. for iMaterial := 0 to NMats - 1 do
  1914. begin
  1915. aFaceGroup := TgxFGVertexIndexList.CreateOwned(mesh.FaceGroups);
  1916. with aFaceGroup do
  1917. begin
  1918. MaterialName :=
  1919. GetOrAllocateMaterial(Materials, string(MatArray[iMaterial].NameStr));
  1920. LightMapIndex :=
  1921. GetOrAllocateLightMap(Materials, string(MatArray[iMaterial].NameStr));
  1922. // copy all vertices belonging to the current face into our index array,
  1923. // there won't be redundant vertices since this would mean a face has more than one
  1924. // material
  1925. // NFaces is the one from FaceGroup
  1926. with MatArray[iMaterial] do
  1927. for j := 0 to NFaces - 1 do
  1928. begin
  1929. Add(FaceArray[FaceIndex[J]].V1);
  1930. Add(FaceArray[FaceIndex[J]].V2);
  1931. Add(FaceArray[FaceIndex[J]].V3);
  1932. end;
  1933. end;
  1934. end;
  1935. end;
  1936. if hasLightMap then
  1937. for j := 0 to mesh.TexCoords.Count - 1 do
  1938. mesh.LightMapTexCoords.Add(mesh.TexCoords[j].X, mesh.TexCoords[j].Y);
  1939. end;
  1940. // Adding non-mesh objects (for example, dummies).
  1941. for I := 0 to KeyFramer.MeshMotionCount - 1 do
  1942. if (Owner.MeshObjects.FindMeshByName(string(
  1943. KeyFramer.MeshMotion[I].NameStr)) = nil) then
  1944. begin
  1945. mesh := TgxFile3DSMeshObject.CreateOwned(Owner.MeshObjects);
  1946. mesh.Name := string(KeyFramer.MeshMotion[I].NameStr);
  1947. //dummy targets
  1948. for x := KeyFramer.Settings.Seg.SegBegin to KeyFramer.Settings.Seg.SegEnd do
  1949. TgxMeshMorphTarget.CreateOwned(mesh.MorphTargets);
  1950. mesh.LoadAnimation(KeyFramer.MeshMotion[I]);
  1951. end;
  1952. for I := 0 to Objects.MeshCount - 1 do
  1953. with PMesh3DS(Objects.Mesh[I])^ do
  1954. begin
  1955. mesh := Owner.MeshObjects.FindMeshByName(string(NameStr)) as TgxFile3DSMeshObject;
  1956. with mesh, KeyFramer do
  1957. begin
  1958. CurrentMotionIndex := FindMotionIndex(KeyFramer, NameStr);
  1959. FRefTranf.ModelMatrix := InvertMeshMatrix(Objects, string(NameStr));
  1960. if MeshMotionCount > 0 then
  1961. LoadAnimation(MeshMotion[CurrentMotionIndex]);
  1962. end;
  1963. end;
  1964. // Lights Omni.
  1965. for I := 0 to Objects.OmniLightCount - 1 do
  1966. begin
  1967. lights_mesh := TgxFile3DSOmniLightObject.CreateOwned(Owner.MeshObjects);
  1968. // Dummy targets for it.
  1969. for x := KeyFramer.Settings.Seg.SegBegin to KeyFramer.Settings.Seg.SegEnd do
  1970. TgxMeshMorphTarget.CreateOwned(lights_mesh.MorphTargets);
  1971. lights_mesh.LoadData(Owner, Objects.OmniLight[I]);
  1972. lights_mesh.LoadAnimation(KeyFramer.OmniLightMotion[I]);
  1973. end;
  1974. // Lights Spot.
  1975. for I := 0 to Objects.SpotLightCount - 1 do
  1976. begin
  1977. lights_mesh := TgxFile3DSSpotLightObject.CreateOwned(Owner.MeshObjects);
  1978. // Dummy targets for it.
  1979. for x := KeyFramer.Settings.Seg.SegBegin to KeyFramer.Settings.Seg.SegEnd do
  1980. TgxMeshMorphTarget.CreateOwned(lights_mesh.MorphTargets);
  1981. lights_mesh.LoadData(Owner, Objects.SpotLight[I]);
  1982. lights_mesh.LoadAnimation(KeyFramer.SpotLightMotion[I]);
  1983. end;
  1984. // Camera Objects.
  1985. for I := 0 to Objects.CameraCount - 1 do
  1986. begin
  1987. camera_mesh := TgxFile3DSCameraObject.CreateOwned(Owner.MeshObjects);
  1988. // Dummy targets for it.
  1989. for x := KeyFramer.Settings.Seg.SegBegin to KeyFramer.Settings.Seg.SegEnd do
  1990. TgxMeshMorphTarget.CreateOwned(camera_mesh.MorphTargets);
  1991. camera_mesh.LoadData(Owner, Objects.Camera[I]);
  1992. camera_mesh.LoadAnimation(KeyFramer.CameraMotion[I]);
  1993. end;
  1994. // Apply animation matrix to static data
  1995. if vFile3DS_LoadedStaticFrame >= 0 then
  1996. begin
  1997. for i := 0 to Owner.MeshObjects.Count - 1 do
  1998. begin
  1999. if Owner.MeshObjects[i] is TgxFile3DSMeshObject then
  2000. begin
  2001. mesh := Owner.MeshObjects[i] as TgxFile3DSMeshObject;
  2002. mesh.FStatic := True;
  2003. for j := 0 to mesh.Vertices.Count - 1 do
  2004. mesh.Vertices[j] := VectorTransform(mesh.Vertices[j], mesh.FAnimTransf.ModelMatrix);
  2005. end;
  2006. end;
  2007. end;
  2008. finally
  2009. Free;
  2010. end;
  2011. end;
  2012. // ------------------------------------------------------------------
  2013. initialization
  2014. // ------------------------------------------------------------------
  2015. RegisterClasses([TgxFile3DSDummyObject, TgxFile3DSMeshObject,
  2016. TgxFile3DSOmniLightObject, TgxFile3DSSpotLightObject,
  2017. TgxFile3DSCameraObject]);
  2018. RegisterVectorFileFormat('3ds', '3D Studio files', Tgx3DSVectorFile);
  2019. RegisterVectorFileFormat('prj', '3D Studio project files', Tgx3DSVectorFile);
  2020. end.