LZScene

Форк
0
/
FileGL2.pas 
360 строк · 11.5 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   Ghoul2 (GLM/GLA) file format loading structures
6

7
   Note:
8
	Also referred to as MDX (MDXM/MDXA) format in C source.
9

10
	 History : 
11
	    09/05/03 - SG - Fixed compressed bone pool
12
	    01/04/03 - SG - Finished GLM/GLA loading procedures
13
	    25/03/03 - SG - Creation
14
	 
15
}
16
unit FileGL2;
17

18
interface
19

20
uses
21
  Classes, GLVectorTypes, SysUtils, GLVectorGeometry;
22

23
type
24
  TGLMHeader = record
25
    fileID           : array[0..3] of char;
26
    version          : integer;
27
    strFile,
28
    animName         : array[0..63] of char;
29
    animIndex,
30
    numBones,
31
    numLODs,
32
    ofsLODs,
33
    numSurfaces,
34
    ofsSurfHierarchy,
35
    ofsEnd           : integer;
36
  end;
37

38
  TGLMSurfaceHeirachyOffsets = array of integer;
39

40
  TGLMSurfaceHeirachy = record
41
    name         : array[0..63] of Char;
42
    flags        : LongWord;
43
    shader       : array[0..63] of Char;
44
    shaderIndex,
45
    parentIndex,
46
    numChildren  : integer;
47
    childIndices : array of integer;
48
  end;
49

50
  TGLMSurfaceHeader = record
51
    ident,
52
    thisSurfaceIndex,
53
    ofsHeader,
54
    numVerts,
55
    ofsVerts,
56
    numTriangles,
57
    ofsTriangles,
58
    numBoneReferences,
59
    ofsBoneReferences,
60
    ofsEnd            : integer;
61
  end;
62

63
  TGLMTriangle = record
64
    indices : array[0..2] of integer;
65
  end;
66

67
  TGLMVertex = record
68
    normal,
69
    vertex                     : TVector3f;
70
    uiNumWeightsAndBoneIndices : Cardinal; // packed int
71
    BoneWeightings             : array[0..3] of Byte;
72
  end;
73

74
  TGLMSurface = record
75
    SurfaceHeader : TGLMSurfaceHeader;
76
    Triangles      : array of TGLMTriangle;
77
    Vertices       : array of TGLMVertex;
78
    TexCoords      : array of TVector2f;
79
    BoneReferences : array of Integer;
80
  end;
81

82
  TGLMLODInfo = record
83
    ofsEnd : integer;
84
  end;
85

86
  TGLMLODSurfaceOffsets = array of integer;
87

88
  TGLMLODs = record
89
    LODInfo           : TGLMLODInfo;
90
    LODSurfaceOffsets : TGLMLODSurfaceOffsets;
91
    Surfaces          : array of TGLMSurface;
92
  end;
93

94
  TGLAHeader = record
95
    fileID     : array[0..3] of char;
96
    version    : integer;
97
    Name       : array[0..63] of char;
98
    fScale     : single;
99
    numFrames,
100
    ofsFrames,
101
    numBones,
102
    ofsCompBonePool,
103
    ofsSkel,
104
    ofsEnd     : integer;
105
  end;
106

107
  TGLABone = array[0..2] of TVector4f;
108
  TGLACompQuatBone = array[0..6] of Word; {14 bytes}
109

110
  TGLASkeletonOffsets = array of integer;
111

112
  TGLASkeleton = record
113
    name           : array[0..63] of char;
114
    flags          : LongWord;
115
    parent         : Integer;
116
    BasePoseMat,
117
    BasePoseMatInv : TGLABone;
118
    numChildren    : Integer;
119
    children       : array of Integer;
120
  end;
121

122
  // Ghoul2 Model structure
123
  TFileGLM = class
124
    public
125
      ModelHeader            : TGLMHeader;
126
      SurfaceHeirachyOffsets : TGLMSurfaceHeirachyOffsets;
127
      SurfaceHeirachy        : array of TGLMSurfaceHeirachy;
128
      LODs                   : array of TGLMLODs;
129
      procedure LoadFromStream(aStream : TStream);
130
  end;
131

132
  // Ghoul2 Animation structure
133
  TFileGLA = class
134
    public
135
      AnimHeader      : TGLAHeader;
136
      SkeletonOffsets : TGLASkeletonOffsets;
137
      Skeleton        : array of TGLASkeleton;
138
      BoneIndices     : array of Integer;
139
      CompBonePool    : array of TGLACompQuatBone;
140
      function GetCompressedMatrix(Frame,Bone : Integer):TGLACompQuatBone;
141
      function GetUnCompressedMatrix(Frame,Bone : Integer):TMatrix;
142
      procedure LoadFromStream(aStream : TStream);
143
  end;
144

145
function G2_GetVertWeights(vert:TGLMVertex):Integer;
146
function G2_GetVertBoneIndex(vert:TGLMVertex; iWeightNum:Integer):Integer;
147
function G2_GetVertBoneWeight(vert:TGLMVertex; iWeightNum:Cardinal; 
148
  var fTotalWeight:Single; const iNumWeights:Cardinal):single;
149

150
procedure MC_UnCompressQuat(var mat : TMatrix; const comp : TGLACompQuatBone);
151

152
// ------------------------------------------------------------------
153
// ------------------------------------------------------------------
154
// ------------------------------------------------------------------
155
implementation
156
// ------------------------------------------------------------------
157
// ------------------------------------------------------------------
158
// ------------------------------------------------------------------
159

160
// ------------------
161
// ------------------ Misc routines ------------------
162
// ------------------
163

164
// Adapted from mdx_format.h
165
// static inline int G2_GetVertWeights( const mdxmVertex_t *pVert )
166
// static inline int G2_GetVertBoneIndex( const mdxmVertex_t *pVert, const int iWeightNum)
167
// static inline float G2_GetVertBoneWeight( const mdxmVertex_t *pVert, const int iWeightNum, float &fTotalWeight, int iNumWeights )
168

169
function G2_GetVertWeights(vert:TGLMVertex):Integer;
170
begin
171
  // Get number of bones per vertex (0..3)+1 = (1..4)
172
  result:=(vert.uiNumWeightsAndBoneIndices shr 30)+1;
173
end;
174

175
function G2_GetVertBoneIndex(vert:TGLMVertex; iWeightNum:Integer):Integer;
176
begin
177
  // Extract the bone reference array index, a 5-bit integer
178
  result:=(vert.uiNumWeightsAndBoneIndices shr (5*iWeightNum)) and 31;
179
end;
180

181
function G2_GetVertBoneWeight(vert:TGLMVertex; iWeightNum:Cardinal;
182
  var fTotalWeight:Single; const iNumWeights:Cardinal):single;
183
var
184
  fBoneWeight : Single;
185
  iTemp       : Cardinal;
186
begin
187
  if (iWeightNum = iNumWeights-1) then begin
188
    // No need to calculate final weight value, return the
189
    // weight left over out of 1
190
    fBoneWeight:=1-fTotalWeight;
191
  end else begin
192
    // Get the initial 8-bit bone weight
193
    iTemp:=vert.BoneWeightings[iWeightNum];
194
    // Get the 2-bit overflow and 'or' it to the front of the
195
    // weight to get 10-bit integer weight (0..1023)
196
    iTemp:=iTemp or ((vert.uiNumWeightsAndBoneIndices shr (12+(iWeightNum*2))) and $300);
197
    // Convert to floating point weight (0..1)
198
    fBoneWeight:=iTemp/1023;
199
    // Accumulate total weight
200
    fTotalWeight:=fTotalWeight+fBoneWeight;
201
  end;
202
  Result:=fBoneWeight;
203
end;
204

205
// Adapted from matcomp.c
206
// void MC_UnCompressQuat(float mat[3][4],const unsigned char * comp)
207

208
procedure MC_UnCompressQuat(var mat : TMatrix; const comp : TGLACompQuatBone);
209
begin
210
  mat:=QuaternionToMatrix(QuaternionMake([comp[1]-32726,comp[2]-32726,comp[3]-32726],comp[0]-32726));
211
  mat.V[3]:=VectorMake(comp[4]/64-512,comp[5]/64-512,comp[6]/64-512,1);
212
end;
213

214

215
// ------------------
216
// ------------------ TFileGLM ------------------
217
// ------------------
218

219
// LoadFromStream
220
//
221
procedure TFileGLM.LoadFromStream(aStream: TStream);
222
var
223
  idstr   : array[0..3] of char;
224
  i,j     : integer;
225
  ofs,
226
  LODofs  : int64;
227
begin
228
  aStream.Read(idstr,sizeof(idstr));
229
  aStream.Position:=0;
230

231
  if not (idstr='2LGM') then begin
232
    raise Exception.Create(Format('Unknown or incorrect identity tag: [%s]',[idstr]));
233
    exit;
234
  end;
235

236
  aStream.Read(ModelHeader,SizeOf(ModelHeader));
237

238
  if ModelHeader.version<>6 then
239
    raise Exception.Create(Format('Only GLM (MDXM) version 6 is supported. File is version %d.',[ModelHeader.version]));
240

241
  SetLength(SurfaceHeirachyOffsets,ModelHeader.numSurfaces);
242
  aStream.Read(SurfaceHeirachyOffsets[0],sizeof(Integer)*ModelHeader.numSurfaces);
243

244
  SetLength(SurfaceHeirachy,ModelHeader.numSurfaces);
245
  for i:=0 to ModelHeader.numSurfaces-1 do
246
  with SurfaceHeirachy[i] do begin
247
    aStream.Read(name,Length(name));
248
    aStream.Read(flags,sizeof(LongWord));
249
    aStream.Read(shader,Length(shader));
250
    aStream.Read(shaderindex,sizeof(Integer));
251
    aStream.Read(parentindex,sizeof(Integer));
252
    aStream.Read(numChildren,sizeof(Integer));
253
    if numChildren>0 then begin
254
      SetLength(childIndices,numChildren);
255
      aStream.Read(childIndices[0],numChildren*sizeof(Integer));
256
    end else SetLength(childIndices,0);
257
  end;
258

259
  SetLength(LODs,ModelHeader.numLODs);
260
  for i:=0 to ModelHeader.numLODs-1 do
261
  with LODs[i] do begin
262
    LODofs:=aStream.Position;
263
    aStream.Read(LODInfo,sizeof(LODInfo));
264
    SetLength(LODSurfaceOffsets,ModelHeader.numSurfaces);
265
    aStream.Read(LODSurfaceOffsets[0],sizeof(integer)*ModelHeader.numSurfaces);
266
    SetLength(Surfaces,ModelHeader.numSurfaces);
267
    for j:=0 to ModelHeader.numSurfaces-1 do
268
    with Surfaces[j] do begin
269
      ofs:=aStream.Position;
270
      aStream.Read(SurfaceHeader,SizeOf(TGLMSurfaceHeader));
271
      SetLength(Triangles,SurfaceHeader.numTriangles);
272
      SetLength(Vertices,SurfaceHeader.numVerts);
273
      SetLength(TexCoords,SurfaceHeader.numVerts);
274
      SetLength(BoneReferences,SurfaceHeader.numBoneReferences);
275
      aStream.Position:=ofs+SurfaceHeader.ofsTriangles;
276
      aStream.Read(Triangles[0],SurfaceHeader.numTriangles*SizeOf(TGLMTriangle));
277
      aStream.Position:=ofs+SurfaceHeader.ofsVerts;
278
      aStream.Read(Vertices[0],SurfaceHeader.numVerts*SizeOf(TGLMVertex));
279
      aStream.Read(TexCoords[0],SurfaceHeader.numVerts*SizeOf(TVector2f));
280
      aStream.Position:=ofs+SurfaceHeader.ofsBoneReferences;
281
      aStream.Read(BoneReferences[0],SurfaceHeader.numBoneReferences*SizeOf(Integer));
282
      aStream.Position:=ofs+SurfaceHeader.ofsEnd;
283
    end;
284
    aStream.Position:=LODofs+LODInfo.ofsEnd;
285
  end;
286
end;
287

288

289
// ------------------
290
// ------------------ TFileGLA ------------------
291
// ------------------
292

293
// GetCompressedMatrix
294
//
295
function TFileGLA.GetCompressedMatrix(Frame, Bone: Integer): TGLACompQuatBone;
296
begin
297
  Result:=CompBonePool[BoneIndices[Frame*AnimHeader.numBones+Bone]];
298
end;
299

300
// GetUnCompressedMatrix
301
//
302
function TFileGLA.GetUnCompressedMatrix(Frame, Bone: Integer): TMatrix;
303
begin
304
  MC_UnCompressQuat(Result,CompBonePool[BoneIndices[Frame*AnimHeader.numBones+Bone]]);
305
end;
306

307
// LoadFromStream
308
//
309
procedure TFileGLA.LoadFromStream(aStream: TStream);
310
var
311
  idstr  : array[0..3] of char;
312
  i,temp : integer;
313
  buf    : array of array[0..2] of Byte;
314
begin
315
  aStream.Read(idstr,sizeof(idstr));
316
  aStream.Position:=0;
317

318
  if not (idstr='2LGA') then begin
319
    raise Exception.Create(Format('Unknown or incorrect identity tag: [%s]',[idstr]));
320
    exit;
321
  end;
322

323
  aStream.Read(AnimHeader,SizeOf(AnimHeader));
324

325
  if AnimHeader.version<>6 then
326
    raise Exception.Create(Format('Only GLA (MDXA) version 6 is supported. File is version %d.',[AnimHeader.version]));
327

328
  SetLength(SkeletonOffsets,AnimHeader.numBones);
329
  aStream.Read(SkeletonOffsets[0],sizeof(Integer)*AnimHeader.numBones);
330

331
  SetLength(Skeleton,AnimHeader.numBones);
332
  for i:=0 to AnimHeader.numBones-1 do
333
  with Skeleton[i] do begin
334
    aStream.Read(name,Length(name));
335
    aStream.Read(flags,sizeof(LongWord));
336
    aStream.Read(Parent,SizeOf(Integer));
337
    aStream.Read(basePoseMat,sizeof(TGLABone));
338
    aStream.Read(basePoseMatInv,sizeof(TGLABone));
339
    aStream.Read(numChildren,sizeof(Integer));
340
    if numChildren>0 then begin
341
      SetLength(children,numChildren);
342
      aStream.Read(children[0],numChildren*sizeof(Integer));
343
    end else SetLength(children,0);
344
  end;
345

346
  aStream.Position:=AnimHeader.ofsFrames;
347
  SetLength(BoneIndices,AnimHeader.numFrames*AnimHeader.numBones);
348
  SetLength(buf,AnimHeader.numFrames*AnimHeader.numBones*3);
349
  aStream.Read(buf[0],AnimHeader.numFrames*AnimHeader.numBones*3);
350
  for i:=0 to AnimHeader.numFrames*AnimHeader.numBones-1 do
351
    BoneIndices[i]:=(buf[i][2] shl 16) or (buf[i][1] shl 8) or buf[i][0];
352
  SetLength(buf,0);
353

354
  aStream.Position:=AnimHeader.ofsCompBonePool;
355
  temp:=AnimHeader.ofsEnd-AnimHeader.ofsCompBonePool;
356
  SetLength(CompBonePool,temp div SizeOf(TGLACompQuatBone));
357
  aStream.Read(CompBonePool[0],temp);
358
end;
359

360
end.
361

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.