-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathmz3.pas
183 lines (173 loc) · 5.3 KB
/
mz3.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
unit mz3;
{$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF}
interface
//load and save meshes in Surfice MZ3 format
uses
zstream, Classes, sysutils, meshify_simplify_quadric;
procedure LoadMz3(const FileName: string; var faces: TFaces; var vertices: TVertices);
procedure SaveMz3(const FileName: string; var faces: TFaces; var vertices: TVertices);
implementation
type
TRGBA = packed record //Next: analyze Format Header structure
R,G,B,A : byte;
end;
TFloats = array of single;
TVertexRGBA = array of TRGBA;
function FSize (lFName: String): longint;
var F : File Of byte;
begin
result := 0;
if not fileexists(lFName) then exit;
Assign (F, lFName);
Reset (F);
result := FileSize(F);
Close (F);
end; // FSize()
function LoadMz3Core(const FileName: string; var Faces: TFaces; var Vertices: TVertices; var vertexRGBA: TVertexRGBA; var intensity: TFloats): boolean;
const
kMagic = 23117; //"MZ"
kChunkSize = 16384;
label 666;
var
i: integer;
bytes : array of byte;
Magic, Attr: uint16;
nFace, nVert, nSkip: uint32;
isFace, isVert, isRGBA, isScalar: boolean;
mStream : TMemoryStream;
zStream: TGZFileStream;
begin
result := false;
setlength(Faces,0);
setlength(Vertices,0);
setlength(vertexRGBA,0);
setlength(intensity,0);
if not fileexists(Filename) then exit;
mStream := TMemoryStream.Create;
zStream := TGZFileStream.create(FileName, gzopenread);
setlength(bytes, kChunkSize);
repeat
i := zStream.read(bytes[0],kChunkSize);
mStream.Write(bytes[0],i) ;
until i < kChunkSize;
zStream.Free;
if mStream.Size < 72 then exit; //6 item header, 3 vertices (3 values, XYZ), 1 face (3 indices) each 4 bytes
mStream.Position := 0;
mStream.Read(Magic,2);
mStream.Read(Attr,2);
mStream.Read(nFace,4);
mStream.Read(nVert,4);
mStream.Read(nSkip,4);
if (magic <> kMagic) then goto 666;
isFace := (Attr and 1) > 0;
isVert := (Attr and 2) > 0;
isRGBA := (Attr and 4) > 0;
isScalar := (Attr and 8) > 0;
if (Attr > 15) then begin
writeln('Unsupported future format '+ inttostr(Attr));
goto 666;
end;
if (nFace = 0) and (isFace) then goto 666;
if (nVert = 0) and ((isVert) or (isRGBA) or (isScalar) ) then goto 666;
if nSkip > 0 then
mStream.Seek(nSkip, soFromCurrent);
result := true;
if isFace then begin
setlength(Faces, nFace);
mStream.Read(Faces[0], nFace * 3 * sizeof(int32));
end;
if isVert then begin
setlength(Vertices, nVert);
mStream.Read(Vertices[0], nVert * 3 * sizeof(single));
end;
if isRGBA then begin
setlength(vertexRGBA, nVert);
mStream.Read(vertexRGBA[0], nVert * 4 * sizeof(byte));
end;
if isScalar then begin
setlength(intensity, nVert);
mStream.Read(intensity[0], nVert * sizeof(single));
end;
result := true;
666 :
mStream.Free;
end; // LoadMz3Core()
procedure LoadMz3(const FileName: string; var faces: TFaces; var vertices: TVertices);
var
vertexRGBA: TVertexRGBA;
intensity: TFloats;
begin
LoadMz3Core(FileName, Faces, Vertices, vertexRGBA, intensity);
if length(vertexRGBA) > 0 then begin
writeln('Warning: ignoring vertex colors');
setlength(vertexRGBA, 0);
end;
if length(intensity) > 0 then begin
writeln('Warning: ignoring vertex intensities');
setlength(intensity, 0);
end;
end; // LoadMz3()
procedure SaveMz3Core(const FileName: string; Faces: TFaces; Vertices: TVertices; vertexRGBA: TVertexRGBA; intensity: TFloats);
const
kMagic = 23117; //"MZ"
var
isFace, isVert, isRGBA, isScalar: boolean;
Magic, Attr: uint16;
nFace, nVert, nSkip: uint32;
mStream : TMemoryStream;
zStream: TGZFileStream;
FileNameMz3: string;
begin
nFace := length(Faces);
nVert := length(Vertices);
FileNameMz3 := changeFileExt(FileName, '.mz3');
isFace := nFace > 0;
isVert := nVert > 0;
isRGBA := false;
if length(vertexRGBA) > 0 then begin
isRGBA := true;
nVert := length(vertexRGBA);
end;
isScalar := false;
if length(intensity) > 0 then begin
isScalar := true;
nVert := length(intensity);
end;
if (nFace = 0) and (nVert = 0) then exit;
magic := kMagic;
Attr := 0;
if isFace then Attr := Attr + 1;
if isVert then Attr := Attr + 2;
if isRGBA then Attr := Attr + 4;
if isScalar then Attr := Attr + 8;
nSkip := 0; //do not pad header with any extra data
mStream := TMemoryStream.Create;
mStream.Write(Magic,2);
mStream.Write(Attr,2);
mStream.Write(nFace,4);
mStream.Write(nVert,4);
mStream.Write(nSkip,4);
if isFace then
mStream.Write(Faces[0], nFace * sizeof(TPoint3i));
if isVert then
mStream.Write(Vertices[0], nVert * 3 * sizeof(single));
if isRGBA then
mStream.Write(vertexRGBA[0], nVert * 4 * sizeof(byte));
if isScalar then
mStream.Write(intensity[0], nVert * sizeof(single));
mStream.Position := 0;
zStream := TGZFileStream.Create(FileNameMz3, gzopenwrite);
zStream.CopyFrom(mStream, mStream.Size);
zStream.Free;
mStream.Free;
end; // SaveMz3Core()
procedure SaveMz3(const FileName: string; var faces: TFaces; var vertices: TVertices);
var
vertexRGBA: TVertexRGBA;
intensity: TFloats;
begin
setlength(vertexRGBA, 0);
setlength(intensity,0);
SaveMz3Core(FileName, faces, vertices, vertexRGBA, intensity);
end; //SaveMz3()
end.