#C:\Perl\bin\perl -w
$TRAHeader = "\013Rod'sTracer";
$curver    = 0x00010001;
#$curver    = 101;
%OBJID = ('obj_sphere',0,'light_omni',1,'viewport',2,'ambient',3,'obj_plane',4,
          'null',5,'camera',6,'tri_plane',7,'tri',8,'quad',9,'translate',10,
          'rotate',11,'scale',12);

%COLOR = ('R',0.5,'G',0.5,'B',0.5);
%SURFACE = ('Kd',0.6,'Ks',0.6,'Ns',3);
%AMB   = ('R',0.3,'G',0.2,'B',0.1);
#-------------------------------------------
@vertex = ();
@faces = ();
%procs = (
  0x3d3d => \&EDIT3DS,
  0x4000 => \&EDIT_OBJECT,
  0x4100 => \&OBJ_TRIMESH,
  0x4110 => \&TRI_VERTEXL,
  0x4120 => \&TRI_FACEL,
  0x4700 => \&OBJ_CAMERA
);
#-------------------------------------------
$C = 0;
$ObjName = "";
$CHUNK_MAIN     = 0;
$CHUNK          = 0;
$CLEN           = 0;
$POS            = 6;
$GLEN           = 0;

if (@ARGV < 1 ) 
{
  die  "Usage: 3ds2tra.pl <infile.3ds> [outfile.tra]\n";
}

if (!-f $ARGV[0])
{
  die "Error opening $ARGV[0]\n";
}

$INname =  $ARGV[0];
$ARGV[0] =~ /(.+)\../;
$OUTname = $1.'.tra';
if (defined $ARGV[1])
 {
   $OUTname = $ARGV[1] 
 }

open IN, "<$INname" ||
  die "Error opening $INname:$!\n";
binmode IN;
open OUT, ">$OUTname" ||
  die "Error opening $OUTname:$!\n";
binmode OUT;
print OUT $TRAHeader;
print OUT pack('L',$curver);
print OUT pack('C',$OBJID{'ambient'});
saveRGB(%AMB);

read IN, $C, 2;
$CHUNK_MAIN = unpack "S", $C;
($CHUNK_MAIN == 0x4d4d) || die "Not a 3ds file\n";
read IN, $C, 4;
$GLEN = unpack "L", $C;
printf "0x%x\n",$GLEN;
while (!eof(IN) && ($POS < $GLEN))
{
  (read(IN,$C,2)==2) || die "Unexpected EOF reading chunk\n";
  $CHUNK = unpack "S", $C;
  (read(IN,$C,4)==4)  || die "Unexpected EOF reading chunk lenght\n";
  $CLEN  = unpack "L", $C;
  die "Chunk size error" if $CLEN == 0;
  if ($procs{$CHUNK})
  {
   $POS += $procs{$CHUNK}->()+6;
  }
   else
  {
   $POS += $CLEN;
  }
  seek IN, $POS, SEEK_SET;
}

foreach $face (@faces)  
{
  print OUT pack("C",$OBJID{'tri'},1);
  saveVec($vertex[$face->{'v1'}]);
  saveVec($vertex[$face->{'v2'}]);
  saveVec($vertex[$face->{'v3'}]);
  saveRGB(%COLOR);
  saveSurf(%SURFACE);
}
@faces = ();
@vertex = ();


sub saveVec {
  my ($vec) = @_;
  print OUT pack("d3",$$vec{'X'},$$vec{'Y'},$$vec{'Z'});
};
sub saveRGB {
  my (%vec) = @_;
  print OUT pack("d3",$vec{'R'},$vec{'G'},$vec{'B'});
};

sub saveSurf {
  my (%vec) = @_;
  print OUT pack("d3",$vec{'Kd'},$vec{'Ks'},$vec{'Ns'});
};
sub saveDouble {
  my ($val) = @_;
  print OUT pack("d",$val);
};

sub EDIT3DS {
  print "Loading Edit\n";
  return 0;
}
sub EDIT_OBJECT {
  $ObjName = "";  
  {
   read (IN, $C, 1);
   last if $C eq "\0";
   $ObjName .= $C;
   redo;
  }
  print "Loaded $ObjName\n";
  return length($ObjName)+1;
}
sub OBJ_TRIMESH {
  print "Loading Trimesh ($ObjName)\n";
  foreach $face (@faces)  
  {
    print "writing !\n";
    print OUT pack("C",$OBJID{'tri'},1);
    saveVec($vertex[$face->{'v1'}]);
    saveVec($vertex[$face->{'v2'}]);
    saveVec($vertex[$face->{'v3'}]);
    saveRGB($COLOR);
    saveSurf($SURFACE);
  }
  @faces = ();
  @vertex = ();
  return 0;
}
sub TRI_VERTEXL {
  my ($count,$i);
  read IN,$C,2;
  $count = unpack "S", $C;
  print "Loading $count vertexes\n";
  for ($i=0;$i<$count;$i++)
  {
   read IN, $C ,4;
   $vertex[$i]->{'X'} = unpack "f", $C;
   read IN, $C ,4;
   $vertex[$i]->{'Z'} = unpack "f", $C;
   read IN, $C,4;
   $vertex[$i]->{'Y'} = unpack "f", $C;
  }
  return $count*12+2;
}
sub TRI_FACEL {
  my ($count,$i,$tmp);
  read IN,$C,2;
  $count = unpack "S", $C;
  print "Loading $count faces\n";
  for ($i=0;$i<$count;$i++)
  {
   read IN, $C ,2;
   $faces[$i]->{'v1'} = unpack "S",$C;
   read IN, $C ,2;
   $faces[$i]->{'v2'} = unpack "S",$C;
   read IN, $C ,2;
   $faces[$i]->{'v3'} = unpack "S",$C;
   read IN,$tmp,2
  }
  return $count*8+2;
}

sub OBJ_CAMERA {
  my (%org,%targ,$roll,$fov,$xtoy);
  $xtoy = 1;
  print "Loading Camera ($ObjName)\n";
   read IN, $C ,4;
   $org{'X'} = unpack "f", $C;
   read IN, $C ,4;
   $org{'Z'} = unpack "f", $C;
   read IN, $C,4;
   $org{'Y'} = unpack "f", $C;
  print "Origin - $org{'X'}:$org{'Y'}:$org{'Z'}\n";
   read IN, $C ,4;
   $targ{'X'} = unpack "f", $C;
   read IN, $C ,4;
   $targ{'Z'} = unpack "f", $C;
   read IN, $C,4;
   $targ{'Y'} = unpack "f", $C;
  print "Target - $targ{'X'}:$targ{'Y'}:$targ{'Z'}\n";
   read IN, $C ,4;
   $roll = unpack "f", $C;
   read IN, $C ,4;
   $fov  = unpack "f", $C;
  print "Roll,Fov - $roll,$fov\n";
#----------------------------------
  print OUT pack "C", $OBJID{'camera'};
  saveVec(\%org);
  saveVec(\%targ);
  saveDouble($roll);
  saveDouble($fov);
  saveDouble($xtoy);
  return 32;
}