assimp icon indicating copy to clipboard operation
assimp copied to clipboard

Support for VST format

Open jumpjack opened this issue 3 years ago • 2 comments
trafficstars

I found this ancient 3d format which apparently is not supported by any modern software: VST, used by NASA ViSTa softwtare a decade ago. Fortunately, the format is well documented, so it should not be difficult to implement it, but I am not a C++ programmer, I only know Javascript.

Summary diagram of the format:

VST-format

It is a multi-resolution format, containing several LODs (Level Of Detail groups). Each LOD contain several "patches"; each patch is a set of faces OR of points, depending on second parameter of PatchHeader:

image

My interpretation:

immagine

immagine

Vertex are stored at the beginning of the file, after:

  • "VST header" (fixed length: 40 bytes)
  • Overall Bounding Box (Fixed length: 24)
  • References to Textures (1 or more, depending on Int32 stored at 0x1C-0x1F, each reference being 2048 bytes long)
  • "Coordinate System" (Fixed length 4096 bytes)

Hence:

Constants:

  • VST_HEADER_LENGTH = 40
  • TEXTURES_COUNT_OFFSET = 28
  • VERTEX_COUNT_OFFSET = 32
  • LODS_COUNT_OFFSET = 36
  • BOUNDING_BOX_LEN = 24
  • TEXTURE_REF_LEN = 2048
  • COORD_SYS_LEN = 4096
  • PATCH_HEADER_LEN = 24
  • LOD_HEADER_LEN = 28
  • SINGLE_VERTEX_LEN = 20
  • PATCH_TYPE_OFFSET = 8
  • PATCH_FACES_COUNT_OFFSET = 16 // Number of arrays of vertex pointers in patch
  • PATCH_VERTEX_COUNT_OFFSET = 20 // Number of vertex pointers in patch

Variables:

  • texturesCount: offset 0x1C-0x1F
  • vertexCount: offset 0x20-0x23
  • vertexOffset = VST_HEADER_LENGTH + BOUNDING_BOX_LEN + texturesCount * TEXTURE_REF_LEN + COORD_SYS_LEN (for one texture: dec6208, 0x1840 )
  • totalVertexLength = vertexCount * SINGLE_VERTEX_LEN
  • first_LOD_offset = vertexOffset + totalVertexLength
  • firstPatchOffset = first_LOD_offset + LOD_HEADER_LEN + BOUNDING_BOX_LEN
  • firstPatchTypeOffset = firstPatchOffset + PATCH_TYPE_OFFSET
  • firstPatchLen = offset(firstPatchOffset + PATCH_FACES_COUNT_OFFSET) + offset(firstPatchOffset + PATCH_VERTEX_COUNT_OFFSET)
  • facesCount: must parse whole LOD to count how many "faces" ("index arrays") are present in each patch of the LOD.

VST format was used to produce hundreds of file for NASA Missions "Spirit" and "Opportunity" ("MER rovers"): https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2mw_0xxx/data/navcam/site0137/

The textures referenced as .IMG files in the .VST files are actually contained in .RGB files with same name (.IMG are NASA multiband images).

Example association: 2n292280938vilb100p0703l0m1.vst file points to 2N292280938RSLB100P0703L0M1.IMG , but there is no such file in folder; there is also no 2N292280938RSLB100P0703L0M1.RGB file, but there is a "similar" one, 2N292280938XYLB100P0703l0M1.RGB: the only difference is "XYL" rather than "RSL" in the name; but I think you can disregard this field: what matters are the field about rover location when picture used to create 3d model was taken:

Explanation of 2N292280938XYLB100P0703L0M1 name:

  • 2 = MER2
  • N = NAVCAM
  • 292280938 = Timestamp
  • XYL = Product type
  • B1 = Site 137
  • 00 = Position 0
  • P0703 = Navcam Observation n.0703
  • L = Left camera
  • 0 = no filter
  • M = Creator of the file
  • 1 = version of the file

In a nutshell, all fields are mandatory to associate a VST to an RGB, but the "XYL/RSL" field.


Comparison to PLY format, given that texturesCount and vertexCount are known:

ply
format ascii 1.0           { ascii/binary, format version number }
comment made by anonymous  { comments keyword specified, like all lines }
element vertex VVVV          { vertexCount }
property float32 x         { ok }
property float32 y         { ok  }
property float32 z         { ok  }
element face FFFF          { number of faces in one LOD }
property list uint8 int32 vertex_index   { each face is a list of int32 pointers to vertex; how many pointers is 
                                                                given by an uint8 value before the values}
end_header                 { delimits the end of the header }
0 0 0                      { start of vertex list }
0 0 1
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
3 0 1 2                   { start of face list; in VST all faces are triangles }
3 7 6 5 
3 0 4 5 
3 1 5 6 
3 2 6 7 
3 3 7 4 

jumpjack avatar Jun 17 '22 07:06 jumpjack

Working to my own converter: https://github.com/jumpjack/VST-converter

jumpjack avatar Jun 17 '22 13:06 jumpjack

I successfully created my kaitai-struct definition (in KSY language) of VST format: https://github.com/jumpjack/VST-converter/blob/main/Vst.js

This allows automatic creation of C/C++ source code to create a VST object from a VST file, just by compiling the KSY file using kaitai struct: you need just to download the kaitai-struct compiler (java, working on any machine) and follow instructions to compile for your language, then use the resulting library as described here.

jumpjack avatar Jul 09 '22 19:07 jumpjack