This is a 3DS max loader in Delphi6. The program always end with an access violation in memory, somwhere in the T3DObject.Create section, when it is called from an another class. (first occur in TChunk.Load3Data when AddObject is called) Why? How can it be solved?
unit Unit3DS_11;
interface
uses Windows, Classes;
type point = record
k:integer;
x,y,z,nx,ny,nz:Single;
end;
type face = record
a,b,c:integer;
end;
type T3DObject = class(TObject)
private
// Nothing here at moment
public
PointCount, FaceCount: Integer;
ObjectName:String;
p:array of point;
f:array of face;
constructor Create;
destructor Destroy; override;
procedure Draw;
end;
type TChunk = class(TObject)
private
function ReadObjectString:String;
public
Id: word;
iBytesReaded, ChunkLength : Integer;
iFileHandle, iFileLength, ObjCount:Integer;
Objects:array of T3DObject;
function ReadChunk: Integer;
function ReadBuffer(var Buffer; Count:Integer):Integer;
procedure AddObject(ObjNr: Integer);
procedure Load3Data;
constructor Create;
destructor Destroy; override;
end;
type T3DModel = class(TObject)
private
ObjCount:Integer;
RootChunk:TChunk;
Objects:array of T3DObject;
public
constructor Create;
destructor Destroy; override;
procedure LoadFromFile(const FileName:string);
procedure Clone3Data;
procedure Draw;
end;
implementation
uses SysUtils, OpenGL;
constructor T3DObject.Create;
begin
inherited;
ObjectName:='';
PointCount:=0; FaceCount:=0;
p:=nil;
f:=nil;
end;
destructor T3DObject.Destroy;
begin
Finalize(p);
Finalize(f);
inherited;
end;
procedure T3Dobject.Draw;
var i:integer;
begin
for i:=0 to FaceCount-1 do begin
glBegin(GL_POLYGON);
glVertex3f(p[f[i].a].x,p[f[i].a].y,p[f[i].a].z);
glVertex3f(p[f[i].b].x,p[f[i].b].y,p[f[i].b].z);
glVertex3f(p[f[i].c].x,p[f[i].c].y,p[f[i].c].z);
glEnd();
end; end;
constructor TChunk.Create;
begin
inherited;
iFileHandle:=0; iFileLength:=0; iBytesReaded:=0; ObjCount:=0; ChunkLength:=0;
Id:=0;
Objects:=nil;
end;
destructor TChunk.Destroy;
begin
Finalize(Objects);
inherited;
end;
function TChunk.ReadChunk: Integer;
begin
iBytesReaded:=FileRead(iFileHandle, Id, 2);
iBytesReaded:=iBytesReaded + FileRead(iFileHandle, ChunkLength, 4);
Result:=iBytesReaded;
end;
function TChunk.ReadBuffer(var Buffer; Count: Integer): Integer;
begin
Result:=FileRead(iFileHandle, Buffer, Count);
iBytesReaded:=iBytesReaded + Result;
end;
function TChunk.ReadObjectString:String;
var //S:String;
C:Char;
i:integer;
SStr:ShortString;
begin
C:=#255; i:=0;
while (C<>#0) {and (i<=20)} do begin
iBytesReaded:=iBytesReaded+FileRead(iFileHandle, C, 1);
SStr[i+1]:=C;
Inc(i);
end;
SetLength(Result, I-1);
Move(SStr[1], Result[1], I-1);
end;
procedure TChunk.AddObject(ObjNr:Integer);
begin
SetLength(Objects,ObjNr);
Objects[ObjNr].Create;
end;
procedure TChunk.Load3Data;
var i,x: Integer;
begin
while (iBytesReaded < iFileLength) do begin
ReadChunk;
case Id of
$4D4D: begin
// MAIN CHUNK
// ShowMessage('Found $4D4D at: ' + IntToStr(iBytesReaded) + ' length: ' + IntToStr(ChunkLength));
end;
$3D3D: begin
// 3D EDITOR CHUNK
// ShowMessage('Found $3D3D at: ' + IntToStr(iBytesReaded) + ' length: ' + IntToStr(ChunkLength));
end;
$4000: begin
// OBJECT BLOCK
inc(ObjCount);
AddObject(ObjCount);
Objects[ObjCount].ObjectName:=ReadObjectString; // PROPERTY USE ???!!!
// ShowMessage(ObjectName);
end;
$4100: begin
// 3D Data Chunk (kb)
end;
$4110: begin // VERTICES LIST
with Objects[ObjCount] do begin
ReadBuffer(PointCount, 2);
SetLength(p,PointCount);
for i:=0 to PointCount-1 do begin
ReadBuffer(p[i].x,4);
ReadBuffer(p[i].y,4);
ReadBuffer(p[i].z,4);
end; end; end;
$4120: begin // FACES DESCRIPTION
with Objects[ObjCount] do begin
ReadBuffer(FaceCount, 2);
SetLength(f,FaceCount);
for i:=0 to FaceCount-1 do begin
ReadBuffer(f[i].a, 2);
ReadBuffer(f[i].b, 2);
ReadBuffer(f[i].c, 2);
ReadBuffer(x, 2);
end; end; end;
else
iBytesReaded:=FileSeek(iFileHandle,ChunkLength-6,1); end;
end; // while end;
end;
constructor T3DModel.Create;
begin
inherited;
ObjCount:=0;
//RootChunk:=nil;
Objects:=nil;
end;
destructor T3DModel.Destroy;
begin
Finalize(Objects);
inherited;
end;
procedure T3DModel.LoadFromFile(const FileName:string);
var iFileHandle, iFileLength: Integer;
begin
iFileHandle:=0; //iFileLength:=0;
try
iFileHandle := FileOpen(FileName, fmOpenRead);
finally
iFileLength := FileSeek(iFileHandle,0,2);
FileSeek(iFileHandle,0,0);
RootChunk:=TChunk.Create;
RootChunk.iFileHandle:=iFileHandle;
RootChunk.iFileLength:=iFileLength;
RootChunk.Load3Data;
Clone3Data;
RootChunk.Free;
RootChunk.Destroy;
//ShowMessage('RootChunk Destroyed Successfully');
FileClose(iFileHandle);
end;
end;
procedure T3DModel.Clone3Data;
var i,j:integer;
begin
ObjCount:=RootChunk.ObjCount;
SetLength(Objects,ObjCount);
for i:=1 to ObjCount do begin
Objects[i].Create;
with Objects[i] do begin
PointCount:=RootChunk.Objects[i].PointCount;
FaceCount:=RootChunk.Objects[i].FaceCount;
SetLength(p,Objects[i].PointCount);
SetLength(f,Objects[i].FaceCount);
ObjectName:=RootChunk.Objects[i].ObjectName;
for j:=0 to PointCount-1 do p[j]:= RootChunk.Objects[i].p[j];
for j:=0 to FaceCount-1 do f[j]:= RootChunk.Objects[i].f[j];
end;
end;
end;
procedure T3DModel.Draw;
var i:integer;
begin
for i:=1 to ObjCount do Objects[i].Draw;
end;
end.
===========================================================
===========================================================