Caviar
The caviar (.cvr) files in Alpha Centauri are a voxel based 3D file format that has animation capabilities.
Code that can read it can be found at https://github.com/uaEquals42/CVR-Colorizer
Contents |
Overview
I've identified 3 major sections in the caviar file format.
- File start - this section includes the model name and some of the palette codes.
- Unknown - Currently unknown what this section of data is for.
- 3D data - Contains the 3D voxel information. Position, Color and the normal vector.
CVR Specification
Work in progress
Values on the left are the hexadecimal values found in the caviar file format. Description of what they represent on the right.
Data that is tabbed is extra examples and/or values.
File start
43 56 52 00 is the characters "CVR" xx xx xx xx <- file size in bytes. Unsigned? 00 00 00 Next part |-------| Version number for the file is stored here, not sure if it stores anything else as well. 01 0C 00 00 00 9A 99 21 41 9A 99 21 41 - 10.10 33 33 23 41 version 10.20 00 00 00 02 Constant ID 11 00 00 00 Name length + 8 42 41 53 49 43 2E 4D 41 58 Name of file it was converted from? 00 00 00 03 Constant ID xx xx xx xx The distance in bytes to the 3d description section. Relative to this point! Points a ways before the name of body part. What's interesting this distance seems to be exactly the same for the different palates for non-animated files. Need to check to see if number changes for animated files or not. 00 00 01 01 Constant ID 0F 00 00 00 = Palette name length + 8 55 6E 6E 61 6D 65 64 Palette name 00 00 02 01 Constant ID 0A 1B 00 00 <- Points to 3d section label 04. Distance from here to there. 0A F5 ????? A = 10. F5 = 145 10+145 = 155 For reading in the values, I had to move 10 forward before starting to count. 145 for 145 values used? Allot of guess work here aa F5 00 00 00 FC 00 FC FC 00 FC FC 00 FC FC 00 FC FC 00 FC FC 00 FC FC 00 FC FC 00 FC FC 00 FC.... aa F5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 AC 80 50 A0 7C .... Yeah.... Ok. I've learned this: aa*3 (usually 1*3 or 10*3) tells how far to right to being start counting up from 0 for color numbers. F5 (145) is the length of this sections data. so values greater than 145 - aa. are fetched by some other method. Colors are stored as R G B values. 1 byte each. 00 00 02 01 xx xx xx xx < points to 3d section label 04 0A F5 00 00 00 < Why is this duplicated!? 01 F5 < unnamed.... Animated. 5 body parts 01 F5 < Unnamed... no-anime. 14 body parts /\- 245 hmmm The next two bits = 245*3 in length. Ok, I (think) this is saying how big the palette is in size.
Large Amount of unknown data
After that there is a large section of data that is currently unknown as to what it does.
Lets skip to the 3d data section.
3d Voxel Data Section
00 00 00 04 Constant ID, Earlier Reference points here 11 9D 00 00 ok this is the distance to the end of the file in bytes + 4. If you measure from the 04. 00 00 01 04 Constant ID 14 00 00 00 Name length + 8 21 41 43 41 43 2D 41 56 2E 6D 61 78 00 NAME ------------If this is an animation only file this will be missing----- 00 02 04 0C Constant ID 00 00 00 ???? 01 00 00 00 Number of body parts for object 00 ?? Spacer? ----------- End optional section ------------------ 00 03 04 0C Constant ID ? 00 00 00 ????<br /> 01 00 00 00 # of frames Never set to 00. Always 1 or more 00 00 04 04 Constant ID DD 9C 00 00 Distance 00 01 04 04 Constant ID 10 00 00 00 Length of Part Name + 8 41 41 2D 52 4F 56 45 52 NAME ----------- On select.cvr, this section wasn't here. select.cvr was 10.10 version. was animated but only had one "part" This section was also missing from AVHT-LightsReposition, an animation only file. 00 02 04 04 Constant ID 74 9C 00 00 Distance ----------- or -- Not sure if here all the time if 02 04 04 is missing. Just need to write a function to find ID lines. 00 Probably and artifact of their save function when skiping unused data. Might explain some of the weird bits that I've found solo laying around. -- 01 02 04 04 Constant ID 6C 9C 00 00 Distance 0A 00 00 00 Ok, currently I have no idea what this is. If i change it, CVR will crash. 64 9C 00 00 00 00 80 40 64 9C 00 00 63 9C 00 00 most of this has to deal with the number of units per 3d pixel I have no clue how it actually works. 7F 00 B3 00 2D 00 ZZ sz xx sx yy sy zz,xx,yy didn't change object position. sz, sx, sy when i changed them reduced the size and offset the item in the view zz, xx, yy I think this tells the viewer the dimensions of the item on screen so that it knows when to render C1 FF A7 FF EA FF <- Positional Data. I believe it is the starting point for rendering voxels. Not sure how it's supposed to interact with the rotation point, yet. zz zz xx xx yy yy 24 00 26 00 0A 00 <- Related to the rotation point for object, Not sure on the math yet for it. zz zz xx xx yy yy E7 33 00 00 < Number of 3d voxels in this part --- This part changes, can either be here or isn't --- Wish I knew how the program knows this part exists. Showed up in select, which is animated 1 part item. zz zz xx xx yy yy ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? zz zz xx xx yy yy nn nn nn nn nn nn nn nn <- Number of voxels until the next location jump. 00 00 00 00 --- END Section --- 26 C1 95 66 C2 95 66 C3 95 ... < 3d data ok. 26 C1 95 gg ff pp pp is the palate code. gg in binary ddddd nnn ddddd <- see lookup chart below for the location the next voxel should be placed. nnn <- is used for a normal lookup chart ff eeee ???? Some of these are used for knowing which normal to use eeee is where I suspect the normal information is also stored.
Multi-part Models
If this is a multi part file...... F5 A8 00 F5 D0 00 F5 end of 3d data 00 00 00 00 00 00 03 04 04 Constant ID 51 00 00 00 ??? 01 03 04 04 09 00 00 00 00 02 03 04 is it 2 3 4: 4 14 or is it 2 3 4 4: 14???? heck what could it be pointing to or representing? 04 14 00 00 00 40 1E E0 BE F0 DB 7C 43 FF DD CB 43 03 03 04 04 2C 00 00 00 64 71 12 34 0F 96 59 34 00 00 80 BF 52 CF 7D 3F F2 A8 05 3E 4D 97 2D 34 F2 A8 05 BE 52 CF 7D 3F 1F 9C 44 34 00 00 04 04 84 76 00 00 00 01 04 04 Constant ID 13 00 00 00 Length of Part's Name + 8 44 72 69 6C 6C 5F 41 72 6D 5F 31 00 02 04 04 Constant ID 18 76 00 00 Distance to next 03 04 04 marker 01 02 04 04 Constant ID 10 76 00 00 0A 00 00 00 ????? 08 76 00 00 00 00 A0 40 08 76 00 00 07 76 00 00 AF 00 37 00 21 00 If this is the same as the other section, then this is the scale data A9 FF E5 FF F0 FF ???Position? Check! 4D 00 07 00 F7 FF ???Rotation Check it out. 31 27 00 00 3d voxel count? ok no guess for here.... will have to try out stuff and see 4D 00 11 00 F6 FF F7 FF F6 FF FD FF 14 00 15 00 08 00 00 00 F6 FF 01 00 60 02 00 00 00 00 00 00 ok, 3d data begins again. 26 B0 F5 B7 E9 F5 6F E9 F5 2E
Lookup chart for voxel direction data
+Y | /z+ | / |/ +x---------- (-x) /| / | / |
x, y, z dict_directions = {'00000':[-1,-1,-1]} 00 dict_directions['00001'] = [-1, 0,-1] 08 dict_directions['00010'] = [-1,+1,-1] 10 dict_directions['00011'] = [ 0,-1,-1] 18 dict_directions['00100'] = [ 0, 0,-1] dict_directions['00101'] = [ 0,+1,-1] 28 dict_directions['00110'] = [+1,-1,-1] 30 dict_directions['00111'] = [+1, 0,-1] 38 dict_directions['01000'] = [+1,+1,-1] 40 dict_directions['01001'] = [-1,-1, 0] 48 dict_directions['01010'] = [-1, 0, 0] 50 dict_directions['01011'] = [-1,+1, 0] 58 dict_directions['01100'] = [ 0,-1, 0] 60 dict_directions['01101'] = [ 0,+1, 0] 68 dict_directions['01110'] = [+1,-1, 0] 70 dict_directions['01111'] = [+1, 0, 0] 78 dict_directions['10000'] = [+1,+1, 0] 80 dict_directions['10001'] = [-1,-1,+1] 88 dict_directions['10010'] = [-1, 0,+1] 90 dict_directions['10011'] = [-1,+1,+1] 98 dict_directions['10100'] = [ 0,-1,+1 ] A0 dict_directions['10101'] = [ 0, 0,+1 ] A8 dict_directions['10110'] = [ 0,+1,+1 ] B0 dict_directions['10111'] = [+1,-1,+1 ] B8 dict_directions['11000'] = [+1, 0,+1] C0 dict_directions['11001'] = [+1,+1,+1] C8 dict_directions['11010'] = [ ?, ?, ?] d0 ??????!!!!! Noticed this appears only at the end of parts sections for direction for some files!
Other files don't have it. I think it is a marker that they used for certain versions of the CVR file.