Formats.B3D.pas 19 KB

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