123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- //
- // The graphics engine GXScene
- //
- unit Formatx.B3D;
- (* File streaming class for the B3D loader *)
- interface
- {$I Stage.Defines.inc}
- {$R-}
- uses
- System.Classes,
- System.SysUtils,
-
- Stage.VectorGeometry,
- Stage.VectorTypes,
- GXS.VectorLists;
- type
- TB3DChunkType = (bctUnknown, bctHeader, bctTexture, bctBrush, bctNode, bctVertex, bctTriangle,
- bctMesh, bctBone, bctKeyFrame, bctAnimation);
- PB3DChunk = ^TB3DChunk;
- TB3DChunk = record
- chunk: array[0..3] of char;
- length: Integer;
- end;
- PBB3DChunk = ^TBB3DChunk;
- TBB3DChunk = record
- Version: Integer;
- end;
- PTEXSChunk = ^TTEXSChunk;
- TTEXSChunk = record
- 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
- flags, blend: Integer; //blitz3D TextureFLags and TextureBlend: default=1,2
- //these are the same as far as I know as the flags for a texture in Blitz3D
- x_pos, y_pos: Single; //x and y position of texture: default=0,0
- x_scale, y_scale: Single; //x and y scale of texture: default=1,1
- rotation: Single; //rotation of texture (in radians): default=0 radian = 180/pi degrees
- end;
- PBRUSChunk = ^TBRUSChunk;
- TBRUSChunk = record
- n_texs: Integer;
- name: array[0..255] of Char; //eg "WATER" - just use texture name by default
- red, green, blue, alpha: Single; //Blitz3D Brushcolor and Brushalpha: default=1,1,1,1
- shininess: Single; //Blitz3D BrushShininess: default=0
- blend, fx: Integer; //Blitz3D Brushblend and BrushFX: default=1,0
- texture_id: array of Integer; //textures used in brush, ie if there is more then one texture used, ie Alphamaps, colour maps etc,
- //you put all ID's here as ints.
- end;
- PVertexData = ^TVertexData;
- TVertexData = record
- next: PVertexData;
- x, y, z: Single; //always present
- nx, ny, nz: Single; //vertex normal: present if (flags&1)
- red, green, blue, alpha: Single; //vertex color: present if (flags&2)
- tex_coords: array of Single; //tex coords
- end;
- PVRTSChunk = ^TVRTSChunk;
- TVRTSChunk = record
- flags: Integer; //1=normal values present, 2=rgba values present
- tex_coord_sets: Integer; //texture coords per vertex (eg: 1 for simple U/V) max=8
- tex_coord_set_size: Integer; //components per set (eg: 2 for simple U/V) max=4
- vertices: PVertexData;
- end;
- PTRISChunk = ^TTRISChunk;
- TTRISChunk = record
- next: PTRISChunk;
- brush_id: Integer; //brush applied to these TRIs: default=-1
- vertex_id: array of Integer; //vertex indices
- end;
- PMESHChunk = ^TMESHChunk;
- TMESHChunk = record
- brush_id: Integer; //'master' brush: default=-1
- vertices: TVRTSChunk; //vertices
- triangles: PTRISChunk; //1 or more sets of triangles
- end;
- PBONEChunk = ^TBONEChunk;
- TBONEChunk = record
- vertex_id: Integer; //vertex affected by this bone
- weight: Single; //;how much the vertex is affected
- end;
- PKEYSChunk = ^TKEYSChunk;
- TKEYSChunk = record
- next: PKEYSChunk;
- flags: Integer; //1=position, 2=scale, 4=rotation
- frame: Integer; //where key occurs
- position: TAffineVector; //present if (flags&1)
- scale: TAffineVector; //present if (flags&2)
- rotation: TGLVector; //present if (flags&4)
- end;
- PANIMChunk = ^TANIMChunk;
- TANIMChunk = record
- flags: Integer; //unused: default=0
- frames: Integer; //how many frames in anim
- fps: Single; //default=60
- end;
- PNODEChunk = ^TNODEChunk;
- TNODEChunk = record
- name: array[0..255] of char; //name of node
- position: TAffineVector; //local...
- scale: TAffineVector; //coord...
- rotation: TGLVector; //system...
- //array of node elements
- //should be one of meshes or bones, support meshes only for now
- meshes: PMESHChunk; //what 'kind' of node this is - if unrecognized, just use a Blitz3D pivot.
- (*
- not supprot yet
- bones: PBONEChunk;
- *)
- keys: PKEYSChunk; //optional animation keys
- nodes: PNODEChunk; //optional child nodes
- animation: TANIMChunk; //optional animation
- next: PNODEChunk; //point to the next node
- level: Integer;
- end;
- type
- TB3DMaterial = class
- public
- MaterialData: TBRUSChunk;
- constructor Create;
- destructor Destroy; override;
- function GetMaterialName: string;
- end;
- TB3DTexture = class
- public
- TextureData: TTEXSChunk;
- constructor Create;
- destructor Destroy; override;
- function GetTextureName: string;
- end;
- TB3DNode = class
- public
- NodeData: PNODEChunk;
- constructor Create;
- destructor Destroy; override;
- function GetNodeName: string;
- procedure DestroyNodeData(Node: PNODEChunk);
- end;
- TFileB3D = class
- private
- fTextures: TStringList;
- fMaterials: TStringList;
- fNodes: TB3DNode;
- procedure FreeLists;
- function GetChunkType(const aChunk: TB3DChunk): TB3DChunkType;
- function SkipChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- function ReadTextureChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- function ReadMaterialChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- function ReadNodeChunk(aStream: TStream; const aChunk: TB3DChunk; Node: PNODEChunk; level: Integer): Integer;
- function ReadMeshChunk(aStream: TStream; const aChunk: TB3DChunk; Mesh: PMESHChunk): Integer;
- function ReadVerticesChunk(aStream: TStream; const aChunk: TB3DChunk; Vertices: PVRTSChunk): Integer;
- function ReadTrianglesChunk(aStream: TStream; const aChunk: TB3DChunk; Triangle: PTRISChunk): Integer;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- procedure LoadFromStream(aStream : TStream);
- //for test only
- procedure Check;
-
- property Textures: TStringList read fTextures;
- property Materials: TStringList read fMaterials;
- property Nodes: TB3DNode read fNodes;
- end;
- //-----------------------------------------------------------------------
- implementation
- //-----------------------------------------------------------------------
- constructor TB3DMaterial.Create;
- begin
- inherited Create;
- fillChar(MaterialData, sizeof(TBRUSChunk), 0);
- end;
- destructor TB3DMaterial.Destroy;
- begin
- SetLength(MaterialData.texture_id, 0);
- inherited Destroy;
- end;
- function TB3DMaterial.GetMaterialName: string;
- begin
- SetString(Result, MaterialData.name, strlen(MaterialData.name));
- end;
- constructor TB3DTexture.Create;
- begin
- inherited Create;
- fillChar(TextureData, sizeof(TTEXSChunk), 0);
- end;
- destructor TB3DTexture.Destroy;
- begin
- inherited Destroy;
- end;
- function TB3DTexture.GetTextureName: string;
- begin
- SetString(Result, TextureData.fileName, strlen(TextureData.fileName));
- end;
- constructor TB3DNode.Create;
- begin
- inherited Create;
- NodeData := nil;
- end;
- destructor TB3DNode.Destroy;
- begin
- DestroyNodeData(NodeData);
- inherited Destroy;
- end;
- function TB3DNode.GetNodeName: string;
- begin
- SetString(Result, NodeData^.name, strlen(NodeData^.name));
- end;
- procedure DeleteVertices(var aVertex: PVertexData);
- var
- V: PVertexData;
- begin
- while aVertex<>nil do
- begin
- SetLength(aVertex^.tex_coords, 0);
- V := aVertex^.next;
- freeMem(aVertex);
- aVertex := nil;
- DeleteVertices(V);
- end;
- end;
- procedure DeleteTriangles(var aTriangle: PTRISChunk);
- var
- T: PTRISChunk;
- begin
- while aTriangle<>nil do
- begin
- SetLength(aTriangle^.vertex_id, 0);
- T := aTriangle^.next;
- freeMem(aTriangle);
- aTriangle := nil;
- DeleteTriangles(T);
- end;
- end;
- procedure TB3DNode.DestroyNodeData(Node: PNODEChunk);
- var
- oldNode, PNode: PNODEChunk;
- begin
- PNode := Node;
- while PNode<>nil do
- begin
- if PNode^.meshes<>nil then
- begin
- DeleteTriangles(PNode^.meshes^.triangles);
- DeleteVertices(PNode^.meshes^.vertices.vertices);
- freeMem(PNode^.meshes);
- PNode^.meshes := nil;
- end;
- if PNode^.keys<>nil then
- freeMem(PNode^.keys);
- DestroyNodeData(PNode^.nodes);
- oldNode := PNode;
- PNode := PNode^.next;
- freeMem(oldNode);
- end;
- end;
- //------------------------------------------------------------------------------
- constructor TFileB3D.Create;
- begin
- inherited Create;
- fTextures := TStringList.Create;
- fMaterials := TStringList.Create;
- fNodes := TB3DNode.Create;
- end;
- destructor TFileB3D.Destroy;
- begin
- FreeLists;
- fTextures.free;
- fMaterials.free;
- fNodes.free;
- inherited Destroy;
- end;
- function TFileB3D.GetChunkType(const aChunk: TB3DChunk): TB3DChunkType;
- begin
- Result := bctUnKnown;
- if StrLIComp(aChunk.chunk, 'BB3D', 4)=0 then
- Result := bctHeader;
- if StrLIComp(aChunk.chunk, 'TEXS', 4)=0 then
- Result := bctTexture;
- if StrLIComp(aChunk.chunk, 'BRUS', 4)=0 then
- Result := bctBrush;
- if StrLIComp(aChunk.chunk, 'NODE', 4)=0 then
- Result := bctNode;
- if StrLIComp(aChunk.chunk, 'VRTS', 4)=0 then
- Result := bctVertex;
- if StrLIComp(aChunk.chunk, 'BONE', 4)=0 then
- Result := bctBone;
- if StrLIComp(aChunk.chunk, 'KEYS', 4)=0 then
- Result := bctKeyFrame;
- if StrLIComp(aChunk.chunk, 'ANIM', 4)=0 then
- Result := bctAnimation;
- if StrLIComp(aChunk.chunk, 'MESH', 4)=0 then
- Result := bctMesh;
- if StrLIComp(aChunk.chunk, 'TRIS', 4)=0 then
- Result := bctTriangle;
- end;
- function TFileB3D.SkipChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- begin
- aStream.Seek(aChunk.length, soFromCurrent);
- Result := aChunk.length;
- end;
- function ReadString(aStream: TStream; buffer: PChar; MaxCount: Integer): Integer;
- begin
- Result := 0;
- while Result<MaxCount do
- begin
- aStream.Read(buffer[Result], sizeof(char));
- Inc(result);
- if buffer[result-1]=#0 then
- break;
- end;
- end;
- function TFileB3D.ReadTextureChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- var
- Texture: TB3DTexture;
- Count: Integer;
- begin
- Result := 0;
- if aChunk.length<5 then
- exit;
- Count := 0;
- while Count<aChunk.length do
- begin
- Texture := TB3DTexture.Create;
- Inc(Count, ReadString(aStream, Texture.TextureData.fileName, 255));
- Inc(Count, aStream.Read(Texture.TextureData.flags, sizeof(integer)));
- Inc(Count, aStream.Read(Texture.TextureData.blend, sizeof(integer)));
- Inc(Count, aStream.Read(Texture.TextureData.x_pos, sizeof(single)));
- Inc(Count, aStream.Read(Texture.TextureData.y_pos, sizeof(single)));
- Inc(Count, aStream.Read(Texture.TextureData.x_scale, sizeof(single)));
- Inc(Count, aStream.Read(Texture.TextureData.y_scale, sizeof(single)));
- Inc(Count, aStream.Read(Texture.TextureData.rotation, sizeof(single)));
- fTextures.AddObject(Texture.GetTextureName, Texture);
- end;
- Result := fTextures.Count;
- end;
- function TFileB3D.ReadMaterialChunk(aStream: TStream; const aChunk: TB3DChunk): Integer;
- var
- Material: TB3DMaterial;
- Count, I: Integer;
- TextureCount: Integer;
- begin
- Result := 0;
- if aChunk.length<5 then
- exit;
- Count := 0;
- TextureCount := 0;
- while Count<aChunk.length do
- begin
- Material := TB3DMaterial.Create;
- if Count=0 then
- begin
- Inc(Count, aStream.Read(Material.MaterialData.n_texs, sizeof(integer)));
- TextureCount := Material.MaterialData.n_texs;
- end else
- Material.MaterialData.n_texs := TextureCount;
- Inc(Count, ReadString(aStream, Material.MaterialData.name, 255));
- Inc(Count, aStream.Read(Material.MaterialData.red, sizeof(single)));
- Inc(Count, aStream.Read(Material.MaterialData.green, sizeof(single)));
- Inc(Count, aStream.Read(Material.MaterialData.blue, sizeof(single)));
- Inc(Count, aStream.Read(Material.MaterialData.alpha, sizeof(single)));
- Inc(Count, aStream.Read(Material.MaterialData.shininess, sizeof(single)));
- Inc(Count, aStream.Read(Material.MaterialData.blend, sizeof(integer)));
- Inc(Count, aStream.Read(Material.MaterialData.fx, sizeof(integer)));
- SetLength(Material.MaterialData.texture_id, TextureCount);
- for I:=0 to TextureCount-1 do
- Inc(Count, aStream.Read(Material.MaterialData.texture_id[I], sizeof(Integer)));
- fMaterials.AddObject(Material.GetMaterialName, Material);
- end;
- Result := fMaterials.Count;
- end;
- function TFileB3D.ReadMeshChunk(aStream: TStream; const aChunk: TB3DChunk; Mesh: PMESHChunk): Integer;
- var
- C: TB3DChunk;
- T: PTRISChunk;
- begin
- Result := 0;
- fillChar(Mesh^, sizeof(TMESHChunk), 0);
- Mesh^.brush_id := -1;
- Inc(Result, aStream.Read(Mesh^.brush_id, sizeof(Integer)));
- T := nil;
- while Result<aChunk.length do
- begin
- Inc(Result, aStream.Read(C, sizeof(TB3DChunk)));
- case GetChunkType(C) of
- bctVertex:
- begin
- Inc(Result, ReadVerticesChunk(aStream, C, @(Mesh^.vertices)));
- end;
- bctTriangle:
- begin
- if Mesh^.triangles=nil then
- begin
- GetMem(Mesh^.triangles, sizeof(TTRISChunk));
- fillChar(Mesh^.triangles^, sizeof(TTRISChunk), 0);
- Inc(Result, ReadTrianglesChunk(aStream, C, Mesh^.triangles));
- end else
- begin
- if T=nil then
- begin
- GetMem(T, sizeof(TTRISChunk));
- fillChar(T^, sizeof(TTRISChunk), 0);
- Inc(Result, ReadTrianglesChunk(aStream, C, T));
- Mesh^.triangles^.next := T;
- end else
- begin
- GetMem(T^.next, sizeof(TTRISChunk));
- fillChar(T^.next^, sizeof(TTRISChunk), 0);
- Inc(Result, ReadTrianglesChunk(aStream, C, T^.next));
- T := T^.next;
- end;
- end;
- end;
- else
- inc(Result, SkipChunk(aStream, C));
- end;
- end;
- end;
- function TFileB3D.ReadVerticesChunk(aStream: TStream; const aChunk: TB3DChunk; Vertices: PVRTSChunk): Integer;
- var
- v: PVertexData;
- v1: PVertexData;
- size: Integer;
- begin
- Result := 0;
- fillChar(Vertices^, sizeof(TVRTSChunk), 0);
- Inc(Result, aStream.Read(Vertices^.flags, sizeof(Integer)));
- Inc(Result, aStream.Read(Vertices^.tex_coord_sets, sizeof(Integer)));
- Inc(Result, aStream.Read(Vertices^.tex_coord_set_size, sizeof(Integer)));
- size := Vertices^.tex_coord_set_size*Vertices^.tex_coord_sets;
- v := nil;
- while Result<aChunk.length do
- begin
- if Vertices^.vertices=nil then
- begin
- GetMem(Vertices^.vertices, sizeof(TVertexData));
- fillChar(vertices^.vertices^, sizeof(TVertexData), 0);
- end else
- begin
- if v=nil then
- begin
- GetMem(v, sizeof(TVertexData));
- fillChar(v^, sizeof(TVertexData), 0);
- vertices^.vertices^.next := v;
- end else
- begin
- GetMem(v^.next, sizeof(TVertexData));
- fillChar(v^.next^, sizeof(TVertexData), 0);
- v := v^.next;
- end;
- end;
- if v=nil then
- v1 := vertices^.vertices
- else
- v1 := v;
- Inc(Result, aStream.Read(v1^.x, sizeof(single)));
- Inc(Result, aStream.Read(v1^.y, sizeof(single)));
- Inc(Result, aStream.Read(v1^.z, sizeof(single)));
- //W3D Begin
- if (Vertices^.flags and 1)>0 then begin
- Inc(Result, aStream.Read(v1^.nx, sizeof(single)));
- Inc(Result, aStream.Read(v1^.ny, sizeof(single)));
- Inc(Result, aStream.Read(v1^.nz, sizeof(single)));
- end;
- if (Vertices^.flags and 2)>0 then begin
- Inc(Result, aStream.Read(v1^.red, sizeof(single)));
- Inc(Result, aStream.Read(v1^.green, sizeof(single)));
- Inc(Result, aStream.Read(v1^.blue, sizeof(single)));
- Inc(Result, aStream.Read(v1^.alpha, sizeof(single)));
- end;
- //W3D END
- SetLength(v1^.tex_coords, size);
- Inc(Result, aStream.Read(v1^.tex_coords[0], size*sizeof(single)));
- end;
- end;
- function TFileB3D.ReadTrianglesChunk(aStream: TStream; const aChunk: TB3DChunk; Triangle: PTRISChunk): Integer;
- begin
- Result := 0;
- if Triangle=nil then
- begin
- GetMem(Triangle, sizeof(TTRISChunk));
- fillChar(Triangle^, sizeof(TTRISChunk), 0);
- Triangle^.brush_id := -1;
- end;
- Inc(Result, aStream.Read(Triangle^.brush_id, sizeof(Integer)));
- SetLength(Triangle^.vertex_id, (aChunk.length-Result) div sizeof(Integer));
- Inc(Result, aStream.Read(Triangle^.vertex_id[0], (aChunk.length-Result)));
- end;
- //read in only the mesh data, the keyframes and animation had been dropped
- function TFileB3D.ReadNodeChunk(aStream: TStream; const aChunk: TB3DChunk; Node: PNODEChunk; level: Integer): Integer;
- var
- Count: Integer;
- C: TB3DChunk;
- N: PNODEChunk;
- begin
- N := nil;
- fillChar(Node^, sizeof(TNODEChunk), 0);
- Node^.level := level;
- Count := 0;
- Inc(Count, ReadString(aStream, Node^.name, 255));
- Inc(Count, aStream.Read(Node^.position.X, sizeof(TAffineVector)));
- Inc(Count, aStream.Read(Node^.scale.X, sizeof(TAffineVector)));
- Inc(Count, aStream.Read(Node^.rotation.X, sizeof(TGLVector)));
- while Count<aChunk.length do
- begin
- Inc(Count, aStream.Read(C, sizeof(TB3DChunk)));
- case GetChunkType(C) of
- bctMesh:
- begin
- GetMem(Node^.meshes, sizeof(TMESHChunk));
- Inc(Count, ReadMeshChunk(aStream, C, Node^.meshes));
- end;
- bctKeyframe:
- begin
- Inc(Count, SkipChunk(aStream, C));
- end;
- bctNode:
- begin
- if N=nil then
- begin
- GetMem(N, sizeof(TNODEChunk));
- fillChar(N^, sizeof(TNODEChunk), 0);
- Inc(Count, ReadNodeChunk(aStream, C, N, level + 1));
- Node^.next := N;
- end else
- begin
- GetMem(N^.next, sizeof(TNODEChunk));
- fillChar(N^.next^, sizeof(TNODEChunk), 0);
- Inc(Count, ReadNodeChunk(aStream, C, N^.next, level + 1));
- N := N^.next;
- end;
- end;
- bctAnimation:
- begin
- Inc(Count, SkipChunk(aStream, C));
- end;
- else
- Inc(Count, SkipChunk(aStream, C));
- end;
- end;
- Result := Count;
- end;
- procedure TFileB3D.LoadFromStream(aStream : TStream);
- var
- aChunk: TB3DChunk;
- FileSize: Integer;
- begin
- FileSize := aStream.Size;
- while aStream.Position<FileSize do
- begin
- aStream.Read(aChunk, sizeof(TB3DChunk));
- case GetChunkType(aChunk) of
- bctHeader:
- begin
- FileSize := aChunk.length - sizeof(TB3DChunk) - sizeof(TBB3DChunk);
- aStream.Seek(sizeof(TBB3DChunk), soFromCurrent);
- end;
- bctTexture:
- begin
- ReadTextureChunk(aStream, aChunk);
- end;
- bctBrush:
- begin
- ReadMaterialChunk(aStream, aChunk);
- end;
- bctNode:
- begin
- if fNodes.NodeData=nil then
- begin
- GetMem(fNodes.NodeData, sizeof(TNODEChunk));
- ReadNodeChunk(aStream, aChunk, fNodes.NodeData, 0);
- end;
- end;
- else
- SkipChunk(aStream, aChunk);
- end;
- end;
- end;
- procedure TFileB3D.FreeLists;
- begin
- while fTextures.Count>0 do
- begin
- fTextures.Objects[0].free;
- ftextures.Delete(0);
- end;
- while fMaterials.Count>0 do
- begin
- fMaterials.Objects[0].free;
- fMaterials.Delete(0);
- end;
- end;
- //for test only
- procedure TFileB3D.Check;
- var
- NodeLevel: Integer;
- // NodeCount: Integer;
- Node: PNODEChunk;
- // VerticesCount: Integer;
- // FaceCount: Integer;
- Face: PTRISChunk;
- Vertex: PVertexData;
- begin
- NodeLevel := 0;
- // NodeCount := 0;
- // VerticesCount := 0;
- // FaceCount := 0;
- Node := fNodes.NodeData;
- while Node<>nil do
- begin
- if Node^.meshes<>nil then
- // Inc(NodeCount);
- if Node^.level>NodeLevel then
- NodeLevel := Node^.level;
- if Node^.meshes<>nil then
- begin
- Vertex := Node^.meshes.vertices.vertices;
- while Vertex<>nil do
- begin
- // Inc(VerticesCount);
- Vertex := Vertex.next;
- end;
- Face := Node^.meshes.triangles;
- while Face<>nil do
- begin
- // Inc(FaceCount);
- Face := Face.next;
- end;
- end;
- Node := Node^.next;
- end;
- //MessageBeep(FaceCount);
- //MessageBeep(VerticesCount);
- //MessageBeep(NodeLevel);
- //MessageBeep(NodeCount);
- end;
- end.
|