FileB3D.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. {
  5. File streaming class for the B3D loader
  6. }
  7. unit FileB3D;
  8. interface
  9. {$I GLScene.inc}
  10. {$R-}
  11. uses
  12. System.Classes,
  13. System.SysUtils,
  14. GLVectorGeometry,
  15. GLVectorTypes,
  16. GLVectorLists;
  17. type
  18. TB3DChunkType = (bctUnknown, bctHeader, bctTexture, bctBrush, bctNode, bctVertex, bctTriangle,
  19. bctMesh, bctBone, bctKeyFrame, bctAnimation);
  20. PB3DChunk = ^TB3DChunk;
  21. TB3DChunk = record
  22. chunk: array[0..3] of char;
  23. length: Integer;
  24. end;
  25. PBB3DChunk = ^TBB3DChunk;
  26. TBB3DChunk = record
  27. Version: Integer;
  28. end;
  29. PTEXSChunk = ^TTEXSChunk;
  30. TTEXSChunk = record
  31. fileName: array[0..255] of char; //texture file name this is the filename of the texture, ie "wall.bmp" Has to be in the local Directory
  32. flags, blend: Integer; //blitz3D TextureFLags and TextureBlend: default=1,2
  33. //these are the same as far as I know as the flags for a texture in Blitz3D
  34. x_pos, y_pos: Single; //x and y position of texture: default=0,0
  35. x_scale, y_scale: Single; //x and y scale of texture: default=1,1
  36. rotation: Single; //rotation of texture (in radians): default=0 radian = 180/pi degrees
  37. end;
  38. PBRUSChunk = ^TBRUSChunk;
  39. TBRUSChunk = record
  40. n_texs: Integer;
  41. name: array[0..255] of Char; //eg "WATER" - just use texture name by default
  42. red, green, blue, alpha: Single; //Blitz3D Brushcolor and Brushalpha: default=1,1,1,1
  43. shininess: Single; //Blitz3D BrushShininess: default=0
  44. blend, fx: Integer; //Blitz3D Brushblend and BrushFX: default=1,0
  45. texture_id: array of Integer; //textures used in brush, ie if there is more then one texture used, ie Alphamaps, colour maps etc,
  46. //you put all ID's here as ints.
  47. end;
  48. PVertexData = ^TVertexData;
  49. TVertexData = record
  50. next: PVertexData;
  51. x, y, z: Single; //always present
  52. nx, ny, nz: Single; //vertex normal: present if (flags&1)
  53. red, green, blue, alpha: Single; //vertex color: present if (flags&2)
  54. tex_coords: array of Single; //tex coords
  55. end;
  56. PVRTSChunk = ^TVRTSChunk;
  57. TVRTSChunk = record
  58. flags: Integer; //1=normal values present, 2=rgba values present
  59. tex_coord_sets: Integer; //texture coords per vertex (eg: 1 for simple U/V) max=8
  60. tex_coord_set_size: Integer; //components per set (eg: 2 for simple U/V) max=4
  61. vertices: PVertexData;
  62. end;
  63. PTRISChunk = ^TTRISChunk;
  64. TTRISChunk = record
  65. next: PTRISChunk;
  66. brush_id: Integer; //brush applied to these TRIs: default=-1
  67. vertex_id: array of Integer; //vertex indices
  68. end;
  69. PMESHChunk = ^TMESHChunk;
  70. TMESHChunk = record
  71. brush_id: Integer; //'master' brush: default=-1
  72. vertices: TVRTSChunk; //vertices
  73. triangles: PTRISChunk; //1 or more sets of triangles
  74. end;
  75. PBONEChunk = ^TBONEChunk;
  76. TBONEChunk = record
  77. vertex_id: Integer; //vertex affected by this bone
  78. weight: Single; //;how much the vertex is affected
  79. end;
  80. PKEYSChunk = ^TKEYSChunk;
  81. TKEYSChunk = record
  82. next: PKEYSChunk;
  83. flags: Integer; //1=position, 2=scale, 4=rotation
  84. frame: Integer; //where key occurs
  85. position: TAffineVector; //present if (flags&1)
  86. scale: TAffineVector; //present if (flags&2)
  87. rotation: TVector; //present if (flags&4)
  88. end;
  89. PANIMChunk = ^TANIMChunk;
  90. TANIMChunk = record
  91. flags: Integer; //unused: default=0
  92. frames: Integer; //how many frames in anim
  93. fps: Single; //default=60
  94. end;
  95. PNODEChunk = ^TNODEChunk;
  96. TNODEChunk = record
  97. name: array[0..255] of char; //name of node
  98. position: TAffineVector; //local...
  99. scale: TAffineVector; //coord...
  100. rotation: TVector; //system...
  101. //array of node elements
  102. //should be one of meshes or bones, support meshes only for now
  103. meshes: PMESHChunk; //what 'kind' of node this is - if unrecognized, just use a Blitz3D pivot.
  104. {
  105. not supprot yet
  106. bones: PBONEChunk;
  107. }
  108. keys: PKEYSChunk; //optional animation keys
  109. nodes: PNODEChunk; //optional child nodes
  110. animation: TANIMChunk; //optional animation
  111. next: PNODEChunk; //point to the next node
  112. level: Integer;
  113. end;
  114. type
  115. TB3DMaterial = class
  116. public
  117. MaterialData: TBRUSChunk;
  118. constructor Create;
  119. destructor Destroy; override;
  120. function GetMaterialName: string;
  121. end;
  122. TB3DTexture = class
  123. public
  124. TextureData: TTEXSChunk;
  125. constructor Create;
  126. destructor Destroy; override;
  127. function GetTextureName: string;
  128. end;
  129. TB3DNode = class
  130. public
  131. NodeData: PNODEChunk;
  132. constructor Create;
  133. destructor Destroy; override;
  134. function GetNodeName: string;
  135. procedure DestroyNodeData(Node: PNODEChunk);
  136. end;
  137. // TFileB3D
  138. //
  139. TFileB3D = class
  140. private
  141. fTextures: TStringList;
  142. fMaterials: TStringList;
  143. fNodes: TB3DNode;
  144. procedure FreeLists;
  145. function GetChunkType(const aChunk: TB3DChunk): TB3DChunkType;
  146. function SkipChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  147. function ReadTextureChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  148. function ReadMaterialChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  149. function ReadNodeChunk(aStream: TStream; const aChunk: TB3DChunk; Node: PNODEChunk; level: Integer): Integer;
  150. function ReadMeshChunk(aStream: TStream; const aChunk: TB3DChunk; Mesh: PMESHChunk): Integer;
  151. function ReadVerticesChunk(aStream: TStream; const aChunk: TB3DChunk; Vertices: PVRTSChunk): Integer;
  152. function ReadTrianglesChunk(aStream: TStream; const aChunk: TB3DChunk; Triangle: PTRISChunk): Integer;
  153. public
  154. constructor Create; virtual;
  155. destructor Destroy; override;
  156. procedure LoadFromStream(aStream : TStream);
  157. //for test only
  158. procedure Check;
  159. property Textures: TStringList read fTextures;
  160. property Materials: TStringList read fMaterials;
  161. property Nodes: TB3DNode read fNodes;
  162. end;
  163. //-----------------------------------------------------------------------
  164. implementation
  165. //-----------------------------------------------------------------------
  166. constructor TB3DMaterial.Create;
  167. begin
  168. inherited Create;
  169. fillChar(MaterialData, sizeof(TBRUSChunk), 0);
  170. end;
  171. destructor TB3DMaterial.Destroy;
  172. begin
  173. SetLength(MaterialData.texture_id, 0);
  174. inherited Destroy;
  175. end;
  176. function TB3DMaterial.GetMaterialName: string;
  177. begin
  178. SetString(Result, MaterialData.name, strlen(MaterialData.name));
  179. end;
  180. constructor TB3DTexture.Create;
  181. begin
  182. inherited Create;
  183. fillChar(TextureData, sizeof(TTEXSChunk), 0);
  184. end;
  185. destructor TB3DTexture.Destroy;
  186. begin
  187. inherited Destroy;
  188. end;
  189. function TB3DTexture.GetTextureName: string;
  190. begin
  191. SetString(Result, TextureData.fileName, strlen(TextureData.fileName));
  192. end;
  193. constructor TB3DNode.Create;
  194. begin
  195. inherited Create;
  196. NodeData := nil;
  197. end;
  198. destructor TB3DNode.Destroy;
  199. begin
  200. DestroyNodeData(NodeData);
  201. inherited Destroy;
  202. end;
  203. function TB3DNode.GetNodeName: string;
  204. begin
  205. SetString(Result, NodeData^.name, strlen(NodeData^.name));
  206. end;
  207. procedure DeleteVertices(var aVertex: PVertexData);
  208. var
  209. V: PVertexData;
  210. begin
  211. while aVertex<>nil do
  212. begin
  213. SetLength(aVertex^.tex_coords, 0);
  214. V := aVertex^.next;
  215. freeMem(aVertex);
  216. aVertex := nil;
  217. DeleteVertices(V);
  218. end;
  219. end;
  220. procedure DeleteTriangles(var aTriangle: PTRISChunk);
  221. var
  222. T: PTRISChunk;
  223. begin
  224. while aTriangle<>nil do
  225. begin
  226. SetLength(aTriangle^.vertex_id, 0);
  227. T := aTriangle^.next;
  228. freeMem(aTriangle);
  229. aTriangle := nil;
  230. DeleteTriangles(T);
  231. end;
  232. end;
  233. procedure TB3DNode.DestroyNodeData(Node: PNODEChunk);
  234. var
  235. oldNode, PNode: PNODEChunk;
  236. begin
  237. PNode := Node;
  238. while PNode<>nil do
  239. begin
  240. if PNode^.meshes<>nil then
  241. begin
  242. DeleteTriangles(PNode^.meshes^.triangles);
  243. DeleteVertices(PNode^.meshes^.vertices.vertices);
  244. freeMem(PNode^.meshes);
  245. PNode^.meshes := nil;
  246. end;
  247. if PNode^.keys<>nil then
  248. freeMem(PNode^.keys);
  249. DestroyNodeData(PNode^.nodes);
  250. oldNode := PNode;
  251. PNode := PNode^.next;
  252. freeMem(oldNode);
  253. end;
  254. end;
  255. //------------------------------------------------------------------------------
  256. constructor TFileB3D.Create;
  257. begin
  258. inherited Create;
  259. fTextures := TStringList.Create;
  260. fMaterials := TStringList.Create;
  261. fNodes := TB3DNode.Create;
  262. end;
  263. destructor TFileB3D.Destroy;
  264. begin
  265. FreeLists;
  266. fTextures.free;
  267. fMaterials.free;
  268. fNodes.free;
  269. inherited Destroy;
  270. end;
  271. function TFileB3D.GetChunkType(const aChunk: TB3DChunk): TB3DChunkType;
  272. begin
  273. Result := bctUnKnown;
  274. if StrLIComp(aChunk.chunk, 'BB3D', 4)=0 then
  275. Result := bctHeader;
  276. if StrLIComp(aChunk.chunk, 'TEXS', 4)=0 then
  277. Result := bctTexture;
  278. if StrLIComp(aChunk.chunk, 'BRUS', 4)=0 then
  279. Result := bctBrush;
  280. if StrLIComp(aChunk.chunk, 'NODE', 4)=0 then
  281. Result := bctNode;
  282. if StrLIComp(aChunk.chunk, 'VRTS', 4)=0 then
  283. Result := bctVertex;
  284. if StrLIComp(aChunk.chunk, 'BONE', 4)=0 then
  285. Result := bctBone;
  286. if StrLIComp(aChunk.chunk, 'KEYS', 4)=0 then
  287. Result := bctKeyFrame;
  288. if StrLIComp(aChunk.chunk, 'ANIM', 4)=0 then
  289. Result := bctAnimation;
  290. if StrLIComp(aChunk.chunk, 'MESH', 4)=0 then
  291. Result := bctMesh;
  292. if StrLIComp(aChunk.chunk, 'TRIS', 4)=0 then
  293. Result := bctTriangle;
  294. end;
  295. function TFileB3D.SkipChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  296. begin
  297. aStream.Seek(aChunk.length, soFromCurrent);
  298. Result := aChunk.length;
  299. end;
  300. function ReadString(aStream: TStream; buffer: PChar; MaxCount: Integer): Integer;
  301. begin
  302. Result := 0;
  303. while Result<MaxCount do
  304. begin
  305. aStream.Read(buffer[Result], sizeof(char));
  306. Inc(result);
  307. if buffer[result-1]=#0 then
  308. break;
  309. end;
  310. end;
  311. function TFileB3D.ReadTextureChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  312. var
  313. Texture: TB3DTexture;
  314. Count: Integer;
  315. begin
  316. Result := 0;
  317. if aChunk.length<5 then
  318. exit;
  319. Count := 0;
  320. while Count<aChunk.length do
  321. begin
  322. Texture := TB3DTexture.Create;
  323. Inc(Count, ReadString(aStream, Texture.TextureData.fileName, 255));
  324. Inc(Count, aStream.Read(Texture.TextureData.flags, sizeof(integer)));
  325. Inc(Count, aStream.Read(Texture.TextureData.blend, sizeof(integer)));
  326. Inc(Count, aStream.Read(Texture.TextureData.x_pos, sizeof(single)));
  327. Inc(Count, aStream.Read(Texture.TextureData.y_pos, sizeof(single)));
  328. Inc(Count, aStream.Read(Texture.TextureData.x_scale, sizeof(single)));
  329. Inc(Count, aStream.Read(Texture.TextureData.y_scale, sizeof(single)));
  330. Inc(Count, aStream.Read(Texture.TextureData.rotation, sizeof(single)));
  331. fTextures.AddObject(Texture.GetTextureName, Texture);
  332. end;
  333. Result := fTextures.Count;
  334. end;
  335. function TFileB3D.ReadMaterialChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
  336. var
  337. Material: TB3DMaterial;
  338. Count, I: Integer;
  339. TextureCount: Integer;
  340. begin
  341. Result := 0;
  342. if aChunk.length<5 then
  343. exit;
  344. Count := 0;
  345. TextureCount := 0;
  346. while Count<aChunk.length do
  347. begin
  348. Material := TB3DMaterial.Create;
  349. if Count=0 then
  350. begin
  351. Inc(Count, aStream.Read(Material.MaterialData.n_texs, sizeof(integer)));
  352. TextureCount := Material.MaterialData.n_texs;
  353. end else
  354. Material.MaterialData.n_texs := TextureCount;
  355. Inc(Count, ReadString(aStream, Material.MaterialData.name, 255));
  356. Inc(Count, aStream.Read(Material.MaterialData.red, sizeof(single)));
  357. Inc(Count, aStream.Read(Material.MaterialData.green, sizeof(single)));
  358. Inc(Count, aStream.Read(Material.MaterialData.blue, sizeof(single)));
  359. Inc(Count, aStream.Read(Material.MaterialData.alpha, sizeof(single)));
  360. Inc(Count, aStream.Read(Material.MaterialData.shininess, sizeof(single)));
  361. Inc(Count, aStream.Read(Material.MaterialData.blend, sizeof(integer)));
  362. Inc(Count, aStream.Read(Material.MaterialData.fx, sizeof(integer)));
  363. SetLength(Material.MaterialData.texture_id, TextureCount);
  364. for I:=0 to TextureCount-1 do
  365. Inc(Count, aStream.Read(Material.MaterialData.texture_id[I], sizeof(Integer)));
  366. fMaterials.AddObject(Material.GetMaterialName, Material);
  367. end;
  368. Result := fMaterials.Count;
  369. end;
  370. function TFileB3D.ReadMeshChunk(aStream: TStream; const aChunk: TB3DChunk; Mesh: PMESHChunk): Integer;
  371. var
  372. C: TB3DChunk;
  373. T: PTRISChunk;
  374. begin
  375. Result := 0;
  376. fillChar(Mesh^, sizeof(TMESHChunk), 0);
  377. Mesh^.brush_id := -1;
  378. Inc(Result, aStream.Read(Mesh^.brush_id, sizeof(Integer)));
  379. T := nil;
  380. while Result<aChunk.length do
  381. begin
  382. Inc(Result, aStream.Read(C, sizeof(TB3DChunk)));
  383. case GetChunkType(C) of
  384. bctVertex:
  385. begin
  386. Inc(Result, ReadVerticesChunk(aStream, C, @(Mesh^.vertices)));
  387. end;
  388. bctTriangle:
  389. begin
  390. if Mesh^.triangles=nil then
  391. begin
  392. GetMem(Mesh^.triangles, sizeof(TTRISChunk));
  393. fillChar(Mesh^.triangles^, sizeof(TTRISChunk), 0);
  394. Inc(Result, ReadTrianglesChunk(aStream, C, Mesh^.triangles));
  395. end else
  396. begin
  397. if T=nil then
  398. begin
  399. GetMem(T, sizeof(TTRISChunk));
  400. fillChar(T^, sizeof(TTRISChunk), 0);
  401. Inc(Result, ReadTrianglesChunk(aStream, C, T));
  402. Mesh^.triangles^.next := T;
  403. end else
  404. begin
  405. GetMem(T^.next, sizeof(TTRISChunk));
  406. fillChar(T^.next^, sizeof(TTRISChunk), 0);
  407. Inc(Result, ReadTrianglesChunk(aStream, C, T^.next));
  408. T := T^.next;
  409. end;
  410. end;
  411. end;
  412. else
  413. inc(Result, SkipChunk(aStream, C));
  414. end;
  415. end;
  416. end;
  417. function TFileB3D.ReadVerticesChunk(aStream: TStream; const aChunk: TB3DChunk; Vertices: PVRTSChunk): Integer;
  418. var
  419. v: PVertexData;
  420. v1: PVertexData;
  421. size: Integer;
  422. begin
  423. Result := 0;
  424. fillChar(Vertices^, sizeof(TVRTSChunk), 0);
  425. Inc(Result, aStream.Read(Vertices^.flags, sizeof(Integer)));
  426. Inc(Result, aStream.Read(Vertices^.tex_coord_sets, sizeof(Integer)));
  427. Inc(Result, aStream.Read(Vertices^.tex_coord_set_size, sizeof(Integer)));
  428. size := Vertices^.tex_coord_set_size*Vertices^.tex_coord_sets;
  429. v := nil;
  430. while Result<aChunk.length do
  431. begin
  432. if Vertices^.vertices=nil then
  433. begin
  434. GetMem(Vertices^.vertices, sizeof(TVertexData));
  435. fillChar(vertices^.vertices^, sizeof(TVertexData), 0);
  436. end else
  437. begin
  438. if v=nil then
  439. begin
  440. GetMem(v, sizeof(TVertexData));
  441. fillChar(v^, sizeof(TVertexData), 0);
  442. vertices^.vertices^.next := v;
  443. end else
  444. begin
  445. GetMem(v^.next, sizeof(TVertexData));
  446. fillChar(v^.next^, sizeof(TVertexData), 0);
  447. v := v^.next;
  448. end;
  449. end;
  450. if v=nil then
  451. v1 := vertices^.vertices
  452. else
  453. v1 := v;
  454. Inc(Result, aStream.Read(v1^.x, sizeof(single)));
  455. Inc(Result, aStream.Read(v1^.y, sizeof(single)));
  456. Inc(Result, aStream.Read(v1^.z, sizeof(single)));
  457. //W3D Begin
  458. if (Vertices^.flags and 1)>0 then begin
  459. Inc(Result, aStream.Read(v1^.nx, sizeof(single)));
  460. Inc(Result, aStream.Read(v1^.ny, sizeof(single)));
  461. Inc(Result, aStream.Read(v1^.nz, sizeof(single)));
  462. end;
  463. if (Vertices^.flags and 2)>0 then begin
  464. Inc(Result, aStream.Read(v1^.red, sizeof(single)));
  465. Inc(Result, aStream.Read(v1^.green, sizeof(single)));
  466. Inc(Result, aStream.Read(v1^.blue, sizeof(single)));
  467. Inc(Result, aStream.Read(v1^.alpha, sizeof(single)));
  468. end;
  469. //W3D END
  470. SetLength(v1^.tex_coords, size);
  471. Inc(Result, aStream.Read(v1^.tex_coords[0], size*sizeof(single)));
  472. end;
  473. end;
  474. function TFileB3D.ReadTrianglesChunk(aStream: TStream; const aChunk: TB3DChunk; Triangle: PTRISChunk): Integer;
  475. begin
  476. Result := 0;
  477. if Triangle=nil then
  478. begin
  479. GetMem(Triangle, sizeof(TTRISChunk));
  480. fillChar(Triangle^, sizeof(TTRISChunk), 0);
  481. Triangle^.brush_id := -1;
  482. end;
  483. Inc(Result, aStream.Read(Triangle^.brush_id, sizeof(Integer)));
  484. SetLength(Triangle^.vertex_id, (aChunk.length-Result) div sizeof(Integer));
  485. Inc(Result, aStream.Read(Triangle^.vertex_id[0], (aChunk.length-Result)));
  486. end;
  487. //read in only the mesh data, the keyframes and animation had been dropped
  488. function TFileB3D.ReadNodeChunk(aStream: TStream; const aChunk: TB3DChunk; Node: PNODEChunk; level: Integer): Integer;
  489. var
  490. Count: Integer;
  491. C: TB3DChunk;
  492. N: PNODEChunk;
  493. begin
  494. N := nil;
  495. fillChar(Node^, sizeof(TNODEChunk), 0);
  496. Node^.level := level;
  497. Count := 0;
  498. Inc(Count, ReadString(aStream, Node^.name, 255));
  499. Inc(Count, aStream.Read(Node^.position.X, sizeof(TAffineVector)));
  500. Inc(Count, aStream.Read(Node^.scale.X, sizeof(TAffineVector)));
  501. Inc(Count, aStream.Read(Node^.rotation.X, sizeof(TVector)));
  502. while Count<aChunk.length do
  503. begin
  504. Inc(Count, aStream.Read(C, sizeof(TB3DChunk)));
  505. case GetChunkType(C) of
  506. bctMesh:
  507. begin
  508. GetMem(Node^.meshes, sizeof(TMESHChunk));
  509. Inc(Count, ReadMeshChunk(aStream, C, Node^.meshes));
  510. end;
  511. bctKeyframe:
  512. begin
  513. Inc(Count, SkipChunk(aStream, C));
  514. end;
  515. bctNode:
  516. begin
  517. if N=nil then
  518. begin
  519. GetMem(N, sizeof(TNODEChunk));
  520. fillChar(N^, sizeof(TNODEChunk), 0);
  521. Inc(Count, ReadNodeChunk(aStream, C, N, level + 1));
  522. Node^.next := N;
  523. end else
  524. begin
  525. GetMem(N^.next, sizeof(TNODEChunk));
  526. fillChar(N^.next^, sizeof(TNODEChunk), 0);
  527. Inc(Count, ReadNodeChunk(aStream, C, N^.next, level + 1));
  528. N := N^.next;
  529. end;
  530. end;
  531. bctAnimation:
  532. begin
  533. Inc(Count, SkipChunk(aStream, C));
  534. end;
  535. else
  536. Inc(Count, SkipChunk(aStream, C));
  537. end;
  538. end;
  539. Result := Count;
  540. end;
  541. procedure TFileB3D.LoadFromStream(aStream : TStream);
  542. var
  543. aChunk: TB3DChunk;
  544. FileSize: Integer;
  545. begin
  546. FileSize := aStream.Size;
  547. while aStream.Position<FileSize do
  548. begin
  549. aStream.Read(aChunk, sizeof(TB3DChunk));
  550. case GetChunkType(aChunk) of
  551. bctHeader:
  552. begin
  553. FileSize := aChunk.length - sizeof(TB3DChunk) - sizeof(TBB3DChunk);
  554. aStream.Seek(sizeof(TBB3DChunk), soFromCurrent);
  555. end;
  556. bctTexture:
  557. begin
  558. ReadTextureChunk(aStream, aChunk);
  559. end;
  560. bctBrush:
  561. begin
  562. ReadMaterialChunk(aStream, aChunk);
  563. end;
  564. bctNode:
  565. begin
  566. if fNodes.NodeData=nil then
  567. begin
  568. GetMem(fNodes.NodeData, sizeof(TNODEChunk));
  569. ReadNodeChunk(aStream, aChunk, fNodes.NodeData, 0);
  570. end;
  571. end;
  572. else
  573. SkipChunk(aStream, aChunk);
  574. end;
  575. end;
  576. end;
  577. procedure TFileB3D.FreeLists;
  578. begin
  579. while fTextures.Count>0 do
  580. begin
  581. fTextures.Objects[0].free;
  582. ftextures.Delete(0);
  583. end;
  584. while fMaterials.Count>0 do
  585. begin
  586. fMaterials.Objects[0].free;
  587. fMaterials.Delete(0);
  588. end;
  589. end;
  590. //for test only
  591. procedure TFileB3D.Check;
  592. var
  593. NodeLevel: Integer;
  594. // NodeCount: Integer;
  595. Node: PNODEChunk;
  596. // VerticesCount: Integer;
  597. // FaceCount: Integer;
  598. Face: PTRISChunk;
  599. Vertex: PVertexData;
  600. begin
  601. NodeLevel := 0;
  602. // NodeCount := 0;
  603. // VerticesCount := 0;
  604. // FaceCount := 0;
  605. Node := fNodes.NodeData;
  606. while Node<>nil do
  607. begin
  608. if Node^.meshes<>nil then
  609. // Inc(NodeCount);
  610. if Node^.level>NodeLevel then
  611. NodeLevel := Node^.level;
  612. if Node^.meshes<>nil then
  613. begin
  614. Vertex := Node^.meshes.vertices.vertices;
  615. while Vertex<>nil do
  616. begin
  617. // Inc(VerticesCount);
  618. Vertex := Vertex.next;
  619. end;
  620. Face := Node^.meshes.triangles;
  621. while Face<>nil do
  622. begin
  623. // Inc(FaceCount);
  624. Face := Face.next;
  625. end;
  626. end;
  627. Node := Node^.next;
  628. end;
  629. //MessageBeep(FaceCount);
  630. //MessageBeep(VerticesCount);
  631. //MessageBeep(NodeLevel);
  632. //MessageBeep(NodeCount);
  633. end;
  634. end.