C2ResImport.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:11k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  @Abstract(CAST II engine resources import unit)
  3.  (C) 2006 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  Unit contains resource import routines
  6. *)
  7. {$Include GDefines.inc}
  8. {$Include C2Defines.inc}
  9. unit C2ResImport;
  10. interface
  11. uses
  12.   TextFile, 
  13.   SysUtils,
  14.   BaseTypes, Basics, Base2D, Base3D, Resources,
  15.   Cast2, C2Types, C2Res, C2Visual, C2Materials;
  16. function LoadImage(FileName: BaseTypes.TFileName): TImageResource;
  17. function LoadOBJ(FileName: BaseTypes.TFileName; out VRes: TVerticesResource; out IRes: TIndicesResource; out TRes: TImageResource): Boolean;
  18. function ImportWavResource(FileName: BaseTypes.TFileName): TAudioResource;
  19. function LoadWav(FileName: BaseTypes.TFileName; var Data: Pointer; var Size: Cardinal; var Format: Integer): Boolean;
  20. function SaveWavHeader(Stream: TStream; Format, Size: Cardinal): Boolean;
  21. //function LoadMesh(FileName: BaseTypes.TFileName; Resources: TResourceManager; Actor: TActor; Scale: Single = 1; FromMax: Boolean = False; RecalcNormals: Boolean = False): Integer;
  22. implementation
  23. const ImportCapacityStep = 1;
  24. function LoadImage(FileName: BaseTypes.TFileName): TImageResource;
  25. var
  26.   Data: Pointer;
  27.   Palette: PPalette;
  28.   Stream: TFileStream;
  29.   LineSize: Integer;
  30.   Bpp: Integer;
  31.   PaletteSize: Cardinal;
  32.   PalRes: TPaletteResource;
  33.   TotalPixels: Integer;
  34.   Signature: array[0..2] of Char;
  35.   IDFHeader: TIDFHeader;
  36.   TempWidth, TempHeight: Integer;
  37.   procedure ReportError;
  38.   begin
  39.     {$IFDEF LOGGING} Log.Log('LoadImage: Error loading file "' + FileName + '"', lkError); {$ENDIF}
  40.     if Assigned(Data) then FreeMem(Data);
  41.     if Assigned(Palette) then FreeMem(Palette);
  42.     if Result <> nil then Result.Free; Result := nil;
  43.   end;
  44. begin
  45.   Result := nil;
  46.   Stream := TFileStream.Create(FileName);
  47.   if not Stream.ReadCheck(Signature, 3) then Exit;
  48.   if not Stream.Seek(0) then Exit;
  49.   Palette := nil; Data := nil;
  50.   if Signature = 'IDF' then begin
  51.     if not LoadIDF(Stream, IDFHeader, Data, TotalPixels) then begin
  52.       ReportError;
  53.       Exit;
  54.     end;  
  55.     Result        := TTextureResource.Create(nil);
  56.     Result.Format := IDFHeader.PixelFormat;
  57.     Result.SetDimensions(IDFHeader.Width, IDFHeader.Height);
  58.     Result.SetAllocated(Integer(TotalPixels) * GetBytesPerPixel(IDFHeader.PixelFormat), Data);
  59.     (Result as TTextureResource).Miplevels := IDFHeader.MipLevels;
  60.   end else begin
  61.     Result := TImageResource.Create(nil);
  62.     if not LoadBitmap(Stream, LineSize, TempWidth, TempHeight, BPP, PaletteSize, Palette, Data) then begin
  63.       ReportError;
  64.       Exit;
  65.     end;
  66.     case BPP of
  67.        8: Result.Format := pfP8;
  68.       24: Result.Format := pfB8G8R8;
  69.       32: Result.Format := pfA8R8G8B8;
  70.       else begin
  71.         {$IFDEF LOGGING} Log.Log('LoadImage: Invalid bits per pixel: ' + IntToStr(BPP), lkError); {$ENDIF}
  72.         ReportError;
  73.         Exit;
  74.       end;
  75.     end;
  76.     Result.SetDimensions(TempWidth, TempHeight);
  77.     Result.SetAllocated(Result.Height * LineSize, Data);
  78.   end;
  79.   Stream.Free;
  80.   Result.Name := Signature+'_'+GetFileName(FileName);
  81.   if (Result.Format <> pfP8) and (Result.Format <> pfA8P8) then begin
  82.     if Assigned(Palette) then FreeMem(Palette)
  83.   end else begin
  84.     PalRes := TPaletteResource.Create(nil);
  85.     PalRes.SetAllocated(PaletteSize*SizeOf(TPaletteItem), Palette);
  86.     PalRes.Name := 'Pal_'+GetFileName(FileName);
  87.     Result.AddChild(PalRes);
  88.     Result.PaletteResource := PalRes;
  89.   end;
  90. end;
  91. function ClearCR(s: string): string;
  92. begin
  93.   Result := s;
  94.   while (Result[Length(Result)] = #$A) or (Result[Length(Result)] = #$D) do Result := Copy(Result, 1, Length(Result)-1);
  95. end;
  96. function LoadOBJ(FileName: BaseTypes.TFileName; out VRes: TVerticesResource; out IRes: TIndicesResource; out TRes: TImageResource): Boolean;
  97. var
  98. //  F: TextFile;
  99.   FS: TFileStream;
  100.   SS: TAnsiStringStream;
  101.   p: Pointer;
  102.   S, S2: string;
  103.   i, j: Integer;
  104.   TextureFileName: BaseTypes.TFileName;
  105.   VertexSize: Integer;
  106.   TexOffset, NormOffset, DiffuseOffset, SpecularOffset: Word;
  107.   VCount, NCount, TCount, FCount, Curmaterial, MCount, GroupOffset: Integer;
  108. {$Include LoadObj.inc}
  109. begin
  110.   Result := False;
  111.   VRes := nil; IRes := nil; TRes := nil;
  112.   S := ExtractFileName(FileName);
  113.   S := Copy(S, 1, Length(S)-Length(ExtractFileExt(FileName)));
  114.   if not FileExists(FileName) then if not ErrorHandler(TFileError.Create('File "' + FileName + '" not found')) then Exit;
  115.   FS := TFileStream.Create(FileName);
  116.   GetMem(p, FS.Size);
  117.   FS.Read(p^, FS.Size);
  118.   SS := TAnsiStringStream.Create(p, FS.Size, #10);
  119.   FS.Free;
  120.   VCount := 0; NCount := 0; TCount := 0; FCount := 0; MCount := 0; CurMaterial := -1;
  121.   GroupOffset := 0;
  122. //  AssignFile(F, FileName); Reset(F);
  123.   while SS.Position < SS.Size do begin
  124.     SS.Readln(S);
  125.     S := Uppercase(Trim(S));
  126.     if (S <> '') and (S[1] <> '#') then begin
  127.       if S <> '' then while S[Length(s)] = '' do begin
  128.         SS.Readln(S2);
  129.         S2 := Uppercase(Trim(S2));
  130.         S := Copy(S, 1, Length(S)-1) + ' ' + S2;
  131.       end;
  132.       case S[1] of
  133.         'G': GroupOffset := VCount;
  134.         'V': ReadVertexData(S);
  135.         'F': ReadFaceData(S);
  136.         'U': for i := 0 to MCount-1 do if MData[i].Name = ClearCR(Copy(S, 8, Length(S))) then CurMaterial := i;
  137.         'M': LoadMaterials(S);
  138.       end;
  139.     end;
  140.   end;
  141.   SS.Free;
  142.   
  143.   if VCount = 0 then begin
  144.     {$IFDEF LOGGING} Log.Log(Format('%S: No vertices found', ['LoadOBJ']), lkError); {$ENDIF}
  145.     Exit;
  146.   end;
  147.   if NCount = 0 then begin
  148.     {$IFDEF LOGGING} Log.Log(Format('%S: No normals found. Automatic calculation will apply', ['LoadOBJ']), lkWarning); {$ENDIF}
  149.     CalcNormals;
  150.   end;
  151.   if TCount = 0 then begin
  152.     TCount := 1; SetLength(TData, TCount);
  153.     TData[0] := GetVector3s(0, 0, 0);
  154.   end;
  155.   VRes := TVerticesResource.Create(nil);
  156.   VRes.Name          := 'VER_' + GetFileName(FileName);
  157.   VRes.Format        := GetVertexFormat(False, True, True, True, False, 0, [2]);
  158.   VertexSize         := GetVertexSize(VRes.Format);
  159.   VRes.Allocate(FCount*3 * VertexSize);
  160.   
  161.   NormOffset     := GetVertexElementOffset(VRes.Format, vfiNORM);
  162.   DiffuseOffset  := GetVertexElementOffset(VRes.Format, vfiDIFF);
  163.   SpecularOffset := GetVertexElementOffset(VRes.Format, vfiSPEC);
  164.   TexOffset      := GetVertexElementOffset(VRes.Format, vfiTEX0);
  165.   IRes := TIndicesResource.Create(nil);
  166.   IRes.Name          := 'IND_' + GetFileName(FileName);
  167.   IRes.Format        := IndexSize;
  168.   IRes.Allocate(FCount*3 * IndexSize);
  169.   for i := 0 to FCount-1 do for j := 0 to 2 do with FData[i][j] do begin
  170.     TVector3s((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize])^) := VData[V];
  171.     if M >= 0 then
  172.      Cardinal((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + DiffuseOffset])^) := Round(MData[M].Diffuse.X * 255) shl 16 + Round(MData[M].Diffuse.Y * 255) shl 8 + Round(MData[M].Diffuse.Z * 255) else
  173.       Cardinal((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + DiffuseOffset])^) := $80808080;
  174.     if M >= 0 then
  175.      Cardinal((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + SpecularOffset])^) := Round(MData[M].Specular.X * 255) shl 16 + Round(MData[M].Specular.Y * 255) shl 8 + Round(MData[M].Specular.Z * 255) else
  176.       Cardinal((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + SpecularOffset])^) := $80808080;
  177.     TVector3s((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + TexOffset])^).X := TData[T].X;
  178.     TVector3s((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + TexOffset])^).Y := TData[T].Y;
  179.     if N < NCount then TVector3s((@TByteBuffer(VRes.Data^)[(i*3+j)*VertexSize + NormOffset])^) := NData[N];
  180.     TWordBuffer(IRes.Data^)[i*3+j] := i*3+j;
  181.   end;
  182.   if TextureFileName <> '' then TRes := LoadImage(TextureFileName) else TRes := nil;
  183.   SetLength(VData, 0); SetLength(NData, 0); SetLength(TData, 0); SetLength(MData, 0); SetLength(FData, 0);
  184.   Result := True;
  185. end;
  186. type
  187.   TWaveFormat = packed record
  188.     FormatTag: Word;
  189.     Channels: Word;
  190.     SamplesPerSec: Longword;
  191.     AvgBytesPerSec: Longword;
  192.     BlockAlign: Word;
  193.   end;
  194.   TPCMWaveFormat = packed record
  195.     WaveFormat: TWaveFormat;
  196.     BitsPerSample: Word;
  197.   end;
  198.   TWFHeader = packed record
  199.     RIFFSign: TFileSignature;
  200.     FileLength: Longword;
  201.     WAVESign: TFileSignature;
  202.     FMTSign: TFileSignature;
  203.     FormatLength: Longword;
  204.     Format: TPCMWaveFormat;
  205.     DataSign: TFileSignature;
  206.     DataLength: Longword;
  207.   end;
  208. function ImportWavResource(FileName: BaseTypes.TFileName): TAudioResource;
  209. var Data: Pointer; Size: Cardinal; Format: Integer;
  210. begin
  211.   Result := TAudioResource.Create(nil);
  212.   if not LoadWav(FileName, Data, Size, Format) then Exit;
  213.   Result.Format := Format;
  214.   Result.SetAllocated(Size, Data);
  215.   Result.Name := 'WAV_' + GetFileName(FileName);
  216. end;
  217. function LoadWav(FileName: BaseTypes.TFileName; var Data: Pointer; var Size: Cardinal; var Format: Integer): Boolean;
  218. var F: file; WaveHeader: TWFHeader; BytesRead: Cardinal;
  219. begin
  220.   Result := False;
  221.   AssignFile(F, FileName); Reset(F, 1);
  222.   BlockRead(F, WaveHeader, SizeOf(WaveHeader), BytesRead);
  223.   if BytesRead <> SizeOf(WaveHeader) then Exit;
  224.   if WaveHeader.DataSign <> 'data' then WaveHeader.DataLength := FileSize(F)-SizeOf(WaveHeader);
  225.   Format := PackSoundFormat(WaveHeader.Format.WaveFormat.SamplesPerSec, WaveHeader.Format.BitsPerSample, WaveHeader.Format.WaveFormat.Channels);
  226.   GetMem(Data, WaveHeader.DataLength);
  227.   BlockRead(F, Data^, WaveHeader.DataLength, BytesRead);
  228.   Close(F);
  229.   Size := WaveHeader.DataLength;
  230.   Result := True;
  231. end;
  232. function SaveWavHeader(Stream: TStream; Format, Size: Cardinal): Boolean;
  233. var WaveHeader: TWFHeader;
  234. begin
  235.   Result := False;
  236.   WaveHeader.RIFFSign     := 'RIFF';
  237.   WaveHeader.FileLength   := Size + SizeOf(WaveHeader) - SizeOf(WaveHeader.RIFFSign) - SizeOf(WaveHeader.FileLength);
  238.   WaveHeader.WAVESign     := 'WAVE';
  239.   WaveHeader.FMTSign      := 'fmt ';
  240.   WaveHeader.FormatLength := SizeOf(WaveHeader.Format);
  241.   WaveHeader.Format.WaveFormat.FormatTag      := 1;                    // WAVE_FORMAT_PCM
  242.   WaveHeader.Format.WaveFormat.Channels       := UnpackSoundFormat(Format).Channels;
  243.   WaveHeader.Format.WaveFormat.SamplesPerSec  := UnpackSoundFormat(Format).SampleRate;
  244.   WaveHeader.Format.WaveFormat.AvgBytesPerSec := UnpackSoundFormat(Format).SampleRate * UnpackSoundFormat(Format).Channels * UnpackSoundFormat(Format).BitsPerSample div 8;
  245.   WaveHeader.Format.WaveFormat.BlockAlign     := UnpackSoundFormat(Format).Channels * UnpackSoundFormat(Format).BitsPerSample div 8;
  246.   WaveHeader.Format.BitsPerSample             := UnpackSoundFormat(Format).BitsPerSample;
  247.   WaveHeader.DataSign     := 'data';
  248.   WaveHeader.DataLength   := Size;
  249.   if not Stream.WriteCheck(WaveHeader, SizeOf(WaveHeader)) then Exit;
  250.   Result := True;
  251. end;
  252. end.