Jump to content

OBD:CRSA: Difference between revisions

m
...
m (...)
 
(25 intermediate revisions by 4 users not shown)
Line 1: Line 1:
[[Main Page]] >> [[OBD:Oni Binary Data|Oni Binary Data]] >> [[OBD:File types|File Types]] >> CRSA File
{{OBD_File_Header | type=CRSA | prev=CONS | next=DOOR | name=Corpse Array | family=Level | align=center | onistuff=crsa}}




<CENTER>[[OBD:CONS|<==]] <FONT SIZE=5>CRSA File</FONT> [[OBD:DOOR|==>]]<BR>
The first image shows the header and the beginning of the first element. The second image the end of it.
<FONT SIZE=2>Corpse Array - Level File</FONT></CENTER>




http://www6.fh-eberswalde.de/user/dkriesch/onistuff/images/crsa_a.gif
[[image:crsa_a.gif]]


==Array header==


==CRSA - Corpse Array==
[[image:crsa_m.gif]]
Related :
[[OBD:File types/Level|Level files]]
[[OBD:Oni Binary Data|Oni Binary Data]]


The array consists of a 32-byte header, followed by a number of fixed-size corpse chunks (1100 bytes each).


The resulting file is completed to a 32-byte multiple with the 0xADDE blank filler
{{Table}}
 
{{OBDth}}
Since the capacity of the array is always the same (20 corpses), CRSA files are all the same size (0x5620 bytes).
{{OBDtr| 0x000 | res_id  |FF0000| 01 35 02 00 | 565        | 00565-.CRSA }}
The array actually takes up 0x5610 bytes : the last 16 bytes are filled with the blank filler 0xADDE.
{{OBDtr| 0x004 | lev_id  |FFFF00| 01 00 00 06 | 3          | level 3 }}
===Header===
{{OBDtr| 0x008 | char[12] |00FF00| AD DE      | dead      | padding }}
;What's in the header?
{{OBDtr| 0x014 | uint32    |00FFFF| 11 00 00 00 | 17        | number of "fixed" corpses }}
*File ID and level ID as usual : 4 bytes each
{{OBDtr| 0x018 | uint32    |FF00FF| 11 00 00 00 | 17        | number of "used" corpses }}
*A blank field filled with 0xADDE (dead) : 12 bytes
{{OBDtr| 0x01C | uint32    |FF8000| 14 00 00 00 | 20        | array capacity; always the same in original Oni }}
*Array size (number of corpses) duplicated : 2x4 bytes
{{OBDtrBK}}
*Array capacity (maximum number of corpses, always 20) : another 4 bytes
{{OBDtr2|0x000 | char[32]|FFC8C8| _lvl_3_Intro_TCL_A_corpse.dat| ignored; the name of the source file }}
;Example:'''00565-.CRSA''' in '''level3_Final.dat'''
{{OBDtr|0x020 | uint[32] |FFC8C8|  |  | node list; runtime only }}
{|border=1 cellspacing=0
{{OBDtr| 0x0A0 | link    |FFFFC8| 01 36 02 00 | 566        | link to 00566-TCTF_lite_1.[[OBD:ONCC|ONCC]] }}
|+Header
|- ALIGN=CENTER VALIGN=TOP
!Offset
|0x0A4||matrix||
!Raw hex/string
{|border=1 cellspacing=0 style="white-space:nowrap"
!Value
|-BGCOLOR="#C8FFC8"
!Meaning
|C1 74 66 3F||00 78 3E 3D||45 AB DD 3E
|-BGCOLOR="#C8FFC8"
|A6 8B 7D 3D||19 73 7F BF||EE 67 B0 BC
|-BGCOLOR="#C8FFC8"
|03 AE DC 3E||82 2C 3D 3D||8D B2 66 BF
|-BGCOLOR="#C8FFC8"
|C5 FA E7 41||2E 2B CB C1||58 B4 45 C1
|}
|
{|border=1 cellspacing=0 style="white-space:nowrap"
|0.900219||0.046501||0.432947
|-
|-
|0x00
|0.061901||-0.997850||0.021534
|01 35 02 00
|565
|File ID for 00565-.CRSA
|-
|-
|0x04
|0.431015||0.0461850||-0.901162
|01 00 00 06
|3
|Level ID
|-
|-
|0x08<br>0x0C<br>0x010
|28.997446||-25.396084||-12.356529
|AD DE AD DE<br>AD DE AD DE<br>AD DE AD DE
|}
|DEAD
|ALIGN=LEFT|transform matrix for the pelvis (in world space)
|blank filler
{{OBDtrBK|0xD4-0x434 : transform matrices for the other 18 bones}}
|- ALIGN=CENTER VALIGN=TOP
|0x434||AABB||
{|border=1 cellspacing=0 style="white-space:nowrap"
|-BGCOLOR="#C8FFFF"
|D4 22 8C 41||95 50 E9 C1||BC 31 9C C1
|-BGCOLOR="#C8FFFF"
|75 E6 14 42||2E 20 B1 C1||07 B1 D3 C0
|}
|
{|border=1 cellspacing=0 style="white-space:nowrap"
|17.517006||-29.164347||-19.524284
|-
|-
|0x14
|37.225056||-22.140713||-6.615360
|11 00 00 00
|}
|17
|ALIGN=LEFT|bounding box for the whole corpse
|17 corpses (array size)
|-
|0x18
|11 00 00 00
|17
|17 corpses (array size again)
|-
|0x1C
|14 00 00 00
|20
|Room for 20 corpses (array capacity)
|}
|}
;Array capacity
:The array capacity is larger than the number of "fixed"/"used" corpses to allow the engine to store new corpses at runtime. "Fixed" means that those corpses are never overwritten/deleted at runtime, all new corpses are stored after the "fixed" ones. This means that "fixed" <= "used" <= "capacity".
;Bones
:Here is one of the few places where the bone count 19 is apparently hardcoded.
:I.e., custom characters with weird bone counts won't work. See, e.g., [[OBD:TRIA#Bones|TRIA]]
;What's in a bone?
:The transformation matrix (3D rotation/scale/shear/mirror and translation)
::can be seen as four 3D vectors '''X''', '''Y''', '''Z''', and '''R''' in world space.
:If a bone mesh has a vertex at (x, y, z) in its native coordinates,
::then the actual position of that vertex in the level will be '''R''' + x '''X''' + y '''Y''' + z '''Z'''
:That's the transformation defined by the 3x4 transform matrix.
Reminder : the 2nd coordinate of '''X''', '''Y''', '''Z''', and '''R''' is the height.


===Corpse chunks===
;Authoring
They follow the header directly
:The script command [[make_corpse]](filename) creates a separate corpse file in the Oni folder. The pose of this corpse is taken from the player character (the [[Dev Mode]] shortcut Ctrl+F7, "Play dead", would have come in handy here). The format is roughly as above. The contents of the files thus created can then be inserted as elements in a level's CRSA.


;What's in a corpse?
*A space for notes (160 bytes) : often the name of the file the corpse was taken from when packing the array.
*A link to the [[OBD:ONCC|ONCC]] (model that should be used for the corpse) : that's 4 bytes as usual.
*Then, 19 bones, each of them defined by absolute orientation and position (unlike in a TRAM, where orientations are relative)<br>Every bone is (3x3 + 3)x4 = 48 bytes, so that's 19x48 = 912 bytes.
*Finally, an axis-aligned bounding box (2x3x4 = 24 bytes)
The total size of a corpse is thus 1100 bytes.


;What's in a bone?:The absolute orientation is defined in a "heavy" way ''via'' an orthonormal trihedron :
{{OBD_File_Footer | type=CRSA | prev=CONS | next=DOOR | name=Corpse Array | family=Level}}
:three 3D vectors '''x''', '''y''' and '''z''', each of length 1, at right angles with each other, and ordered "directly"
:(like Oni's world axes : if '''x''' points left and '''y''' points up then '''z''' points to ''front'', not back).
:Each one of those vectors is stored as 3 floats (3x4 bytes), first '''x''', then '''y''', then '''z''' (so 3x3x4 = 36 bytes in total).
:The absolute position '''R''' of a bone (of its parent node, actually) is stored as 3 floats right after the orientation trihedron.
:That's another 12 bytes, so 48 bytes in total.
Reminder : the 2nd coordinate of '''R''' aka ''y'' is the height; same for '''x''', '''y''' and '''z'''.


;Example:first corpse of '''00565-.CRSA''' in '''level3_Final.dat'''.
{{OBD}}
:Offsets are measured from the start of the corpse chunk.
{|border=1 cellspacing=0
|+Notes and ONCC link
!Offset
!Raw hex/string
!Value
!Meaning
|-
|0x00
|colspan=2|_lvl_3_Intro_TCL_A_corpse.dat
|probably the name of the source file
|-
|0xA0
|01 36 02 00
|566
|Link to 00566-TCTF_lite_1.[[OBD:ONCC|ONCC]]
|}
{|border=1 cellspacing=0
|+Bone orientation and position
!Offset
!Bone
!Raw hex
!Value/Meaning
|-
|0xA4
|Pelvis
|C1 74 66 3F 00 78 3E 3D 45 AB DD 3E<br>A6 8B 7D 3D 19 73 7F BF EE 67 B0 BC<br>03 AE DC 3E 82 2C 3D 3D 8D B2 66 BF<br>C5 FA E7 41 2E 2B CB C1 58 B4 45 C1
|'''x''' = (0.900219, 0.046501, 0.432947)<br>'''y''' =  (0.061901, -0.997850, -0.021534)<br>'''z''' = (0.431015, 0.0461850, -0.901162)<br>'''R''' = (28.997446, -25.396084, -12.356529)
|-
|0xD4
|Lt Thigh
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x104
|Lt Calf
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x134
|Lt Foot
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x164
|Rt Thigh
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x194
|Rt Calf
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x1C4
|Rt Foot
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x1F4
|Mid
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x224
|Chest
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x254
|Neck
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x284
|Head
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x2B4
|Lt Shoulder
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x2E4
|Lt Arm
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x314
|Lt Wrist
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x344
|Lt Fist
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x374
|Rt Shoulder
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x3A4
|Rt Arm
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x3D4
|Rt Wrist
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|-
|0x404
|Rt Fist
|...
|'''x''' = (, , )<br>'''y''' =  (, , )<br>'''z''' = (, , )<br>'''R''' = (, , )
|}
{|border=1 cellspacing=0
|+axis-aligned bounding box
!Offset
!Raw hex/string
!Value
!Meaning
|-
|0x434
|D4 22 8C 41 95 50 E9 C1 BC 31 9C C1
|(17.517006, -29.164347, -19.524284)
|"minimal" corner of the AABB
|-
|0x440
|75 E6 14 42 2E 20 B1 C1 07 B1 D3 C0
|(37.225056, -22.140713, -6.615360)
|"maximal" corner of the AABB
|}
281

edits