## Approaches of Parsing Bone Representations

Read or post any tutorial related to file format analysis for modding purposes.
jayn23
mega-veteran
Posts: 167
Joined: Sun Jul 17, 2011 9:30 pm
Has thanked: 46 times
Been thanked: 149 times

### Re: Approaches of Parsing Bone Representations

Thanks for all the great tips

i feel kind of stupid with this but i cant seem to get the correct numbers for world transformation, and was hoping you could look at the numbers and maybe tell me what i am doing wrong:
I have a picture of debug console of noesis where first line(bones1) is original 4x3 matrix while second line(bones2) in world transformation.
up until i = 2 i get the correct answer by multiplying bone * bone[i-1] etc..
from i =3 no matter what combination i do i dont get the same result.
what i am doing is Matrix[3]*matrix[2]*matrix[1]*matrix[0], i tried a few other combinations including matrix[3]*matrix[2]-world transformation but none give the same result as noesis.

i dont know how important it is to understand this if noesis does this , but it bugs the hell out of me that i cant figure it out
You do not have the required permissions to view the files attached to this post.

jayn23
mega-veteran
Posts: 167
Joined: Sun Jul 17, 2011 9:30 pm
Has thanked: 46 times
Been thanked: 149 times

### Re: Approaches of Parsing Bone Representations

couldn't add a second attachment before, here are my matrices:
if i understood correctly:

for i =3
Bones[3] * Bones[2] * Bones[1]* Bones[0] = answer
You do not have the required permissions to view the files attached to this post.

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

jayn23 wrote:
Sun Aug 18, 2019 9:25 pm
what i am doing is Matrix[3]*matrix[2]*matrix[1]*matrix[0]
It should be matrix[0]*matrix[1]*matrix[2]*matrix[3] since it's row-major matrix.
noe.png
jayn23 wrote:
Sun Aug 18, 2019 9:25 pm
i dont know how important it is to understand this if noesis does this , but it bugs the hell out of me that i cant figure it out
Theoretically to convert a parent space tree to world space, you need to premultiply each node in a level with its parent recurrently from the root level down to the last level, or use other methods that have the same effect. So it doesn't matter how Noesis does it, so long as it works as expected. But you should know at least one way to convert it yourself.
You do not have the required permissions to view the files attached to this post.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.

jayn23
mega-veteran
Posts: 167
Joined: Sun Jul 17, 2011 9:30 pm
Has thanked: 46 times
Been thanked: 149 times

### Re: Approaches of Parsing Bone Representations

Ill take a look at the numbers when i get home, but i am sure ill get it to work now.

Thanks a lot for all your help and fast reply's i really appreciate it.

723119159
Posts: 55
Joined: Sun Dec 02, 2018 4:27 pm
Has thanked: 3 times

### Re: Approaches of Parsing Bone Representations

Hello,and sorry to disturb you.
Could you analysis the bigworld engine model?I can't find any ather idears.
http://www.mediafire.com/file/g432vuf89 ... 05408/file
this is a sample. bone file is .visual
Thanks

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

chr_body_rank_104_a_slender.zip

Code: Select all

``````# Dump Name: chr_body_rank_104_a_slender.o4a
# From Game: IDOLM@STER One For All
# Platform: PS3
# Bone Format: 4x4 Matrices (inversed)
# Coordinate System: Left-Hand
# Endian: Big
``````
Bone data structure:

Code: Select all

``````long	boneCount
for i = 0 < boneCount
long	boneID
long	structSize
long	unknown
char	boneName[0x20]
long	parentID
byte	skip[0x9C]
float	boneMat[4][4] // Column-major
byte	skip2[0xC]
``````
Same procedure as for Iron Man 2. Probably some kind of "feature" of PS3 games?

Noesis code(lack convertion to right-handed):

Code: Select all

``````#load the model
bs = NoeBitStream(data, NOE_BIGENDIAN)
bones = []
for i in range(0, boneCount):
bs.seek(8, NOESEEK_REL)
if boneName == "":
boneName = "Scene Root"
bs.seek(0x9C, NOESEEK_REL)
Mat44 = NoeMat44.fromBytes( bs.readBytes(0x40), NOE_BIGENDIAN )
boneMat = Mat44.toMat43().inverse()
bs.seek(0x10, NOESEEK_REL)
bones.append( NoeBone(boneID, boneName, boneMat, None, parentID) )

mdl = NoeModel()
mdl.setBones(bones)
mdlList.append(mdl)
return 1
``````
You do not have the required permissions to view the files attached to this post.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

g_uec.zip

Code: Select all

``````# Dump Name: g_uec.ve1
# From Game: Ben 10 Ultimate Alien: Cosmic Destruction
# Platform: XBOX 360
# Bone Format: Quaternion Rotation, Translation
# Coordinate System: Right-Hand
# Engine: Vicious Engine
# Endian: Big
``````
Bone data structure:

Code: Select all

``````word	boneCount
word	boneCount
byte	itemBoneCount
byte	itemBoneCount
word	skip
for i = 0 < boneCount
float	Rotation[4] // Quaternion Rotation
float	Translation[3]
float	Scaling[3]
char	parentID
byte	skip[3]
for i = 0 < itemBoneCount
float	Rotation[4] // Quaternion Rotation
float	Translation[3]
char	parentID
byte	skip[3]
``````
Similar procedures as previous examples. Just with an extra bone list.

Noesis code:

Code: Select all

``````#load the model
bs = NoeBitStream(data, NOE_BIGENDIAN)
bs.seek(2, NOESEEK_REL)
bs.seek(7, NOESEEK_REL)
bones = []
for i in range(0, boneCount):
bs.seek(3, NOESEEK_REL)
boneMat = Rot.toMat43(transposed = 0)
boneMat[3] = Tran
bones.append( NoeBone(i, "bone%03d"%i, boneMat, None, bonePIndex) )
for i in range(0, itemBoneCount):
bs.seek(3, NOESEEK_REL)
boneMat = Rot.toMat43(transposed = 0)
boneMat[3] = Tran
idx = boneCount + i
bones.append( NoeBone(idx, "bone%03d"%idx, boneMat, None, bonePIndex) )
totalBoneCount = boneCount + itemBoneCount
# Converting local matrix to world space
for i in range(0, totalBoneCount):
j = bones[i].parentIndex
if j != -1:
bones[i].setMatrix( bones[i].getMatrix() * bones[j].getMatrix() )

mdl = NoeModel()
mdl.setBones(bones)
mdlList.append(mdl)
return 1
``````
You do not have the required permissions to view the files attached to this post.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

Time for some clarification.

Why would the following method of converting a parent-space bone tree to world space work within Noesis?

Code: Select all

``````for i in range(0, boneCount):
j = bones[i].parentIndex
if j != -1:
bones[i].setMatrix( bones[i].getMatrix() * bones[j].getMatrix() )
``````
It has nothing to do with Noesis' feature but simply because it's logically correct for any organized bone list.

Let's see how the bone nodes are usually stored.

(bone tree of g_uec.ve1 from Ben 10 Ultimate Alien: Cosmic Destruction)

The number of each node equals to its index in the node list, the same below.

And this diagram shows how the nodes are traversed.

As you can see, the traversal order of the nodes is exactly aligned to how they're stored in the bone list.

Bones stored as above are in the so-called depth-first traversal order. However it can also apply to bone list in breadth-first storage.

(bone tree of mermaid_normal.model from GuJian3)

The traversal order of the list:

So long as the bone nodes in the list are organized in a way where any node is stored after its parent node, this method will work correctly.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.

EPYCSPYDER
beginner
Posts: 22
Joined: Thu Feb 06, 2020 12:48 pm
Has thanked: 6 times
Been thanked: 3 times

### Re: Approaches of Parsing Bone Representations

Can you read the bones from forza 4 car? It has 75 bones
You do not have the required permissions to view the files attached to this post.

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

anakinhooddown.zip

Code: Select all

``````# Dump Name: anakinhooddown.sw3
# From Game: Star Wars: Episode III – Revenge of the Sith
# Platform: Xbox
# Bone Format: 4x3 Matrices
# Coordinate System: Left-Hand
# Endian: Little
``````
Bone data structure:

Code: Select all

``````long	boneCount
for i = 0 < boneCount
char	boneName[0x20]
float	boneMat[4][3] // Rotation[3][3](column-major), Translation[3]
short	parentID
``````
The rotation matrices are in column-major so transposes are required.
Also similar to Iron Man 2 and IDOLM@STER One For All, they need to be inversed.

Noesis code (lack convertion to right-handed):

Code: Select all

``````#load the model
bs = NoeBitStream(data)
bones = []
for i in range(0, boneCount):
pos = bs.tell() + 0x20
bs.seek(pos, NOESEEK_ABS)
bones.append(NoeBone(i, boneName, boneMat, None, bonePIndex))

mdl = NoeModel()
mdl.setBones(bones)
mdlList.append(mdl)
return 1
``````
You do not have the required permissions to view the files attached to this post.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.

jayn23
mega-veteran
Posts: 167
Joined: Sun Jul 17, 2011 9:30 pm
Has thanked: 46 times
Been thanked: 149 times

### Re: Approaches of Parsing Bone Representations

Hi Bigchillghost,

Thanks for updating this thread all the time, i still find my self checking it out every now and then to give me ideas how to do things its very useful
Noesis code (lack convertion to right-handed):
apparently rich thought about this to, yesterday i found a built in function for swapping from left to right hand and thought you might be interested.

Code: Select all

``boneMat = NoeMat43.fromBytes(bs.readBytes(48)).transpose().inverse().swapHandedness(0)``
swapHandedness (axis) while axis can be 0,1,2
for anakin it worked with 0

Bigchillghost
double-veteran
Posts: 719
Joined: Tue Jul 05, 2016 9:37 am
Has thanked: 24 times
Been thanked: 653 times

### Re: Approaches of Parsing Bone Representations

jayn23 wrote:
Tue May 26, 2020 8:01 pm
i still find my self checking it out every now and then to give me ideas how to do things its very useful
Good to know.
yesterday i found a built in function for swapping from left to right hand and thought you might be interested.
Yeah I noticed that long time ago but never get it working. It appears that I mistook that function as one that affects the object itself and didn't overwrite the original matrix with the swapped one. I tested the other left-handed formats posted in this thread but some of them seem to be in right-handed already(Aavtar The Game, Iron Man 2 and IDOLM@STER). Not sure if it's because they use a different naming aspect from the others so I'll leave them as they are. Thanks for the hint anyway.
May you find peace in this puzzle-solving game. Say it with action: click the when you get helped.