3 *aof2obj* is a script to convert Artlantis Object Format files to Wavefront
 
   4 OBJ; it can be used to have .aof files imported into 3D modeling programs
 
   5 such as blender (http://blender.org).
 
   7 Artlantis is a closed source 3D modeling and rendering software which can be
 
   8 found at http://www.artlantis.com/
 
  10 Artlantis Object Format is one of the formats produced by Artlantis.
 
  12 Wavefront OBJ is a very common format used to interchange data about 3D
 
  13 models, see https://en.wikipedia.org/wiki/Wavefront_.obj_file
 
  15 *aof2obj* requires the lxml python module.
 
  17 == Artlantis Object Format
 
  19 The Artlantis Object Format is based on XML, it provides information about the
 
  20 vertices of the model (<Points> element), the objects it is composed by,
 
  21 the faces of the objects (<Polygons> element), the materials and the setup
 
  22 for example rendering. The XML file also embeds a preview image
 
  23 (<Preview.Image> element) of the rendering result.
 
  25 Currently *aof2obj* supports only a small subset of these features, it was
 
  26 written only as a quick script hacked together to see what was inside some AOF
 
  27 files that can be found on the web.
 
  29 Notes that the resulting models may need to be rescaled to become visible in
 
  30 the viewport of the destination 3D program which will import the .obj files
 
  31 produced by this script.
 
  33 == Examples of .aof files
 
  35 Some sample files can be found starting from this page:
 
  37  - http://www.polantis.com/ikea/expedit-bookcase
 
  39 Having the same model in both .aof and .obj makes it a little easier to
 
  40 reverse engineer the .aof format, even if its structure is very
 
  41 straightforward already.
 
  43  - http://www.polantis.com/data/2/2/1093/formats/14/90/IKEA-Expedit_Bookcase-3d.aof
 
  44  - http://www.polantis.com/data/2/2/1093/formats/16/95/IKEA-Expedit_Bookcase-3d.obj
 
  46  - http://www.polantis.com/data/2/2/1094/formats/14/90/IKEA-Expedit_Bookcase_Black-3d.aof
 
  47  - http://www.polantis.com/data/2/2/1094/formats/16/95/IKEA-Expedit_Bookcase_Black-3d.obj
 
  51 *aof2obj* extracts also the Artlantis Preview Files embedded into the Artlantis
 
  52 Object Format files, and saves them with the .prw extension.
 
  54 These files can be converted to ppm with the *prw2ppm* script.
 
  56 The Artlantis Preview Files are bitmap images compressed using an RLE encoding.
 
  58 There is a header with this structure:
 
  62 where T, W and H are respectively the file type, the image width and height,
 
  63 as 32-bit big-endian integer values.
 
  65 Immediately after the header there is the image data, which can be seen as divided into
 
  66 packets of the format:
 
  70 Where C is the run count as a 32 bit big-endian integer, and P+ is
 
  71 a sequence of 1 or more Pixels encoded as 32-bit big-endian integers with the
 
  72 color information in the format 00RRGGBB.
 
  75 The rightmost byte was always zero in the analyzed files.
 
  77 A .prw file looks like:
 
  79   TWHCPPPPCPCPCPCPCPPPPPPPPPCP...
 
  81 The run counter C can refer to two types of packets:
 
  83   - run-length packet: here the single P value has to be repeated C times
 
  85   - raw packet: here C is followed by C different P pixels values
 
  87 to decide if a packet is a 'run-length packet' or a 'raw packet' the last
 
  88 pixel value of the previous packet has to be inspected: let be P and Q two
 
  89 pixel values, and consider the sequence:
 
  95  - if P == Q then C starts a run-length packet and Q is repeated C
 
  96    times and X will be the next run count,
 
  98  - if P != Q then C starts a raw packet and Q is the first pixel of a sequence
 
  99    of C different pixel values (X will be the second pixel value).
 
 101 Some special treatment might be still needed to handle the count in the first
 
 102 packet, in the analyzed files the first packet was always a 'run-length
 
 103 packet', so this is the assumption *prw2ppm* relies on.
 
 105 I call this RLE compression method the 'sandwich encoding', because the count
 
 106 in run-length packets is between two identical pixel values.