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

Re: [NOESIS] Titan Quest

Post by Demonsangel »

Image

Ok, so Noesis can now load the .tex files (Tamschi's source was a great help!), but I do need some help on Noesis functions on how to load them more efficiently.

After loading the file into memory and correcting the data I don't know what to do with the raw ( DXT5 compressed) pixel data, so I basically write everything back into NoeBitStream, get the buffer from this load that bitstream asif it was a dds file.

Code: Select all

	def WriteFixedDDS(self):
		file=NoeBitStream()
		file.writeBytes(b"\x44\x44\x53\x20")
		file.writeBytes(noePack("<1i",self.header.DefaultSize))
		file.writeBytes(noePack("<1i",self.header.Flags))
		file.writeBytes(noePack("<1i",self.header.Height))
		file.writeBytes(noePack("<1i",self.header.Width))
		file.writeBytes(noePack("<1i",self.header.LinearSize))
		file.writeBytes(noePack("<1i",self.header.Depth))
		file.writeBytes(noePack("<1i",self.header.MipmapCount))
		file.writeBytes(noePack("<11i",*self.header.Reserved1))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.DefaultSize))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.Flags))
		file.writeBytes(b"\x44\x58\x54\x35")
		file.writeBytes(noePack("<1i",self.header.PixelFormat.RGBBitCount))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.RBitMask))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.GBitMask))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.BBitMask))
		file.writeBytes(noePack("<1i",self.header.PixelFormat.ABitMask))
		file.writeBytes(noePack("<1i",self.header.Caps))
		file.writeBytes(noePack("<1i",self.header.Caps2))
		file.writeBytes(noePack("<1i",self.header.Caps3))
		file.writeBytes(noePack("<1i",self.header.Caps4))
		file.writeBytes(noePack("<1i",self.header.Reserved2))
		self.header.Images[0].reverse()
		for l in range(self.header.Layers):
			for m in range(self.header.MipmapCount):
				file.writeBytes(self.header.Images[l][m])
		return file

Code: Select all

buffer=dds.WriteFixedDDS()
tex = rapi.loadTexByHandler(buffer, '.dds')
	if tex: texList.append(tex)
So I have the data, now how do I "decompress" it or whatever I need to do so I could use this instead:

Code: Select all

texList.append(NoeTexture("TQTex",dds.header.Width,dds.header.Height,dds.header.Images[0][10],noesis.NOESISTEX_RGBA32))
Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

I don't know if this works, but there are noesis.NOESISTEX_DXT1, noesis.NOESISTEX_DXT3 and noesis.NOESISTEX_DXT5 constants that you can use instead of noesis.NOESISTEX_RGBA32.
The format should be somewhere in the DDS header.

A few .tex files don't have reversed mip maps, so you have to check that flag to choose the right image.
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 »

Noesis still crashes when trying to display the texture.

Edit: What am I doing wrong to load the texture in my model script? Neither the .dds/.tga/.tex work when trying the following:

Code: Select all

rapi.rpgSetMaterial("AW01")
mdl=rapi.rpgConstructModel()
matList=[]
texList=[]
material = NoeMaterial("AW01","")
material.setTexture("ancestralwarrior02.tga")
matList.append(material)
mdl.setModelMaterials(NoeModelMaterials(texList, matList))
mdl.setBones(self.bones)
mdlList=[]
mdlList.append(mdl)
The material is set in Noesis but no texture appears. After exporting the model to blender/3ds max the UV coordinates are correct.
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 »

Tamschi, I'm having trouble understanding the function you sent to get the vertex weight, especially with the info about shaders. Couldn't I just get the vertex weight out of the vertex data?
Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

Demonsangel wrote:Tamschi, I'm having trouble understanding the function you sent to get the vertex weight, especially with the info about shaders. Couldn't I just get the vertex weight out of the vertex data?
No, that won't work. The bone indices in the vertex data map to the bone slots in the draw call, not the bone array.

For each vertex, you have to find the draw call that uses it and change each bone index in the vertex' weights so that

newBoneIndex = boneListInDrawCall[oldBoneIndex];

If you want to export the mesh, you have to make sure that there aren't more than 27 bones in each draw call's bone list, otherwise Titan Quest and the Viewer crash with an invalid memory access.

The skinning shaders all take exactly 27 matrices for bone transformations. Any more than that and there's an array overflow in the animation 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 »

Would it be alright for me to adjust the current NoeBones' indexes (using NoeBone.index) to match the index in the drawcall? I parented them via bonenames and not indexes.
Or would this be asking for disasters to happen.
Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

If there is more than one draw call, the same bone id in the vertex weights can point to different bones. You really need to edit the weights to make it 100% compatible.

A bone id of 255 in the vertex weights means no bone, but the weight value isn't always 0.0 if the id is 255.
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 »

So if I get it right I need to parse the drawcalls.

For each drawcall I need to know which triangles it uses and for each triangle which vertices it uses.
These vertices then belong to the current drawcall and the current drawcall's bonelist?

I need then need to use the boneindex listed in the vertexdata use it to get the correct actual bone index by using the drawcalls bonelist.

Who comes up with this stuff.
Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

It makes perfect sense if you only want to push the mesh to the GPU. Otherwise you'd have to rearrange the weights each time the mesh is loaded into the game.
MrAdults
Moderator
Posts: 1007
Joined: Mon Mar 23, 2009 2:57 am
Has thanked: 44 times
Been thanked: 505 times

Re: [NOESIS] Titan Quest

Post by MrAdults »

I only just now noticed this thread. It's pretty common for games to use a per-draw bone palette. Bullet Witch does too. You can look at the Bullet Witch Python script with Noesis to see how that's managed, there's already an existing function to let you feed your bone palette into the Noesis RPG interface so you don't even have to deal with mapping the indices yourself.

Also, it looked to me like you ended up doing your own hierarchical bone transforms for the skeleton. You can let Noesis do that for you too. Just set up your NoeBones with standard parent-relative matrices and then call rapi.multiplyBones. (syntax is "boneList = rapi.multiplyBones(boneList)")
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 have a mesh with 2 drawcalls
1) 3041 faces, 27 bones
2) 323 faces, 7bones

My importer errors out when trying to parse vertex 5422 (and others following it)
vertex 5422 belongs to face 3065 which means the second drawcall.
vertex 5422's boneindices are (0,12,4,255) and weights(0.84,0.12,0.04,0)

So this vertex is asking for bone index 12 in drawcall 2 but there are only 7 indices and the weight for the bone is not zero.

What went wrong?
Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

Wich one is it? I'll try to open it in MeshView.
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 »

Tamschi
n00b
Posts: 14
Joined: Sun Sep 25, 2011 9:43 pm
Been thanked: 1 time

Re: [NOESIS] Titan Quest

Post by Tamschi »

Face 3065 is {3538, 3537, 3526}.
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 »

Means I can calculate all the triangles myself as well, Noesis gives me Tri 3065(5421,5422,5423)

Edit: okies that worked so far.
Post Reply