LZScene

Форк
0
/
GLFileB3D.pas 
342 строки · 11.6 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  B3D VectorFile class to load Blitz 3D model files
6

7
   History :
8
   10/11/12 - PW - Added CPP compatibility: changed vector arrays to records
9
   22/01/10 - Yar - Added GLVectorTypes to uses
10
   22/01/10 - Yar - Added GLTextureFormat to uses
11
   22/12/05 - Mathx - Added to the GLScene Project.
12

13
}
14
unit GLFileB3D;
15

16
interface
17

18
uses
19
  Classes, SysUtils,
20
   
21
  GLVectorFileObjects, GLApplicationFileIO, GLTexture, GLTextureFormat,
22
  GLMaterial, GLVectorTypes, GLVectorGeometry, GLVectorLists,
23

24
  FileB3D;
25

26
type
27
  TGLB3DVectorFile = class(TGLVectorFile)
28
  public
29
    class function Capabilities: TGLDataFileCapabilities; override;
30
    procedure LoadFromStream(AStream: TStream); override;
31
  end;
32

33
implementation
34

35
// ------------------------------ TGLB3DVectorFile ------------------------------
36
// Capabilities
37

38
class function TGLB3DVectorFile.Capabilities: TGLDataFileCapabilities;
39
begin
40
  Result := [DfcRead];
41
end;
42

43
// LoadFromStream
44

45
procedure TGLB3DVectorFile.LoadFromStream(AStream: TStream);
46

47
var
48
  B3d: TFileB3D;
49
  S: string;
50
  Mo: TGLMeshObject;
51
  I, J: Integer;
52
  FaceGroup: TFGVertexIndexList;
53
  // lightmapBmp : TGLBitmap;
54
  Node: PNODEChunk;
55
  B3DMat: TB3DMaterial;
56
  B3DTex: TB3DTexture;
57
  B3DLightTex: TB3DTexture;
58
  Vertex: PVertexData;
59
  Triangles: PTRISChunk;
60
  V, V1: TAffineVector;
61
  Matrix: TMatrix;
62
  MatLib: TGLMaterialLibrary;
63
  LightLib: TGLMaterialLibrary;
64
  RotQuat: TQuaternion;
65
  RotMat: TMatrix;
66

67
  function GetOrAllocateMaterial(MaterialNum: Integer; AMat: TB3DMaterial;
68
    ATex: TB3DTexture; ALightmap: TB3DTexture): string;
69
  var
70
    LibMat: TGLLibMaterial;
71
    TexName: string;
72
    LightName: string;
73
  begin
74
    if GetOwner is TGLBaseMesh then
75
    begin
76
      MatLib := TGLBaseMesh(GetOwner).MaterialLibrary;
77
      LightLib := TGLBaseMesh(GetOwner).LightmapLibrary;
78
      // got a linked material library?
79
      if Assigned(MatLib) then
80
      begin
81
        Result := AMat.GetMaterialName;
82
        // add base material
83
        LibMat := MatLib.Materials.GetLibMaterialByName(Result);
84
        if not Assigned(LibMat) then
85
        begin
86
          if Assigned(ATex) then
87
            TexName := ATex.GetTextureName
88
          else
89
            TexName := '';
90

91
          if not FileExists(TexName) then
92
            TexName := ExtractFileName(TexName);
93
          if TexName <> '' then
94
            LibMat := MatLib.AddTextureMaterial(Result + IntToStr(MaterialNum),
95
              TexName, False)
96
          else
97
          begin
98
            LibMat := MatLib.Materials.Add;
99
            LibMat.Name := Result + IntToStr(MaterialNum);
100
          end;
101

102
          Libmat.Material.FrontProperties.Diffuse.Red := AMat.MaterialData.Red;
103
          Libmat.Material.FrontProperties.Diffuse.Green :=
104
            AMat.MaterialData.Green;
105
          Libmat.Material.FrontProperties.Diffuse.Blue :=
106
            AMat.MaterialData.Blue;
107
          Libmat.Material.FrontProperties.Diffuse.Alpha :=
108
            AMat.MaterialData.Alpha;
109
          Libmat.Material.FrontProperties.Shininess :=
110
            Round(AMat.MaterialData.Shininess * 100.0);
111
          Libmat.Material.MaterialOptions := [MoNoLighting];
112

113
          if AMat.MaterialData.Alpha <> 1 then
114
          begin
115
            Libmat.Material.FaceCulling := FcNoCull;
116
            Libmat.Material.BlendingMode := BmTransparency;
117
          end;
118

119
          if Assigned(ATex) then
120
          begin
121

122
            LibMat.TextureOffset.AsAffineVector :=
123
              AffineVectorMake(ATex.TextureData.X_pos,
124
              ATex.TextureData.Y_pos, 0);
125

126
            LibMat.TextureScale.AsAffineVector :=
127
              AffineVectorMake(ATex.TextureData.X_scale,
128
              ATex.TextureData.Y_scale, 1);
129

130
            if ATex.TextureData.Flags = 2 then
131
            begin
132
              Libmat.Material.FaceCulling := FcNoCull;
133
              Libmat.Material.BlendingMode := BmTransparency;
134
            end;
135

136
            if AMat.MaterialData.Alpha <> 1 then
137
            begin
138
              Libmat.Material.Texture.ImageAlpha := TiaAlphaFromIntensity;
139
              Libmat.Material.Texture.TextureFormat := TfRGBA;
140
              Libmat.Material.Texture.TextureMode := TmModulate;
141
            end;
142

143
          end;
144
        end;
145
        // add lightmap material
146
        if (Assigned(LightLib)) and (Assigned(ALightmap)) then
147
        begin
148
          LightName := ALightmap.GetTextureName;
149
          // add base material
150
          LibMat := LightLib.Materials.GetLibMaterialByName(LightName
151
            { + IntToStr(MaterialNum) } );
152
          if not Assigned(LibMat) then
153
          begin
154
            if not FileExists(LightName) then
155
              LightName := ExtractFileName(LightName);
156

157
            LibMat := LightLib.AddTextureMaterial(LightName
158
              { + IntToStr(MaterialNum) } , LightName, False);
159
            LibMat.Material.Texture.TextureMode := TmReplace;
160
            if Assigned(ALightMap) then
161
            begin
162

163
              LibMat.TextureOffset.AsAffineVector :=
164
                AffineVectorMake(ALightMap.TextureData.X_pos,
165
                ALightMap.TextureData.Y_pos, 0);
166

167
              LibMat.TextureScale.AsAffineVector :=
168
                AffineVectorMake(ALightMap.TextureData.X_scale,
169
                ALightMap.TextureData.Y_scale, 1);
170
            end;
171
          end;
172
          // modify the material lightmap index
173
          AMat.MaterialData.Texture_id[1] := LibMat.Index;
174
        end;
175
      end
176
      else
177
        Result := '';
178
    end
179
    else
180
      Result := '';
181
  end;
182

183
begin
184
  B3d := TFileB3D.Create;
185
  try
186
    // first, load the b3d model sturctures from stream
187
    B3d.LoadFromStream(AStream);
188
    // then add all the materials and lightmaps from b3d structures
189
    for I := 0 to B3d.Materials.Count - 1 do
190
    begin
191
      B3DMat := TB3DMaterial(B3d.Materials.Objects[I]);
192
      B3DTex := nil;
193
      B3DLightTex := nil;
194
      // check if there is one texture layer
195
      if B3DMat.MaterialData.N_texs > 0 then
196
      begin
197
        if B3DMat.MaterialData.Texture_id[0] >= 0 then
198
          B3DTex := TB3DTexture(B3d.Textures.Objects
199
            [B3DMat.MaterialData.Texture_id[0]]);
200
        // check if there are two texture layer
201
        if B3DMat.MaterialData.N_texs > 1 then
202
          // why lightmap in some case on channel 2?
203
          if B3DMat.MaterialData.Texture_id[1] >= 0 then
204
            B3DLightTex :=
205
              TB3DTexture(B3d.Textures.Objects
206
              [B3DMat.MaterialData.Texture_id[1]])
207
          else
208
            { //check if there are three texture layer }
209
            if B3DMat.MaterialData.N_texs > 2 then
210
              if B3DMat.MaterialData.Texture_id[2] >= 0 then
211
                B3DLightTex :=
212
                  TB3DTexture(B3d.Textures.Objects
213
                  [B3DMat.MaterialData.Texture_id[2]]);
214
      end;
215
      GetOrAllocateMaterial(I, B3DMat, B3DTex, B3DLightTex);
216
    end;
217

218
    if GetOwner is TGLBaseMesh then
219
      (GetOwner as TGLBaseMesh).NormalsOrientation := MnoDefault;
220

221
    Node := B3d.Nodes.NodeData;
222
    while Node <> nil do
223
    begin
224
      if Node^.Meshes <> nil then
225
      begin
226
        Mo := TGLMeshObject.CreateOwned(Owner.MeshObjects);
227

228
        SetString(S, Node^.Name, Strlen(Node^.Name));
229
        // if Pos('16', s)>1 then
230
        // Pos('17', s);
231
        Mo.Name := S;
232
        Mo.Mode := MomFaceGroups;
233
        // add all the vertices, normals, colors and texture-coords(including the lightmap texture)
234
        Vertex := Node^.Meshes^.Vertices.Vertices;
235
        while Assigned(Vertex) do
236
        begin
237
          // W3D modif inversed z
238
          Mo.Vertices.Add(AffineVectorMake(Vertex^.Y, Vertex^.X, Vertex^.Z));
239
          if (Node^.Meshes^.Vertices.Flags and 1) > 0 then
240
            Mo.Normals.Add(VectorNormalize(AffineVectorMake(Vertex^.Ny,
241
              Vertex^.Nx, Vertex^.Nz)));
242

243
          if (Node^.Meshes^.Vertices.Flags and 2) > 0 then
244
          begin
245
            Mo.Colors.Add(VectorMake(Vertex^.Red, Vertex^.Green, Vertex^.Blue,
246
              Vertex^.Alpha));
247
          end;
248

249
          case Node^.Meshes^.Vertices.Tex_coord_sets of
250
            1:
251
              begin
252
                case Node^.Meshes^.Vertices.Tex_coord_set_size of
253
                  2:
254
                    Mo.TexCoords.Add(Vertex^.Tex_coords[0],
255
                      -Vertex^.Tex_coords[1], 0);
256
                  3:
257
                    Mo.TexCoords.Add(Vertex^.Tex_coords[0],
258
                      -Vertex^.Tex_coords[1], Vertex^.Tex_coords[2]);
259
                end;
260
              end;
261
            2: // lightmap tex_coord included
262
              begin
263
                case Node^.Meshes^.Vertices.Tex_coord_set_size of
264
                  2:
265
                    Mo.TexCoords.Add(Vertex^.Tex_coords[0],
266
                      -Vertex^.Tex_coords[1], 0);
267
                  3:
268
                    Mo.TexCoords.Add(Vertex^.Tex_coords[0],
269
                      -Vertex^.Tex_coords[1], Vertex^.Tex_coords[2]);
270
                end;
271
                Mo.LightMapTexCoords.Add
272
                  (Vertex^.Tex_coords
273
                  [Node^.Meshes^.Vertices.Tex_coord_set_size],
274
                  -Vertex^.Tex_coords
275
                  [Node^.Meshes^.Vertices.Tex_coord_set_size + 1]);
276
              end;
277
          end;
278
          Vertex := Vertex^.Next;
279
        end;
280
        // add facegroups
281
        Triangles := Node^.Meshes^.Triangles;
282
        while Assigned(Triangles) do
283
        begin
284
          FaceGroup := TFGVertexIndexList.CreateOwned(Mo.FaceGroups);
285
          if Triangles^.Brush_id >= 0 then
286
          begin
287
            FaceGroup.MaterialName := B3d.Materials[Triangles^.Brush_id] +
288
              InttoStr(Triangles^.Brush_id);
289
            FaceGroup.LightMapIndex :=
290
              TB3DMaterial(B3d.Materials.Objects[Triangles^.Brush_id])
291
              .MaterialData.Texture_id[1];
292
          end
293
          else
294
          begin
295
            FaceGroup.MaterialName := '';
296
            FaceGroup.LightMapIndex := -1;
297
          end;
298
          for J := 0 to Length(Triangles^.Vertex_id) - 1 do
299
            FaceGroup.VertexIndices.Add(Triangles^.Vertex_id[J]);
300
          while FaceGroup.VertexIndices.Count mod 3 <> 0 do
301
            FaceGroup.VertexIndices.Delete(FaceGroup.VertexIndices.Count - 1);
302
          Triangles := Triangles.Next;
303
          FaceGroup.Reverse;
304

305
        end;
306

307
        RotQuat := QuaternionMake([Node^.Rotation.V[2], Node^.Rotation.V[1],
308
          Node^.Rotation.V[3]], Node^.Rotation.V[0]);
309
        RotMat := QuaternionToMatrix(RotQuat);
310
        Mo.Vertices.TransformAsVectors(RotMat);
311

312
        { mo.SetPosition( Node^.Position[1], Node^.Position[0], Node^.Position[2]);
313
          mo.SetScale( Node^.Scale[1], Node^.Scale[0], Node^.Scale[2]);
314
        }
315
        if Pos('ENT_', UpperCase(Mo.Name)) = 0 then
316
          V := AffineVectorMake(Node^.Position.V[1],
317
            Node^.Position.V[0], Node^.Position.V[2])
318
        else
319
        begin
320
          V := AffineVectorMake(0.0, 0.0, 0.0);
321
        end;
322

323
        V1 := AffineVectorMake(Node^.Scale.V[1], Node^.Scale.V[0], Node^.Scale.V[2]);
324
        Matrix := CreateScaleAndTranslationMatrix(VectorMake(V1), VectorMake(V));
325
        Mo.Vertices.TransformAsPoints(Matrix);
326
      end;
327
      Node := Node^.Next;
328
    end;
329
  finally
330
    B3d.Free;
331
  end;
332
end;
333

334
initialization
335

336
// ------------------------------------------------------------------
337
// ------------------------------------------------------------------
338
// ------------------------------------------------------------------
339

340
RegisterVectorFileFormat('b3d', 'Blitz 3D model files', TGLB3DVectorFile);
341

342
end.
343

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

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

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

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