📄 dgtoolssave3ds.pas
字号:
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 + -