GLS.File3DS.pas 70 KB

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