⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dgtoolssave3ds.pas

📁 这是三D开发的一些源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  ClearData;
  if mFaceGroups <> nil then
  mFaceGroups.Free;
  mTexList.Free;
  mVerList.Free;
  mFacList.Free;
  mNorList.Free;
  mFObjList.Free;
  mObject:= nil;
  inherited Destroy;
end;

function TOXToolSave3DS.GetByte( Value: TColor; Shift: byte ): byte;
begin
  Result:= ( Value and ( $FF shl Shift ) ) shr Shift;
end;

Constructor TOXToolSave3DS.Create( cMesh: TGLBaseMesh );
begin
  FMesh:= cMesh;
  FMappingMode:= mmCylindric;//mmSpherical;//mmPlanar;
end;

procedure TOXToolSave3DS.SaveTo3DS( const FileName: string );
var
  ad: PChar;
  FS: TStream;
  TmpDecimal: char;
  xr,xg,xb: byte;
  FMObjList: TList;
  MaterialLib: TGLMaterialLibrary;
  procedure WinColorToBytes( cCol: TColor );
  begin
    xr:= GetByte( cCol, D_J );
    xg:= GetByte( cCol, D_I );
    xb:= GetByte( cCol, D_0 );
  end;
  procedure WriteColorToBytes;
  begin
    FS.WriteBuffer( xr, D_A );
    FS.WriteBuffer( xg, D_A );
    FS.WriteBuffer( xb, D_A );
  end;
  procedure PreScanMesh;
  var cc, ci, cb: integer;
  begin
    FMesh.StructureChanged;
    cc:= FMesh.MeshObjects.Count;
    SetLength( FMeshObject3DS, cc );
    for ci:= D_0 to cc -D_A do begin
      FMeshObject3DS[ci]:= T3DSMeshObject.Create( FMesh.MeshObjects[ci] );
      FMeshObject3DS[ci].mFObjList:= TList.Create;
      if ( FMesh.MeshObjects[ci].FaceGroups.Count > D_0 ) then begin
        SetLength( FMeshObject3DS[ci].mMaterial, FMesh.MeshObjects[ci].FaceGroups.Count );
        for cb:= D_0 to FMesh.MeshObjects[ci].FaceGroups.Count -D_A do begin
          FMeshObject3DS[ci].mMaterial[cb]:= T3DSMeshMaterial.Create( ci, FMeshObject3DS[ci], FMesh, FMesh.MeshObjects[ci].FaceGroups[cb] );
          FMeshObject3DS[ci].mFObjList.Add( FMeshObject3DS[ci].mMaterial[cb] );
        end;
      end;
      FMObjList.Add( FMeshObject3DS[ci] );
      if Assigned( FMesh.MaterialLibrary ) then
        MaterialLib:= FMesh.MaterialLibrary;
    end;
  end;
  procedure WriteChunkID( cW: integer; cID: word; cLength: Cardinal );
  var
    v: Cardinal;
  begin
    v:= D_C;
    case cW of
    D_0: begin
           FS.WriteBuffer( cID, D_B );
           FS.WriteBuffer( cLength, D_D );
         end;
    D_A: begin
           FS.WriteBuffer( cID, D_B );
           FS.WriteBuffer( cLength, D_D );
           FS.WriteBuffer( v, D_D );
         end;
       end;  
  end;
  var
    Mat: TMatrix;
    vPos: TVector3f;
    vEx1,vEx2: TVector3f;
    zero: word;
    h, k, o: integer;
    t, m: integer;
    MainLength: Cardinal;
    VersionLength: Cardinal;
    VerticesLength: Cardinal;
    MeshDataLength: Cardinal;
    MeshMatLength: Cardinal;
    MatrixLength: Cardinal;
    MeshBlock: Cardinal;
    MBTemp: Cardinal;
    dMesh: T3DSMeshObject;
    FaceGroup: TFaceGroup;
    TmpIntegerList: TIntegerList;
    FcCount: LongWord;
    TmpMat: T3DSMeshMaterial;
    TMat: TGLLibMaterial;
    mstr: string;
begin
  FMObjList:= TList.Create;
  zero:= D_0;
  VerticesLength:= D_0;
  MeshDataLength:= D_0;
  MBTemp:= D_0;
  FcCount:= D_0;
  mstr:= '';
  MeshBlock:= D_0;
  MeshMatLength:= D_0;
  MaterialLib:= nil;
  dMesh:= nil;
  MaterialLib:= nil;
  PreScanMesh;
  try
    FS:= CreateFileStream( FileName, fmCreate or fmOpenRead or fmOpenWrite );
    TmpDecimal:= DecimalSeparator;
    DecimalSeparator:= '.';
    VersionLength:= D_E + D_D;
    for t:= D_0 to FMObjList.Count -D_A do begin
      MeshBlock:= MeshBlock + D_E + FMeshObject3DS[t].NameLength + FMeshObject3DS[t].TriMeshLength;
      for m:= D_0 to FMesh.MeshObjects[t].FaceGroups.Count -D_A do begin
        if FMeshObject3DS[t].mMaterial[m].mMaterialMapName <> '' then begin
          MeshMatLength:= MeshMatLength + D_E +
          FMeshObject3DS[t].mMaterial[m].NameLength + D_E +
          FMeshObject3DS[t].mMaterial[m].AmbientLength +
          FMeshObject3DS[t].mMaterial[m].DiffuseLength +
          FMeshObject3DS[t].mMaterial[m].SpecularLength +
          D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapLength;
        end else begin
          MeshMatLength:= MeshMatLength + D_E +
          FMeshObject3DS[t].mMaterial[m].NameLength + D_E +
          FMeshObject3DS[t].mMaterial[m].AmbientLength +
          FMeshObject3DS[t].mMaterial[m].DiffuseLength +
          FMeshObject3DS[t].mMaterial[m].SpecularLength;
        end;
      end;
      if ( FMesh.MeshObjects[t].FaceGroups.Count > D_0 ) then
        MeshDataLength:= D_E + VersionLength + MeshBlock + MeshMatLength
      else
        MeshDataLength:= D_E + VersionLength + MeshBlock;
    end;
    MainLength:= D_E + VersionLength + MeshDataLength;
    LastChunk:= 'M3DMAGIC';
    WriteChunkID( D_0, M3DMAGIC, MainLength );
    LastChunk:= 'M3D_VERSION';
    WriteChunkID( D_A, M3D_VERSION, VersionLength );
    LastChunk:= 'MDATA';
    WriteChunkID( D_0, MDATA, MeshDataLength );
    LastChunk:= 'MESH_VERSION';
    WriteChunkID( D_A, MESH_VERSION, VersionLength );
    for t:= D_0 to FMObjList.Count -D_A do begin
      if ( FMesh.MeshObjects[t].FaceGroups.Count > D_0 ) then begin
        for m:= D_0 to FMesh.MeshObjects[t].FaceGroups.Count -D_A do begin
          TmpMat:= FMeshObject3DS[t].mMaterial[m];
          LastChunk:= 'MAT_ENTRY';
          if FMeshObject3DS[t].mMaterial[m].mMaterialMapName <> '' then begin
            WriteChunkID( D_0, MAT_ENTRY, D_E + FMeshObject3DS[t].mMaterial[m].NameLength + D_E +
                                                FMeshObject3DS[t].mMaterial[m].AmbientLength +
                                                FMeshObject3DS[t].mMaterial[m].DiffuseLength +
                                                FMeshObject3DS[t].mMaterial[m].SpecularLength +
                                                D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapLength )
          end else begin
            WriteChunkID( D_0, MAT_ENTRY, D_E + FMeshObject3DS[t].mMaterial[m].NameLength + D_E +
                                                FMeshObject3DS[t].mMaterial[m].AmbientLength +
                                                FMeshObject3DS[t].mMaterial[m].DiffuseLength +
                                                FMeshObject3DS[t].mMaterial[m].SpecularLength );
          end;
          LastChunk:= 'MAT_NAME';
          WriteChunkID( D_0, MAT_NAME, D_E + FMeshObject3DS[t].mMaterial[m].NameLength );
          GetMem( ad, TmpMat.NameLength );
          ad:= StrPCopy( ad, TmpMat.mName );
          FS.WriteBuffer( ad^, SizeOf( Char ) * TmpMat.NameLength );
          FreeMem( ad, TmpMat.NameLength );
          if MaterialLib <> nil then
            mstr:= FMesh.MeshObjects[t].FaceGroups[m].MaterialName;
          TMat:= MaterialLib.LibMaterialByName(mstr);
          if TMat <> nil then begin
            with TMat.Material.FrontProperties.Ambient do begin
                WinColorToBytes( AsWinColor );
                LastChunk:= 'MAT_AMBIENT';
                WriteChunkID( D_0, MAT_AMBIENT, FMeshObject3DS[t].mMaterial[m].AmbientLength );
                WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
                WriteColorToBytes;
            end;
            with TMat.Material.FrontProperties.Diffuse do begin
                WinColorToBytes( AsWinColor );
                LastChunk:= 'MAT_DIFFUSE';
                WriteChunkID( D_0, MAT_DIFFUSE, FMeshObject3DS[t].mMaterial[m].DiffuseLength );
                WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
                WriteColorToBytes;
            end;
            with TMat.Material.FrontProperties.Specular do begin
                WinColorToBytes( AsWinColor );
                LastChunk:= 'MAT_SPECULAR';
                WriteChunkID( D_0, MAT_SPECULAR, FMeshObject3DS[t].mMaterial[m].SpecularLength );
                WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
                WriteColorToBytes;
            end;
            if ( FMeshObject3DS[t].mMaterial[m].mMaterialMapName <> '' ) then begin
              LastChunk:= 'MAT_TEXMAP';
              WriteChunkID( D_0, MAT_TEXMAP, D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapLength );
              LastChunk:= 'MAT_MAPNAME';
              WriteChunkID( D_0, MAT_MAPNAME,D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              GetMem( ad, FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              ad:= StrPCopy( ad, FMeshObject3DS[t].mMaterial[m].mMaterialMapName );
              FS.WriteBuffer( ad^, SizeOf( Char ) * FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              FreeMem( ad, FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              //
              LastChunk:= 'MAT_MAP_USCALE';
              WriteChunkID( D_0, MAT_MAP_USCALE, FMeshObject3DS[t].mMaterial[m].MapUScaleLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mUScale, D_D );
              LastChunk:= 'MAT_MAP_VSCALE';
              WriteChunkID( D_0, MAT_MAP_VSCALE, FMeshObject3DS[t].mMaterial[m].MapVScaleLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mVScale, D_D );
              LastChunk:= 'MAT_MAP_UOFFSET';
              WriteChunkID( D_0, MAT_MAP_UOFFSET, FMeshObject3DS[t].mMaterial[m].MapUOFFSetLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mUOFFSet, D_D );
              LastChunk:= 'MAT_MAP_VOFFSET';
              WriteChunkID( D_0, MAT_MAP_VOFFSET, FMeshObject3DS[t].mMaterial[m].MapVOFFSetLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mVOFFSet, D_D );
            end;
          end else begin
            with FMesh.Material.FrontProperties.Ambient do begin
              WinColorToBytes( AsWinColor );
              LastChunk:= 'MAT_AMBIENT';
              WriteChunkID( D_0, MAT_AMBIENT, FMeshObject3DS[t].mMaterial[m].AmbientLength );
              WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
              WriteColorToBytes;
            end;
            with FMesh.Material.FrontProperties.Diffuse do begin
              WinColorToBytes( AsWinColor );
              LastChunk:= 'MAT_DIFFUSE';
              WriteChunkID( D_0, MAT_DIFFUSE, FMeshObject3DS[t].mMaterial[m].DiffuseLength );
              WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
              WriteColorToBytes;
            end;
            with FMesh.Material.FrontProperties.Specular do begin
              WinColorToBytes( AsWinColor );
              LastChunk:= 'MAT_SPECULAR';
              WriteChunkID( D_0, MAT_SPECULAR, FMeshObject3DS[t].mMaterial[m].SpecularLength );
              WriteChunkID( D_0, COLOR_24, FMeshObject3DS[t].mMaterial[m].Color24Length );
              WriteColorToBytes;
            end;
            if ( FMeshObject3DS[t].mMaterial[m].mMaterialMapName <> '' ) then begin
              LastChunk:= 'MAT_TEXMAP';
              WriteChunkID( D_0, MAT_TEXMAP, D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapLength );
              LastChunk:= 'MAT_MAPNAME';
              WriteChunkID( D_0, MAT_MAPNAME, D_E + FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              GetMem( ad, FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              ad:= StrPCopy( ad, FMeshObject3DS[t].mMaterial[m].mMaterialMapName );
              FS.WriteBuffer( ad^, SizeOf( Char ) * FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              FreeMem( ad, FMeshObject3DS[t].mMaterial[m].MaterialMapNameLength );
              //
              LastChunk:= 'MAT_MAP_USCALE';
              WriteChunkID( D_0, MAT_MAP_USCALE, FMeshObject3DS[t].mMaterial[m].MapUScaleLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mUScale, D_D );
              LastChunk:= 'MAT_MAP_VSCALE';
              WriteChunkID( D_0, MAT_MAP_VSCALE, FMeshObject3DS[t].mMaterial[m].MapVScaleLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mVScale, D_D );
              LastChunk:= 'MAT_MAP_UOFFSET';
              WriteChunkID( D_0, MAT_MAP_UOFFSET, FMeshObject3DS[t].mMaterial[m].MapUOFFSetLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mUOFFSet, D_D );
              LastChunk:= 'MAT_MAP_VOFFSET';
              WriteChunkID( D_0, MAT_MAP_VOFFSET, FMeshObject3DS[t].mMaterial[m].MapVOFFSetLength );
              FS.WriteBuffer( FMeshObject3DS[t].mMaterial[m].mVOFFSet, D_D );
            end;
          end;
        end;
      end;  
    end;
    for t:= D_0 to FMObjList.Count -D_A do begin
      LastChunk:= 'NAMED_OBJECT';
      WriteChunkID( D_0, NAMED_OBJECT, D_E + FMeshObject3DS[t].NameLength + FMeshObject3DS[t].TriMeshLength );
      GetMem( ad, FMeshObject3DS[t].NameLength );
      ad:= StrPCopy( ad, FMeshObject3DS[t].mName );
      FS.WriteBuffer( ad^, SizeOf( Char ) * FMeshObject3DS[t].NameLength );
      FreeMem( ad, FMeshObject3DS[t].NameLength );
      LastChunk:= 'N_TRI_OBJECT';
      WriteChunkID( D_0, N_TRI_OBJECT, FMeshObject3DS[t].TriMeshLength );
      LastChunk:= 'POINT_ARRAY';
      WriteChunkID( D_0, POINT_ARRAY, FMeshObject3DS[t].VerLength );
      FS.WriteBuffer( FMeshObject3DS[t].mVerList.Count, D_B );
      for o:= D_0 to FMeshObject3DS[t].mVerList.Count -D_A do begin
        FS.WriteBuffer( FMeshObject3DS[t].mVerList.List^[o][D_0], D_D );
        FS.WriteBuffer( FMeshObject3DS[t].mVerList.List^[o][D_A], D_D );
        FS.WriteBuffer( FMeshObject3DS[t].mVerList.List^[o][D_B], D_D );
      end;
      LastChunk:= 'TEX_VERTS';
      WriteChunkID( D_0, TEX_VERTS, FMeshObject3DS[t].TexLength );
      FS.WriteBuffer( FMeshObject3DS[t].mTexList.Count, D_B );
      for o:= D_0 to FMeshObject3DS[t].mTexList.Count -D_A do begin
        FS.WriteBuffer( FMeshObject3DS[t].mTexList.List^[o][D_0], D_D );
        FS.WriteBuffer( FMeshObject3DS[t].mTexList.List^[o][D_A], D_D );
      end;
      {FMesh.MeshObjects[t].GetExtents(vEx1,vEx2);
      Mat:= IdentityHmgMatrix;
      Mat[D_C]:= VectorMake(VectorLerp(vEx1,vEx2,0.5));
      LastChunk:= 'MESH_MATRIX';
      WriteChunkID( D_0, MESH_MATRIX, FMeshObject3DS[t].MatrixLength );
      FS.WriteBuffer( Mat[D_0], D_F );
      FS.WriteBuffer( Mat[D_A], D_F );
      FS.WriteBuffer( Mat[D_B], D_F );
      FS.WriteBuffer( Mat[D_C], D_F ); }
      //
      zero:= D_0;
      FcCount:= FMeshObject3DS[t].FCount;
      LastChunk:= 'FACE_ARRAY';
      WriteChunkID( D_0, FACE_ARRAY, FMeshObject3DS[t].FacLength );
      FS.WriteBuffer( FcCount,D_B );
      for o:= D_0 to FMeshObject3DS[t].mFaceGroups.Count -D_A do begin
        FaceGroup:= FMeshObject3DS[t].mFaceGroups[o];
        TmpIntegerList:= TFGVertexIndexList( FaceGroup ).VertexIndices;
        for k:= D_0 to ( TmpIntegerList.Count div D_C ) -D_A do begin
          FS.WriteBuffer( TmpIntegerList.List^[ k * D_C + D_0 ], D_B );
          FS.WriteBuffer( TmpIntegerList.List^[ k * D_C + D_A ], D_B );
          FS.WriteBuffer( TmpIntegerList.List^[ k * D_C + D_B ], D_B );
          FS.WriteBuffer( zero, D_B );
        end;
      end;
      for m:= D_0 to FMesh.MeshObjects[t].FaceGroups.Count -D_A do begin
        LastChunk:= 'MSH_MAT_GROUP';
        WriteChunkID( D_0, MSH_MAT_GROUP, FMeshObject3DS[t].mMaterial[m].MaterialFaceLength );
        GetMem( ad, FMeshObject3DS[t].mMaterial[m].NameLength );
        ad:= StrPCopy( ad, FMeshObject3DS[t].mMaterial[m].mName );
        FS.WriteBuffer( ad^, SizeOf( Char ) * FMeshObject3DS[t].mMaterial[m].NameLength );
        FreeMem( ad, FMeshObject3DS[t].mMaterial[m].NameLength );
        MBTemp:= FMeshObject3DS[t].FCount;
        FS.WriteBuffer( MBTemp, D_B );
        for o:= D_0 to MBTemp -D_A do begin
          k:= o;
          FS.WriteBuffer( k, D_B );
        end;
      end;
      LastChunk:= 'SMOOTH_GROUP';
      WriteChunkID( D_0, SMOOTH_GROUP, FMeshObject3DS[t].SmoothLength );
      for o:= D_0 to FMeshObject3DS[t].FCount -D_A do begin
        zero:= D_A;
        zero:= zero + D_C;
        FS.WriteBuffer( zero, D_D );
      end;
    end;
    {
    WriteMasterScaleChunk( FS, MASTER_SCALE );            // 0x0100
    WriteMatrixMeshChunk( FS, MESH_MATRIX );              // 0x4160
    //  MESH_TEXTURE_INFO = $4170;
    WriteEditorColorChunk( FS, MESH_COLOR );              // 0x4165  }
    for o := D_0 to FMObjList.Count -D_A do begin
      for k := D_0 to T3DSMeshObject( FMObjList.Items[o] ).mFObjList.Count -D_A do begin
        T3DSMeshMaterial( T3DSMeshObject( FMObjList.Items[o] ).mFObjList.Items[k] ).Free;
      end;
      T3DSMeshObject( FMObjList.Items[o] ).Free;
    end;
    FMObjList.Clear;
    FMObjList.Free;
    FS.Free;
    DecimalSeparator:= TmpDecimal;
  except
    on E: Exception do begin
      Messagebox( D_0, pchar( 'Error While Saving 3DS file!'+#13#13+'Last Processed File Segment: '+LastChunk+ #13+'Msg: '+E.Message )
      , '3DS Saving Error', MB_OK );
    end;
  end;
end;

Destructor TOXToolSave3DS.Destroy;
begin
  inherited Destroy;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -