Important information: this site is currently scheduled to go offline indefinitely by end of the year.

[NOESIS] Titan Quest

Post questions about game models here, or help out others!
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

[NOESIS] Titan Quest

Post by Demonsangel »

I'm trying to create an importer for Titan Quest .msh models into Noesis, but I'm stuck on the bone importing.

I'm not quite sure how I should be importing the data through python.
I was using NoeMat43 but the armature never comes out right. I have been able to export the armature from another program to .dae and successfully import it into Noesis so I took a look at how the data was stored in the .dae file.

this is the bone axis+ position data for "Bone_Root"
Blue = Axis data, Green = Position data. The number correspond to the numbers in the 010 editor template in the next picture.
Image
Image

The .dae seems to use a 4*4 matrix while the .msh seems to use a 4*3.

I was using the following to import the bonedata into noesis and tried swapping everything and whatnot around but it never aligns with the mesh itself.

Code: Select all

boneBuff=self.inFile.readBytes(48)
boneMat.append(NoeMat43.fromBytes(boneBuff))
finale00
M-M-M-Monster veteran
M-M-M-Monster veteran
Posts: 2382
Joined: Sat Apr 09, 2011 1:22 am
Has thanked: 170 times
Been thanked: 307 times

Re: [NOESIS] Titan Quest

Post by finale00 »

Never worked with bones (yet) but since the DAE file stores it as a 4x4 matrix maybe you can try converting it using `toMat44` and see if it is as you expect as a 4x4?
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

I did

Code: Select all

boneBuff=self.inFile.readBytes(48)
boneMat.append(NoeMat43.fromBytes(boneBuff))
boneMat[i] = NoeMat43.toMat44(boneMat[i])
bute then the NoeBone() function throws a

Code: Select all

RuntimeError: Invalid type provided for bone matrix"
howfie
double-veteran
double-veteran
Posts: 929
Joined: Fri Jul 08, 2011 12:06 pm
Location: Torrance, CA
Has thanked: 10 times
Been thanked: 274 times

Re: [NOESIS] Titan Quest

Post by howfie »

Post a pic of the results. If you see the bones as a mirror image across all axes then you didn't setup your inverse bind matrix right. Also, some games have transform nodes that may need to be applied to the bones; it was like this with neptunia mk2. Every game is kind of different; you need to post more source and example. Also, parenting... are you doing it? I see two unknown parameters that you aren't using. With a little more source and posting a file example, I'm sure we can get the bones out for you.
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

How it should be:
Image

how it is:
Image

The best I can make out of it:
Image

Those 2 "unknowns" aren't unknown, they're 2 ints, first one stands for the first ChildBone, the second one for how many ChildBones it has.
According to those 2 ints I parented all the bones, I figured it out with the help of this "pic" i made.
Image

Bone_index: Bone_name, child_index, numChildren

just to explain it a little: (for the example we start at index 27: bone_r_forearm)

children is not 0 so we jump to the child index (29)
29: bone_r_wrist children is not 0 (4) so we jump to the index (31) and the following 3 bones (indexes 31 -34)
they all have 0 children so the link stops there.

I checked all the bones in Noesis and they have their parents set correctly.

now for how far I got with loading them. I read the x/y/z position info seperately from the axis data and had to swap the y and Z data to get it to stand upright.

Code: Select all

boneBuff=self.inFile.readBytes(36)
x=self.inFile.readBytes(4)
y=self.inFile.readBytes(4)
z=self.inFile.readBytes(4)

boneMat.append(NoeMat43.fromBytes(boneBuff+x+z+y))
then I thought it seemed like the position info was relevant to the parent's position and not the actual position so i added them to gether starting from the second bone (bone_root) and that's where I'm stuck.

bonelinks = dictionary with each bone bone stating it's parent's index and name
bonenames = list with all the bonenames sorted according to their indexposition

Code: Select all

for i in range(1,numBones):
   BoneData = boneMat[i]
   BoneDataP= boneMat[bonelinks[bonenames[i]][0]]

   for HKey in range(len(BoneData)):
      for key in range(len(BoneData[HKey])):
	  boneMat[i][HKey][key] = boneMat[i][HKey][key] + BoneDataP[HKey][key]
in the .rar: 3 .msh files, a 010 editor template (hardcoded for the ancestralwarriorA.msh) and the .dae i exported (ancestralwarriorA.msh)
http://www.mediafire.com/?x0z8yhp5tfl21re
howfie
double-veteran
double-veteran
Posts: 929
Joined: Fri Jul 08, 2011 12:06 pm
Location: Torrance, CA
Has thanked: 10 times
Been thanked: 274 times

Re: [NOESIS] Titan Quest

Post by howfie »

Hmmm doesn't look like an absolute vs. Relative problem... If it was you would still see the symmetry, the bones would just be extended all over the place.. Are the joint positions in absolute or relative coordinates? If absolute you will have to convert. I will be home later tonight to try out your sample. But it doesn't look like the data is an IBM so loading it as bytes doesn't work. If no one helps by tonight I'll look at it when I get home.
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

If only the Noesis .dae import script was written in Python, then this would be easy since the data is basically the same, I just need to know what the .dae script does with the data and apply it to the .msh script.
howfie
double-veteran
double-veteran
Posts: 929
Joined: Fri Jul 08, 2011 12:06 pm
Location: Torrance, CA
Has thanked: 10 times
Been thanked: 274 times

Re: [NOESIS] Titan Quest

Post by howfie »

Look in the dae and find the node hierarchy. What are the translation markup values for the root and the first child? That should tell you what noesis does.
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

Code: Select all

<node id="AncestralWarrior_rig" name="AncestralWarrior_rig" type="NODE">
        <matrix>1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
        <node id="MoveAXIS" name="MoveAXIS" sid="_MoveAXIS" type="JOINT">
          <matrix>1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 1 </matrix>
          <node id="Bone_Root" name="Bone_Root" sid="_Bone_Root" type="JOINT">
            <matrix>-8.25632E-08 1.557356E-09 1 2.524711E-09 0.03770908 0.9992887 1.55722E-09 0.003163912 -0.9992887 0.03770908 -8.25632E-08 1.503546 0 0 0 1 </matrix>
The exporter added the "dummy" AncestralWarrior_rig to the Dae so I added that one as well.
The data for the Bone_root is exactly the same as the one in the .msh apart from the [0 0 0 1] added on the end of the matrix. But with this I still don't know how to make Noesis use the data.
Ninja
veteran
Posts: 84
Joined: Sat Feb 26, 2011 3:44 am
Has thanked: 1 time
Been thanked: 20 times

Re: [NOESIS] Titan Quest

Post by Ninja »

Don't know much about bones yet but the MoveAXIS looks weird

Code: Select all

1 0 -0 
0 0 -1 
0 1 -0 
0 0 -0
That swapping the y,z axis and inverting the z axis?
howfie
double-veteran
double-veteran
Posts: 929
Joined: Fri Jul 08, 2011 12:06 pm
Location: Torrance, CA
Has thanked: 10 times
Been thanked: 274 times

Re: [NOESIS] Titan Quest

Post by howfie »

Yeah ninja, if you look at the data in his first post and you look at the DAE output you see the DAE output would have to be a column-major matrix to match up with his data.

<matrix>-8.25632E-08 1.557356E-09 1 ...</matrix>

Collada, however, is row-major order. Should be

<matrix>-8.25632E-08 0.03770908 ...</matrix>

Feed noesis a Mat3x4 instead of a Mat4x3 if you can and see what happens. I am about to test it out myself right now in my own code.
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

I don't know how to do that, I usually look at the inc_noesis.py that comes with Noesis itself to look up functions or run a "vars()" on the class.
howfie
double-veteran
double-veteran
Posts: 929
Joined: Fri Jul 08, 2011 12:06 pm
Location: Torrance, CA
Has thanked: 10 times
Been thanked: 274 times

Re: [NOESIS] Titan Quest

Post by howfie »

You can swap and move around array elements or load the floats one by one instead.
finale00
M-M-M-Monster veteran
M-M-M-Monster veteran
Posts: 2382
Joined: Sat Apr 09, 2011 1:22 am
Has thanked: 170 times
Been thanked: 307 times

Re: [NOESIS] Titan Quest

Post by finale00 »

ya, I don't know a fast way to move stuff around, so I just import struct and be like

Code: Select all

matrix = bytes()
for ...
   matrix += struct.pack("f", new_float)
lol
Demonsangel
mega-veteran
mega-veteran
Posts: 241
Joined: Fri Aug 05, 2011 9:31 pm
Location: Antwerp
Has thanked: 13 times
Been thanked: 41 times

Re: [NOESIS] Titan Quest

Post by Demonsangel »

I've tried following the offsets but the best I can make out of it is that Xvalue gets added Zvalue, Y value gets subtracted by Xvalue and Z -Y, which to me doesn't make sense.

I'll just wait and see if perhaps MrAdults can shine some light on the DAE importing.
I can't load the .dae in blender but I can in 3ds max 2011, so if all else fails I'll try looking for some source for that script and see how they work their magic.
Post Reply