Rtm Binarised File Format: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - " (\=+)([a-zA-Z0-9][^ ]+[a-zA-Z0-9])(\=+) " to " $1 $2 $3 ")
(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{unsupported-doc}}
{{Feature|UnsupportedDoc}}




==UnBinarised Format==
= UnBinarised Format =


Binarised rtm was introduced for the Arma2 engine. For unbinarised see [[Rtm (Animation) File Format]]
For unbinarised see [[Rtm (Animation) File Format]]


==Structure==
= Binarised format =
 
Binarised rtm was introduced for the Arma2 engine.
 
There are currently three versions.
 
version 3: Arma2 family, some found in Arma3 files too
version 4: Arma3
version 5: Arma3 (1024 byte compression rule changed to prefixed flag)
 
== Structure ==
  RTMB
  RTMB
  {
  {
Line 17: Line 27:
   ulong            NoOfBones;            // 128 eg
   ulong            NoOfBones;            // 128 eg
   Asciiz          BoneNames[NoOfBones]; // "weapon\0\rightarm\leftarm\etc..."
   Asciiz          BoneNames[NoOfBones]; // "weapon\0\rightarm\leftarm\etc..."
   CompressedFloats FrameTimes;
   if (Version >= 4)
   CompressedFrames Frames[nFrames];
  {
      ulong        Zero;            // probably count and structure
      ulong nFrameProperties;
      FrameProperty FrameProperties[nFrameProperties];
  }
  FrameTimes      FrameTimes;           // CompressedFloats
   FramePosition    FramePositions[nFrames];// CompressedFrames
  }
  }


BoneNames are the traditional Bis catenated strings. One after the other separated by '\0'. Unlike most others encountered in Bis file architecture, there is no final terminating double null because the count is already known.
BoneNames are the traditional Bis catenated strings. One after the other separated by '\0'. Unlike most others encountered in Bis file architecture, there is no final terminating double null because the count is already known.


==RTMBHeader==
== RTMBHeader ==
  RTMBHeader
  RTMBHeader
  {
  {
   char[4]      Type;          //"BMTR"  
   char[4]      Type;          //"BMTR"  
   ulong        Version;      // =3
   ulong        Version;      // 3==A2, 4,5==A3
  }
  }
==CompressedFloats==
== FrameTimes (compressed) ==


  CompressedFloats
  FrameTimes
  {
  {
   ulong nFrameTimes;          // should always be same as nFrames
   ulong nFrameTimes;          // should always be same as nFrames
Line 37: Line 53:
  }
  }


This is the traditional Bis potentially compressed structure, where, if, the total bytes stored >=1024, the array is compressed (in lzo format)
This is the traditional Bis potentially-compressed lzo structure, where, if, the total bytes stored >=1024, the array is compressed (in lzo format). All bones are 'held' in a position and orientation (specified by FramePosition) for the duration of that frametime period.


Version 5 files use the same new compression rule as Version 64 ODOL .P3D files; each compressed array is prefixed by:


==CompressedFrames==
  ulong elementCount;
  byte compressed; // 0 for not compressed, 2 for compressed


  CompressedFrames
== FramePosition (compressed) ==
 
FramePosition
  {
  {
   ulong  ThisFrameNoOfBones;              // Should always be same as nBones
   ulong  ThisFrameNoOfBones;              // Should always be same as nBones
   short  Transforms[ThisFrameNoOfBones][7];
   Transform  Transforms[ThisFrameNoOfBones];
}
}FramePositions[nFrames];
 
Each bone is held in this position and orientation for this frametime. ThisFrameNoOfBones is irrelevant to the engine and always must be the nBones value. It is present however because of efficiencies in using the standard bis lzo compression methods which rely on this 'count'.
 
Version 5 FramePosition's are optionally compressed with the same compression flag as FrameTimes.


The short values are compressed floats (7 in total) for each 'frame'
=== Transform ===
following information supplied by 'Voyager' to whom all honor and glory


conversion to float is
transform
{
  short  Qnion[4]; //compressed xyzw Rotation
  short  XYZ[3];// Compressed triplet
};


  float ShortToFloat(short value) {return ((float)1.0 / (65534)) * (value + 32767);}
  Quarternion(qX=Qnion[0]/16384,qY=Qnion[1]/16384,qZ=Qnion[2]/16384,qW=Qnion[3]/16384);
Triplet(X=Convert(XYZ[0],Y=Convert(XYZ[1],Z=Convert(XYZ[2]);


this is suspiciously similar to ofp compressed floats
double Convert(ushort value)
{
  double sign = ((value & 0x8000) != 0) ? -1 : 1;
  // S eeeee xxxxxxxxxx
  ushort exponent = (value & 0x7FFF) >> 10;//5bits
  double significand = (double)(value & 0x03FF) / (1 << 10);
  if (exponent == 0) {
    return (sign / 0x4000) * (0.0 + significand );
  }
  return sign * Pow(2, exponent - 15) * (1 + significand ); }
}


float = short * 0.045
=== Frame Properties ===


4 floats probably are used to describe a quaternion that describes the rotation. the other 3 floats are then for the translation
FrameProperty
{
    ulong always_0;
    asciiz kind; // "StepSound" in all current A3 files.
    float frame_time;
    asciiz unknown; // "" in all current A3 files.
};


[[category:Operation Flashpoint: Addons]]
{{GameCategory|ofp|Modelling}}
[[category:Operation Flashpoint: Modelling]]
[[Category:BIS_File_Formats]]
[[Category:BIS_File_Formats]]

Revision as of 16:37, 17 November 2021

bi symbol white.png
Disclaimer: This page describes internal undocumented structures of Bohemia Interactive software.

This page contains unofficial information.

Some usage of this information may constitute a violation of the rights of Bohemia Interactive and is in no way endorsed or recommended by Bohemia Interactive.
Bohemia Interactive is not willing to tolerate use of such tools if it contravenes any general licenses granted to end users of this community wiki or BI products.


UnBinarised Format

For unbinarised see Rtm (Animation) File Format

Binarised format

Binarised rtm was introduced for the Arma2 engine.

There are currently three versions.

version 3: Arma2 family, some found in Arma3 files too
version 4: Arma3
version 5: Arma3 (1024 byte compression rule changed to prefixed flag)

Structure

RTMB
{
  RTMBHeader       Header;
  byte             Always1;              // ??
  XYZTriplet       Displacement;
  ulong            nFrames;              // 55 eg
  ulong            Generally0;           // ??
  ulong            nBones;               // same value as NoOfBones
  ulong            NoOfBones;            // 128 eg
  Asciiz           BoneNames[NoOfBones]; // "weapon\0\rightarm\leftarm\etc..."
  if (Version >= 4)
  {
     ulong         Zero;            // probably count and structure
     ulong nFrameProperties;
     FrameProperty FrameProperties[nFrameProperties];
  }
  FrameTimes       FrameTimes;           // CompressedFloats
  FramePosition    FramePositions[nFrames];// CompressedFrames
}

BoneNames are the traditional Bis catenated strings. One after the other separated by '\0'. Unlike most others encountered in Bis file architecture, there is no final terminating double null because the count is already known.

RTMBHeader

RTMBHeader
{
 char[4]       Type;          //"BMTR" 
 ulong         Version;       // 3==A2, 4,5==A3
}

FrameTimes (compressed)

FrameTimes
{
 ulong nFrameTimes;          // should always be same as nFrames
 float Array[nFrameTimes];
}

This is the traditional Bis potentially-compressed lzo structure, where, if, the total bytes stored >=1024, the array is compressed (in lzo format). All bones are 'held' in a position and orientation (specified by FramePosition) for the duration of that frametime period.

Version 5 files use the same new compression rule as Version 64 ODOL .P3D files; each compressed array is prefixed by:

 ulong elementCount;
 byte compressed; // 0 for not compressed, 2 for compressed

FramePosition (compressed)

FramePosition
{
 ulong   ThisFrameNoOfBones;               // Should always be same as nBones
 Transform  Transforms[ThisFrameNoOfBones];
}FramePositions[nFrames];

Each bone is held in this position and orientation for this frametime. ThisFrameNoOfBones is irrelevant to the engine and always must be the nBones value. It is present however because of efficiencies in using the standard bis lzo compression methods which rely on this 'count'.

Version 5 FramePosition's are optionally compressed with the same compression flag as FrameTimes.

Transform

following information supplied by 'Voyager' to whom all honor and glory

transform
{
  short  Qnion[4]; //compressed xyzw Rotation
  short  XYZ[3];// Compressed triplet
};
Quarternion(qX=Qnion[0]/16384,qY=Qnion[1]/16384,qZ=Qnion[2]/16384,qW=Qnion[3]/16384);

Triplet(X=Convert(XYZ[0],Y=Convert(XYZ[1],Z=Convert(XYZ[2]);
double Convert(ushort value)
{
 double sign = ((value & 0x8000) != 0) ? -1 : 1;
 // S eeeee xxxxxxxxxx
 ushort exponent = (value & 0x7FFF) >> 10;//5bits
 double significand = (double)(value & 0x03FF) / (1 << 10);
 if (exponent == 0) {
   return (sign / 0x4000) * (0.0 + significand );
 }
 return sign * Pow(2, exponent - 15) * (1 + significand ); }
}

Frame Properties

FrameProperty
{
   ulong always_0;
   asciiz kind; // "StepSound" in all current A3 files.
   float frame_time;
   asciiz unknown; // "" in all current A3 files.
};