Im not sure what coding language this is done in, but what is does is convert a .ltb to a .x file. I need someone to reverse this and make it convert .x to ltb. Im going to attach the source code of the program and if anyone can make something it will be great. And btw this is send11
Code:
//------------------------------------------------------
//
// Ltb file class. (Loader only)
//
// TODO: Bones support; Animations support;
//
// This file is provided "as-is". Feel free to
// modify and redistribute. However be sure to
// keep this header intact.
//
// Compatibility: This file contains code that
// is compatible with Delphi Programming Language
// and may be compatible with classic Object Pascal.
//
// Compiler: Borland® Delphi® for Microsoft® Windows™
// Version 10.0.2288.42451. (Turbo Delphi)
//
// Credits: Cote-Duke.
//
//------------------------------------------------------
unit LtbFile;
interface
uses Contnrs, SysUtils;
const
LTB_OK = 0;
const
LTB_FAIL = 1;
const
//-----------------------------------------------
// Offsets.
//-----------------------------------------------
LTB_FILEOFFSET_COMLINELENGTH = 84; // Command line length description.
LTB_FILEOFFSET_MESHCOUNT = 86 + 8; // Mesh count description.
LTB_FILEOFFSET_FIRSTMESH = 86 + 12; // Beginning of the first mesh.
LTB_MESHOFFSET_VERTEXCOUNT = 49; // Vertex count.
LTB_MESHOFFSET_FACECOUNT = 53; // Face count.
LTB_MESHOFFSET_MESHTYPE_HEAD = 57; // Mesh header.
LTB_MESHOFFSET_MESHTYPE = 61; // Mesh type. 1 - not skinned;
// 2 - extra float;
// 4 & 3 - skinned;
LTB_MESHOFFSET_FIRSTVERTEX = 83; // First vertex in mesh.
LTB_MESHOFFSET_FIRSTVERTEX_DS = 85; // First vertex in mesh (not skinned).
//-----------------------------------------------
// Mesh type.
//-----------------------------------------------
LTB_MESHTYPE_NOTSKINNED = 1;
LTB_MESHTYPE_EXTRAFLOAT = 2;
LTB_MESHTYPE_SKINNED = 4;
LTB_MESHTYPE_SKINNEDALT = 3;
LTB_MESHTYPE_TWOEXTRAFLOAT = 5;
type
_LtbVector3 = record
x, y, z: Single;
end;
_LtbVertex = record
Position: _LtbVector3;
Normal : _LtbVector3;
Weights : _LtbVector3;
U, V : Single;
end;
_LtbVertices = array of _LtbVertex;
_LtbIndices = array of Word;
//-----------------------------------------------
// Ltb Mesh class.
//-----------------------------------------------
CLtb******sh = class
private
VertexCount: Word;
IndexCount: Word;
Vertices: _LtbVertices;
Indices: _LtbIndices;
MeshName: ShortString;
public
constructor Create( const MeshName: ShortString;
const VertexCount, IndexCount: Word;
const Vertices: _LtbVertices;
const Indices: _LtbIndices );
function GetMeshName( ): ShortString;
function GetVertices( out Vertices: _LtbVertices ): Word;
function GetIndices( out Indices: _LtbIndices ): Word;
destructor Destroy( ); override;
end;
//-----------------------------------------------
// Ltb File class.
//-----------------------------------------------
CLtbFile = class
private
MeshList: TObjectList;
CommandLine: String;
public
constructor Create( );
function GetMeshCount( ): Cardinal;
function GetMesh( const MeshIndex: Byte ): CLtb******sh;
function GetCommandLine( ): String;
function LoadFromFile( const LtbFileName: ShortString ): Byte;
destructor Destroy( ); override;
end;
implementation
//-----------------------------------------------
// Initialize mesh.
//-----------------------------------------------
constructor CLtb******sh.Create( const MeshName: ShortString;
const VertexCount, IndexCount: Word;
const Vertices: _LtbVertices;
const Indices: _LtbIndices );
begin
Self.MeshName := MeshName;
// Copy vertices.
Self.VertexCount := VertexCount;
SetLength( Self.Vertices, VertexCount );
Self.Vertices := Copy( Vertices, 0, VertexCount );
// Copy indices.
Self.IndexCount := IndexCount;
SetLength( Self.Vertices, IndexCount );
Self.Indices := Copy( Indices, 0, IndexCount );
end;
//-----------------------------------------------
// Get mesh name.
//-----------------------------------------------
function CLtb******sh.GetMeshName( ): ShortString;
begin
Result := MeshName;
end;
//-----------------------------------------------
// Get mesh vertices. Returns number of vertices.
//-----------------------------------------------
function CLtb******sh.GetVertices( out Vertices: _LtbVertices ): Word;
begin
Vertices := Self.Vertices;
Result := VertexCount;
end;
//-----------------------------------------------
// Get mesh indices. Returns number of indices.
//-----------------------------------------------
function CLtb******sh.GetIndices( out Indices: _LtbIndices ): Word;
begin
Indices := Self.Indices;
Result := IndexCount;
end;
//-----------------------------------------------
// Destroy mesh.
//-----------------------------------------------
destructor CLtb******sh.Destroy( );
begin
Vertices := nil;
Indices := nil;
end;
//-----------------------------------------------
// Initialize LTB file.
//-----------------------------------------------
constructor CLtbFile.Create( );
begin
MeshList := TObjectList.Create( );
end;
//-----------------------------------------------
// Get mesh count.
//-----------------------------------------------
function CLtbFile.GetMeshCount( ): Cardinal;
begin
Result := MeshLis*****unt;
end;
//-----------------------------------------------
// Get mesh by it's index.
//-----------------------------------------------
function CLtbFile.GetMesh( const MeshIndex: Byte ): CLtb******sh;
begin
if ( MeshIndex < MeshLis*****unt ) then
Result := CLtb******sh( MeshList[MeshIndex] )
else
Result := nil;
end;
//-----------------------------------------------
// Get command line.
//-----------------------------------------------
function CLtbFile.GetCommandLine( ): String;
begin
Result := CommandLine;
end;
//-----------------------------------------------
// Load peices (meshes) from a LTB file.
//-----------------------------------------------
function CLtbFile.LoadFromFile( const LtbFileName: ShortString ): Byte;
var
i, j : Integer;
_File: File;
BaseOffset: Cardinal; // Base reading offset.
GeoOffset : Integer;
SkipDataSize: Cardinal;
ByteDataA, ByteDataB, ByteDataC, ByteDataD: Byte;
WordData : Word;
CardData : Cardinal;
MeshCount : Cardinal;
MeshName: String;
VertexCount: Word;
IndexCount : Word;
Vertices : _LtbVertices;
Indices : _LtbIndices;
IncludeWeights: Boolean;
IncludePostData: Boolean;
SectionSize: Byte;
begin
Result := LTB_FAIL;
if ( not FileExists( LtbFileName ) ) then
Exit;
// Assign file.
AssignFile( _File, LtbFileName );
// Reset to file's start.
Reset( _File, 1 );
// Clear mesh list.
MeshList.Clear( );
// Reset base offset.
BaseOffset := 0;
// Read command line length.
Seek( _File, BaseOffset + LTB_FILEOFFSET_COMLINELENGTH );
BlockRead( _File, WordData, SizeOf( Word ) );
SetLength( CommandLine, WordData );
// Read command line.
BlockRead( _File, CommandLine[1], WordData );
// Read mesh count.
Seek( _File, BaseOffset + LTB_FILEOFFSET_MESHCOUNT + WordData );
BlockRead( _File, MeshCount, SizeOf( Cardinal ) );
// Seek for first mesh.
Seek( _File, BaseOffset + LTB_FILEOFFSET_FIRSTMESH + WordData );
for i := 0 to ( MeshCount - 1 ) do
begin
// Read mesh name length.
BlockRead( _File, WordData, SizeOf( Word ) );
SetLength( MeshName, WordData );
// Read mesh name.
BlockRead( _File, MeshName[1], WordData );
// Set new base offset.
BaseOffset := FilePos( _File );
// Read vertex count.
Seek( _File, BaseOffset + LTB_MESHOFFSET_VERTEXCOUNT );
BlockRead( _File, VertexCount, SizeOf( Word ) );
// Read face count.
Seek( _File, BaseOffset + LTB_MESHOFFSET_FACECOUNT );
BlockRead( _File, IndexCount, SizeOf( Word ) );
// Since LTB models store their face count, instead
// of index count, we need to multiply it by 3 (Each face - 3 indices).
IndexCount := IndexCount * 3;
// Resize vertices and indices arrays.
SetLength( Vertices, VertexCount );
SetLength( Indices, IndexCount );
// Look-up mesh type.
Seek( _File, BaseOffset + LTB_MESHOFFSET_MESHTYPE_HEAD );
BlockRead( _File, WordData, SizeOf( Word ) );
SkipDataSize := 0;
if ( not ( WordData = LTB_MESHTYPE_SKINNEDALT ) ) then
begin
Seek( _File, BaseOffset + LTB_MESHOFFSET_MESHTYPE );
BlockRead( _File, WordData, SizeOf( Word ) );
end
else
WordData := LTB_MESHTYPE_TWOEXTRAFLOAT;
IncludeWeights := False;
IncludePostData := False;
if ( WordData = LTB_MESHTYPE_NOTSKINNED ) then
begin
// Mesh type: Not skinned.
IncludeWeights := False;
IncludePostData := False;
end
else
if ( WordData = LTB_MESHTYPE_EXTRAFLOAT ) then
begin
// Mesh type: Extra float.
IncludeWeights := False;
IncludePostData := True;
SkipDataSize := SizeOf( Single );
end
else
if ( ( WordData = LTB_MESHTYPE_SKINNED ) or
( WordData = LTB_MESHTYPE_SKINNEDALT ) ) then
begin
// Mesh type: Skinned.
IncludeWeights := True;
IncludePostData := True;
end
else
if ( WordData = LTB_MESHTYPE_TWOEXTRAFLOAT ) then
begin
// Mesh type: Double extra float.
IncludeWeights := False;
IncludePostData := True;
SkipDataSize := SizeOf( Single ) * 2;
end;
Seek( _File, BaseOffset + LTB_MESHOFFSET_FIRSTVERTEX );
BlockRead( _File, ByteDataA, SizeOf( Byte ) );
Seek( _File, BaseOffset + LTB_MESHOFFSET_FIRSTVERTEX + 1 );
BlockRead( _File, ByteDataB, SizeOf( Byte ) );
Seek( _File, BaseOffset + LTB_MESHOFFSET_FIRSTVERTEX + 2 );
BlockRead( _File, ByteDataC, SizeOf( Byte ) );
Seek( _File, BaseOffset + LTB_MESHOFFSET_FIRSTVERTEX + 3 );
BlockRead( _File, ByteDataD, SizeOf( Byte ) );
if ( ( ByteDataA = 0 ) and ( ByteDataB = 0 ) and ( ByteDataC <> 0 ) and ( ByteDataD <> 0 ) ) then
GeoOffset := LTB_MESHOFFSET_FIRSTVERTEX_DS
else
GeoOffset := LTB_MESHOFFSET_FIRSTVERTEX;
// Seek to first vertex.
Seek( _File, BaseOffset + Cardinal( GeoOffset ) );
// Vertices.
for j := 0 to ( VertexCount - 1 ) do
begin
// Read position.
BlockRead( _File, Vertices[j].Position, SizeOf( _LtbVector3 ) );
if ( IncludeWeights ) then
// Read weights.
BlockRead( _File, Vertices[j].Weights, SizeOf( _LtbVector3 ) );
// Read normal.
BlockRead( _File, Vertices[j].Normal, SizeOf( _LtbVector3 ) );
Seek( _File, FilePos( _File ) + Integer( SkipDataSize ) );
// Read u.
BlockRead( _File, Vertices[j].u, SizeOf( Single ) );
// Read v.
BlockRead( _File, Vertices[j].v, SizeOf( Single ) );
end;
// Indices.
for j := 0 to ( IndexCount - 1 ) do
// Read index.
BlockRead( _File, Indices[j], SizeOf( Word ) );
// ** UNKNOWN BEGIN **
// Post-data.
if ( IncludePostData ) then
begin
// Read section count.
BlockRead( _File, CardData, SizeOf( Cardinal ) );
for j := 0 to ( CardData - 1 ) do
Seek( _File, FilePos( _File ) + 12 );
// Final section.
BlockRead( _File, SectionSize, SizeOf( Byte ) );
Seek( _File, FilePos( _File ) + SectionSize );
end
else
BlockRead( _File, WordData, SizeOf( Word ) );
// ** UNKNOWN END **
// Store mesh.
MeshList.Add( CLtb******sh.Create( MeshName, VertexCount, IndexCount,
Vertices, Indices ) );
end;
Vertices := nil;
Indices := nil;
// Close file, after we're done with it.
CloseFile( _File );
Result := LTB_OK;
end;
//-----------------------------------------------
// Destroy LTB file.
//-----------------------------------------------
destructor CLtbFile.Destroy( );
begin
MeshList.Free( );
end;
end.