GLS.FileLMTS.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.FileLMTS;
  5. (* File loader for MTS *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. Vcl.Graphics,
  12. GLS.VectorTypes,
  13. GLS.VectorFileObjects,
  14. GLS.ApplicationFileIO,
  15. GLS.VectorLists,
  16. GLS.VectorGeometry,
  17. GLS.Texture,
  18. GLS.PersistentClasses,
  19. GLS.Graphics,
  20. GLS.Material;
  21. const
  22. C_LMTS_ID = $53544D4C;
  23. C_LMTS_VER = 4;
  24. C_LMTS_SUBS = $53425553;
  25. C_LMTS_TEXT = $54584554;
  26. C_LMTS_TRIS = $53495254;
  27. C_LMTS_TEXFNLEN = 255; // max texture filename length
  28. type
  29. PLMTS_Header = ^TLMTS_Header;
  30. TLMTS_Header = record // packed
  31. ID: cardinal;
  32. Ver: cardinal;
  33. headerSize: cardinal;
  34. nTexts: word; // # of textures
  35. nSubsets: word;
  36. nTris: cardinal;
  37. subSize: word;
  38. vtxSize: word;
  39. end;
  40. PLMTS_TexData = ^TLMTS_TexData;
  41. TLMTS_TexData = record // packed
  42. fName: array [0 .. C_LMTS_TEXFNLEN] of AnsiChar;
  43. Flags: Word;
  44. end;
  45. PLMTS_Subset = ^TLMTS_Subset;
  46. TLMTS_Subset = record // packed
  47. Offset: LongInt;
  48. Count: LongInt;
  49. TextID1: Word;
  50. TextID2: Word;
  51. end;
  52. PLMTS_Vertex = ^TLMTS_Vertex;
  53. TLMTS_Vertex = record // packed
  54. x, y, z: Single;
  55. u1, v1, u2, v2: Single;
  56. end;
  57. PLMTS = ^TLMTS;
  58. TLMTS = record
  59. header: TLMTS_Header;
  60. usrData: pointer;
  61. usrSize: cardinal;
  62. texData: pointer;
  63. subsets: pointer;
  64. tris: pointer;
  65. ok: boolean;
  66. end;
  67. TMaterialInfo = record
  68. FShininess, BShininess: TGLShininess;
  69. FAmbient, FDiffuse, FEmission, FSpecular, BAmbient, BDiffuse, BEmission,
  70. BSpecular: TGLVector;
  71. ImageAlpha: TGLTextureImageAlpha;
  72. magFilter: TGLMagFilter;
  73. minFilter: TGLMinFilter;
  74. TextureMode: TGLTextureMode;
  75. TextureWrap: TGLTextureWrap;
  76. Blendingmode: TGLBlendingMode;
  77. FaceCulling: TGLFaceCulling;
  78. mathash: integer;
  79. end;
  80. TGLLMTSVectorFile = class(TGLVectorFile)
  81. public
  82. class function Capabilities: TGLDataFileCapabilities; override;
  83. procedure LoadFromStream(aStream: TStream); override;
  84. procedure SaveToStream(aStream: TStream); override;
  85. end;
  86. //---------------------------------------------------
  87. implementation
  88. //---------------------------------------------------
  89. uses
  90. GLS.TextureFormat;
  91. // ------------------
  92. // ------------------ TGLLMTSVectorFile ------------------
  93. // ------------------
  94. class function TGLLMTSVectorFile.Capabilities: TGLDataFileCapabilities;
  95. begin
  96. Result := [dfcRead, dfcWrite];
  97. end;
  98. procedure TGLLMTSVectorFile.LoadFromStream(aStream: TStream);
  99. var
  100. MO: TGLMeshObject;
  101. FG: TFGVertexIndexList;
  102. LL: TGLMaterialLibrary;
  103. ML: TGLMaterialLibrary;
  104. LMTS: TLMTS;
  105. T: TLMTS_TexData;
  106. V: array [0 .. 2] of TLMTS_Vertex;
  107. S: TLMTS_Subset;
  108. _4cc: Cardinal;
  109. C: Integer;
  110. fName: string;
  111. vi: TGLIntegerList;
  112. libmat: TGLLibmaterial;
  113. lmnames, matnames: TStringlist;
  114. MatInfoHeader: array [0 .. 3] of AnsiChar;
  115. MatInfoCount: Cardinal;
  116. Matinfo: array of TMaterialInfo;
  117. i, j: Integer;
  118. begin
  119. owner.MeshObjects.Clear;
  120. MO := TGLMeshObject.CreateOwned(owner.MeshObjects);
  121. MO.Mode := momFaceGroups;
  122. vi := TGLIntegerList.create;
  123. LL := owner.LightmapLibrary;
  124. ML := owner.MaterialLibrary;
  125. lmnames := TStringlist.create;
  126. matnames := TStringlist.create;
  127. MatInfoCount := 0;
  128. try
  129. // read header...
  130. aStream.Read(LMTS.header, SizeOf(TLMTS_Header));
  131. // verify...
  132. if (LMTS.header.ID <> C_LMTS_ID) or (LMTS.header.Ver <> C_LMTS_VER) or
  133. (LMTS.header.headerSize < SizeOf(TLMTS_Header)) or
  134. (LMTS.header.subSize < SizeOf(TLMTS_Subset)) or
  135. (LMTS.header.vtxSize < SizeOf(TLMTS_Vertex)) then
  136. raise Exception.create('Error in header');
  137. // read "user" data - actually skip this data...
  138. LMTS.usrSize := LMTS.header.headerSize - SizeOf(TLMTS_Header);
  139. if (LMTS.usrSize > 7) then
  140. begin
  141. aStream.Read(MatInfoHeader, 4);
  142. if MatInfoHeader = 'MATI' then
  143. begin
  144. aStream.Read(MatInfoCount, 4);
  145. if MatInfoCount > 0 then
  146. begin
  147. setlength(Matinfo, MatInfoCount);
  148. for i := 0 to MatInfoCount - 1 do
  149. begin
  150. aStream.Read(Matinfo[i], SizeOf(Matinfo[i]));
  151. end;
  152. end;
  153. if LMTS.usrSize > ((MatInfoCount * SizeOf(TMaterialInfo)) + 8) then
  154. begin
  155. LMTS.usrSize := LMTS.usrSize -
  156. ((MatInfoCount * SizeOf(TMaterialInfo)) + 8);
  157. aStream.Seek(LMTS.usrSize, soFromCurrent);
  158. end;
  159. end
  160. else
  161. aStream.Seek(LMTS.usrSize - 4, soFromCurrent);
  162. end
  163. else if (LMTS.usrSize > 0) then
  164. aStream.Seek(LMTS.usrSize, soFromCurrent);
  165. // read texture filenames data...
  166. aStream.Read(_4cc, SizeOf(_4cc));
  167. if (_4cc <> C_LMTS_TEXT) then
  168. raise Exception.create('Texture data not found');
  169. for C := 0 to LMTS.header.nTexts - 1 do
  170. begin
  171. aStream.Read(T, SizeOf(TLMTS_TexData));
  172. if T.Flags = 0 then
  173. begin
  174. if Assigned(ML) and (trim(String(T.fName)) <> '') then
  175. begin
  176. fName := String(T.fName);
  177. try
  178. if lastdelimiter('.', fName) <> length(fName) - 3 then
  179. fName := fName + '.tga'
  180. else
  181. fName := changefileext(fName, '.tga');
  182. if not fileexists(fName) then
  183. begin
  184. fName := changefileext(fName, '.jpg');
  185. if not fileexists(fName) then
  186. begin
  187. fName := changefileext(fName, '.png');
  188. if not fileexists(fName) then
  189. begin
  190. fName := changefileext(fName, '.bmp');
  191. if not fileexists(fName) then
  192. begin
  193. fName := changefileext(fName, '.dds');
  194. if not fileexists(fName) then
  195. begin
  196. fName := String(T.fName);
  197. end;
  198. // fName:=fName+' (missing)';
  199. end;
  200. end;
  201. end;
  202. end;
  203. libmat := ML.Materials.GetLibMaterialByName(fName);
  204. if not Assigned(libmat) then
  205. begin
  206. with ML.AddTextureMaterial(fName, fName) do
  207. Material.Texture.TextureMode := tmModulate;
  208. end;
  209. matnames.add(fName);
  210. except
  211. matnames.add(fName);
  212. { on E: ETexture do
  213. begin
  214. if not Owner.IgnoreMissingTextures then
  215. raise;
  216. end; }
  217. end;
  218. end
  219. else
  220. matnames.add(String(T.fName));
  221. end
  222. else
  223. begin
  224. if Assigned(LL) and (trim(String(T.fName)) <> '') then
  225. begin
  226. fName := String(T.fName);
  227. try
  228. if lastdelimiter('.', fName) <> length(fName) - 3 then
  229. fName := fName + '.tga'
  230. else
  231. fName := changefileext(fName, '.tga');
  232. if not fileexists(fName) then
  233. begin
  234. fName := changefileext(fName, '.jpg');
  235. if not fileexists(fName) then
  236. begin
  237. fName := changefileext(fName, '.png');
  238. if not fileexists(fName) then
  239. begin
  240. fName := changefileext(fName, '.bmp');
  241. if not fileexists(fName) then
  242. begin
  243. fName := changefileext(fName, '.dds');
  244. if not fileexists(fName) then
  245. begin
  246. fName := String(T.fName);
  247. end;
  248. // fName:=fName+' (missing)';
  249. end;
  250. end;
  251. end;
  252. end;
  253. libmat := LL.Materials.GetLibMaterialByName(fName);
  254. if not Assigned(libmat) then
  255. begin
  256. with LL.AddTextureMaterial(fName, fName).Material.Texture do
  257. begin
  258. minFilter := miLinear;
  259. TextureWrap := twNone;
  260. TextureFormat := tfRGB;
  261. TextureMode := tmModulate;
  262. end;
  263. end;
  264. lmnames.add(fName);
  265. except
  266. lmnames.add(fName);
  267. { on E: ETexture do
  268. begin
  269. if not Owner.IgnoreMissingTextures then
  270. raise;
  271. end; }
  272. end;
  273. end
  274. else
  275. lmnames.add(String(T.fName));
  276. end;
  277. end;
  278. if Assigned(owner.MaterialLibrary) then
  279. for i := 0 to MatInfoCount - 1 do
  280. begin
  281. libmat := nil;
  282. for j := 0 to owner.MaterialLibrary.Materials.Count - 1 do
  283. if owner.MaterialLibrary.Materials[j].NameHashKey = Matinfo[i].mathash
  284. then
  285. begin
  286. libmat := owner.MaterialLibrary.Materials[j];
  287. break;
  288. end;
  289. if Assigned(libmat) then
  290. begin
  291. with Matinfo[i] do
  292. begin
  293. libmat.Material.FrontProperties.Shininess := FShininess;
  294. libmat.Material.BackProperties.Shininess := BShininess;
  295. libmat.Material.FrontProperties.Ambient.Color := FAmbient;
  296. libmat.Material.FrontProperties.Diffuse.Color := FDiffuse;
  297. libmat.Material.FrontProperties.Emission.Color := FEmission;
  298. libmat.Material.FrontProperties.Specular.Color := FSpecular;
  299. libmat.Material.BackProperties.Ambient.Color := BAmbient;
  300. libmat.Material.BackProperties.Diffuse.Color := BDiffuse;
  301. libmat.Material.BackProperties.Emission.Color := BEmission;
  302. libmat.Material.BackProperties.Specular.Color := BSpecular;
  303. libmat.Material.Texture.ImageAlpha := ImageAlpha;
  304. libmat.Material.Texture.magFilter := magFilter;
  305. libmat.Material.Texture.minFilter := minFilter;
  306. libmat.Material.Texture.TextureMode := TextureMode;
  307. libmat.Material.Texture.TextureWrap := TextureWrap;
  308. libmat.Material.Blendingmode := Blendingmode;
  309. libmat.Material.FaceCulling := FaceCulling;
  310. end;
  311. end;
  312. end;
  313. // read subset data...
  314. aStream.Read(_4cc, SizeOf(_4cc));
  315. if (_4cc <> C_LMTS_SUBS) then
  316. raise Exception.create('Subset data not found');
  317. for C := LMTS.header.nSubsets - 1 downto 0 do
  318. begin
  319. aStream.Read(S, LMTS.header.subSize);
  320. FG := TFGVertexIndexList.CreateOwned(MO.FaceGroups);
  321. FG.Mode := fgmmTriangles;
  322. FG.vertexindices.AddSerie(S.Offset * 3, 1, S.Count * 3);
  323. vi.AddSerie(S.Offset * 3, 1, S.Count * 3);
  324. if Assigned(ML) and (S.TextID1 <> $FFFF) then
  325. begin
  326. if (S.TextID1 < matnames.Count) then
  327. begin
  328. libmat := ML.Materials.GetLibMaterialByName(matnames[S.TextID1]);
  329. if Assigned(libmat) then
  330. FG.MaterialName := libmat.Name;
  331. end;
  332. end;
  333. if Assigned(LL) and (S.TextID2 <> $FFFF) then
  334. begin
  335. if (S.TextID2 - matnames.Count < lmnames.Count) and
  336. (S.TextID2 - matnames.Count > -1) then
  337. begin
  338. libmat := LL.Materials.GetLibMaterialByName
  339. (lmnames[S.TextID2 - matnames.Count]);
  340. if Assigned(libmat) then
  341. FG.lightmapindex := libmat.Index;
  342. end;
  343. end;
  344. end;
  345. // read vertex data...
  346. aStream.Read(_4cc, SizeOf(_4cc));
  347. if (_4cc <> C_LMTS_TRIS) then
  348. raise Exception.create('Vertex data not found');
  349. for C := 0 to integer(LMTS.header.nTris) - 1 do
  350. begin
  351. aStream.Read(V[0], LMTS.header.vtxSize);
  352. aStream.Read(V[1], LMTS.header.vtxSize);
  353. aStream.Read(V[2], LMTS.header.vtxSize);
  354. MO.Vertices.add(-V[0].x, V[0].y, V[0].z);
  355. MO.TexCoords.add(V[0].u1, -V[0].v1);
  356. MO.LightmapTexCoords.add(V[0].u2, 1 - V[0].v2);
  357. MO.Vertices.add(-V[2].x, V[2].y, V[2].z);
  358. MO.TexCoords.add(V[2].u1, -V[2].v1);
  359. MO.LightmapTexCoords.add(V[2].u2, 1 - V[2].v2);
  360. MO.Vertices.add(-V[1].x, V[1].y, V[1].z);
  361. MO.TexCoords.add(V[1].u1, -V[1].v1);
  362. MO.LightmapTexCoords.add(V[1].u2, 1 - V[1].v2);
  363. end;
  364. MO.BuildNormals(vi, momtriangles);
  365. vi.free;
  366. matnames.free;
  367. lmnames.free;
  368. setlength(Matinfo, 0);
  369. except
  370. matnames.free;
  371. lmnames.free;
  372. MO.free;
  373. end;
  374. end;
  375. procedure TGLLMTSVectorFile.SaveToStream(aStream: TStream);
  376. var
  377. MO: TGLMeshObject;
  378. FG: TFGVertexIndexList;
  379. i, j, k, l, lmstartindex, C, matindex: integer;
  380. h: TLMTS_Header;
  381. V: array [0 .. 2] of TLMTS_Vertex;
  382. texData: array of TLMTS_TexData;
  383. subsets: array of TLMTS_Subset;
  384. tris: array of TLMTS_Vertex;
  385. _4cc: cardinal;
  386. matname: AnsiString;
  387. ss: integer;
  388. Matinfo: array of TMaterialInfo;
  389. MatInfoCount: integer;
  390. libmat: TGLLibmaterial;
  391. begin
  392. setlength(tris, 0);
  393. setlength(subsets, 0);
  394. setlength(texData, 0);
  395. C := 0;
  396. lmstartindex := maxint;
  397. for i := 0 to owner.MeshObjects.Count - 1 do
  398. begin
  399. MO := owner.MeshObjects[i];
  400. for j := 0 to MO.FaceGroups.Count - 1 do
  401. begin
  402. FG := TFGVertexIndexList(MO.FaceGroups[j]);
  403. matname := AnsiString(FG.MaterialName);
  404. // no duplicate textures please
  405. matindex := -1;
  406. for k := 0 to high(texData) do
  407. if texData[k].fName = matname then
  408. begin
  409. matindex := k;
  410. break;
  411. end;
  412. if matindex = -1 then // not a duplicate, so add it
  413. begin
  414. SetLength(texData, length(texData) + 1);
  415. with texData[high(texData)] do
  416. begin
  417. matindex := high(texData);
  418. StrPCopy(@fName, matname);
  419. Flags := 0;
  420. end;
  421. inc(C); // used to offest the lightmap index
  422. end;
  423. // set some of the facegroup (subsets) info here.
  424. setlength(subsets, length(subsets) + 1);
  425. with subsets[high(subsets)] do
  426. begin
  427. if (matname <> '') then
  428. TextID1 := matindex
  429. else
  430. TextID1 := $FFFF;
  431. end;
  432. if (FG.lightmapindex > -1) and (lmstartindex > FG.lightmapindex) then
  433. lmstartindex := FG.lightmapindex; // used to offest the lightmap index
  434. end;
  435. end;
  436. if lmstartindex = maxint then
  437. lmstartindex := 0; // cool, lightmaps start from the first index
  438. ss := 0;
  439. for i := 0 to owner.MeshObjects.Count - 1 do
  440. begin
  441. MO := owner.MeshObjects[i];
  442. for j := 0 to MO.FaceGroups.Count - 1 do
  443. begin
  444. FG := TFGVertexIndexList(MO.FaceGroups[j]);
  445. // subset already created earlier, just finish filling the data.
  446. // we needed the "c" and "lmstartindex" to be able to do this
  447. with subsets[ss] do
  448. begin
  449. Offset := length(tris) div 3;
  450. Count := FG.vertexindices.Count div 3;
  451. if (FG.lightmapindex > -1) and Assigned(owner.LightmapLibrary) then
  452. TextID2 := C + FG.lightmapindex - lmstartindex
  453. else
  454. TextID2 := $FFFF;
  455. end;
  456. // fill the vertex data
  457. k := 0;
  458. while k < FG.vertexindices.Count do
  459. begin
  460. for l := 0 to 2 do
  461. begin
  462. with V[l] do
  463. begin
  464. // vertex
  465. x := -MO.Vertices[FG.vertexindices[k + l]].X;
  466. y := MO.Vertices[FG.vertexindices[k + l]].Y;
  467. z := MO.Vertices[FG.vertexindices[k + l]].Z;
  468. // texcoords
  469. u1 := 0;
  470. v1 := 0;
  471. if FG is TFGVertexNormalTexIndexList then
  472. begin
  473. if MO.TexCoords.Count > TFGVertexNormalTexIndexList(FG)
  474. .texcoordIndices[k + l] then
  475. begin
  476. u1 := MO.TexCoords[TFGVertexNormalTexIndexList(FG)
  477. .texcoordIndices[k + l]].X;
  478. v1 := -MO.TexCoords[TFGVertexNormalTexIndexList(FG)
  479. .texcoordIndices[k + l]].Y;
  480. end;
  481. end
  482. else if FG is TFGIndexTexCoordList then
  483. begin
  484. u1 := TFGIndexTexCoordList(FG).TexCoords[k + l].X;
  485. v1 := -TFGIndexTexCoordList(FG).TexCoords[k + l].Y;
  486. end
  487. else if MO.TexCoords.Count > FG.vertexindices[k + l] then
  488. begin
  489. u1 := MO.TexCoords[FG.vertexindices[k + l]].X;
  490. v1 := -MO.TexCoords[FG.vertexindices[k + l]].Y;
  491. end;
  492. // lightmap texcoords
  493. u2 := 0;
  494. v2 := 0;
  495. if MO.LightmapTexCoords.Count > FG.vertexindices[k + l] then
  496. begin
  497. u2 := MO.LightmapTexCoords[FG.vertexindices[k + l]].X;
  498. v2 := 1 - MO.LightmapTexCoords[FG.vertexindices[k + l]].Y;
  499. end;
  500. end;
  501. end;
  502. setlength(tris, length(tris) + 3);
  503. tris[high(tris) - 2] := V[0];
  504. tris[high(tris) - 1] := V[2];
  505. tris[high(tris)] := V[1];
  506. inc(k, 3);
  507. end;
  508. inc(ss);
  509. end;
  510. end;
  511. setlength(Matinfo, 0);
  512. // store the material properties..
  513. if Assigned(owner.MaterialLibrary) then
  514. begin
  515. for i := 0 to high(texData) do
  516. begin
  517. libmat := owner.MaterialLibrary.Materials.GetLibMaterialByName
  518. (String(texData[i].fName));
  519. if Assigned(libmat) then
  520. begin
  521. setlength(Matinfo, length(Matinfo) + 1);
  522. with Matinfo[high(Matinfo)] do
  523. begin
  524. FShininess := libmat.Material.FrontProperties.Shininess;
  525. BShininess := libmat.Material.BackProperties.Shininess;
  526. FAmbient := libmat.Material.FrontProperties.Ambient.Color;
  527. FDiffuse := libmat.Material.FrontProperties.Diffuse.Color;
  528. FEmission := libmat.Material.FrontProperties.Emission.Color;
  529. FSpecular := libmat.Material.FrontProperties.Specular.Color;
  530. BAmbient := libmat.Material.BackProperties.Ambient.Color;
  531. BDiffuse := libmat.Material.BackProperties.Diffuse.Color;
  532. BEmission := libmat.Material.BackProperties.Emission.Color;
  533. BSpecular := libmat.Material.BackProperties.Specular.Color;
  534. ImageAlpha := libmat.Material.Texture.ImageAlpha;
  535. magFilter := libmat.Material.Texture.magFilter;
  536. minFilter := libmat.Material.Texture.minFilter;
  537. TextureMode := libmat.Material.Texture.TextureMode;
  538. TextureWrap := libmat.Material.Texture.TextureWrap;
  539. Blendingmode := libmat.Material.Blendingmode;
  540. FaceCulling := libmat.Material.FaceCulling;
  541. mathash := libmat.NameHashKey;
  542. end;
  543. end;
  544. end;
  545. end;
  546. // add the lightmap texture names to the texdata list
  547. C := length(texData);
  548. if Assigned(owner.LightmapLibrary) then
  549. for i := 0 to owner.MeshObjects.Count - 1 do
  550. begin
  551. MO := owner.MeshObjects[i];
  552. for j := 0 to MO.FaceGroups.Count - 1 do
  553. begin
  554. FG := TFGVertexIndexList(MO.FaceGroups[j]);
  555. if FG.lightmapindex > -1 then
  556. begin
  557. matname := AnsiString(owner.LightmapLibrary.Materials
  558. [FG.lightmapindex].Name);
  559. // no duplicate textures please
  560. matindex := -1;
  561. for k := C to high(texData) do
  562. if texData[k].fName = matname then
  563. begin
  564. matindex := k;
  565. break;
  566. end;
  567. if matindex = -1 then // not a duplicate, so add it
  568. begin
  569. SetLength(texData, length(texData) + 1);
  570. with texData[high(texData)] do
  571. begin
  572. StrPCopy(pansichar(@fName), matname);
  573. Flags := 1;
  574. end;
  575. end;
  576. end;
  577. end;
  578. end;
  579. // fill and write the file header
  580. with h do
  581. begin
  582. ID := C_LMTS_ID;
  583. Ver := C_LMTS_VER;
  584. headerSize := 24 + 8 + (length(Matinfo) * SizeOf(TMaterialInfo));
  585. nTexts := length(texData);
  586. nSubsets := length(subsets);
  587. nTris := length(tris) div 3;
  588. subSize := SizeOf(TLMTS_Subset);
  589. vtxSize := SizeOf(TLMTS_Vertex);
  590. end;
  591. aStream.Write(h, SizeOf(h));
  592. aStream.Write('MATI', 4);
  593. MatInfoCount := length(Matinfo);
  594. aStream.Write(MatInfoCount, SizeOf(MatInfoCount));
  595. // write the materials info
  596. for i := 0 to high(Matinfo) do
  597. aStream.Write(Matinfo[i], SizeOf(Matinfo[i]));
  598. // write the texture names
  599. _4cc := C_LMTS_TEXT;
  600. aStream.Write(_4cc, SizeOf(_4cc));
  601. for i := 0 to high(texData) do
  602. aStream.Write(texData[i], SizeOf(texData[i]));
  603. // fagegroups
  604. _4cc := C_LMTS_SUBS;
  605. aStream.Write(_4cc, SizeOf(_4cc));
  606. for i := 0 to high(subsets) do
  607. aStream.Write(subsets[i], SizeOf(subsets[i]));
  608. // vertex data
  609. _4cc := C_LMTS_TRIS;
  610. aStream.Write(_4cc, SizeOf(_4cc));
  611. for i := 0 to high(tris) do
  612. aStream.Write(tris[i], SizeOf(tris[i]));
  613. // free up used memory
  614. setlength(tris, 0);
  615. setlength(subsets, 0);
  616. setlength(texData, 0);
  617. setlength(Matinfo, 0);
  618. end;
  619. //-----------------------------------------------
  620. initialization
  621. //-----------------------------------------------
  622. RegisterVectorFileFormat('lmts', 'Pulsar Studio LMTS File Format',
  623. TGLLMTSVectorFile);
  624. end.