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

Dragon Age 2 (PC)

Post questions about game models here, or help out others!
lpss
ultra-n00b
Posts: 5
Joined: Sat Apr 02, 2011 4:51 pm

Re: Dragon Age 2 (PC)

Post by lpss »

I still can't get the hair/beard meshes with UV maps on Blender... :[
Does anyone know a way to do it? I'm using the Blender 2.49 script as I already had Blender 2.49
figuresculptor
beginner
Posts: 33
Joined: Thu Jan 06, 2011 9:08 pm
Been thanked: 4 times

Re: Dragon Age 2 (PC)

Post by figuresculptor »

lpss wrote:I still can't get the hair/beard meshes with UV maps on Blender... :[
Does anyone know a way to do it? I'm using the Blender 2.49 script as I already had Blender 2.49
lpss:

The same problem exists with the 2.5.6 script - I've actually combed through the beard and hair, and it just looks like all the UVs are set to 0,0 or 1,0. I've looked through the vertex data for other potential UV data, and found nothing. I'm not sure what's going on with the hair or beards, but it's not anything you're doing - it is the script.
figuresculptor
beginner
Posts: 33
Joined: Thu Jan 06, 2011 9:08 pm
Been thanked: 4 times

Re: Dragon Age 2 (PC)

Post by figuresculptor »

Blender 2.57, which is the Release Candidate for the 2.5 branch, was posted a few days ago… and broke compatibility with most scripts.

I've updated my 2.56 script to work with 2.57. I haven't had time to add the armature parsing yet, but I did add an option to rotate the object to face front.

NB: For some reason, this isn't working correctly as an addon right now. If you open the script in Blender and run it, it will add a menu item. When I've figured out why it doesn't work as an addon, I'll post the fixed version.

Code: Select all

bl_addon_info = {
	"name": "Import Dragon Age 2 Mesh files (.msh)",
	"author": "FigureSculptor",
	"version": (2, 1),
	"blender": (2, 5, 7),
	"api": 35622,
	"location": "File > Import ",
	"description": "Import Dragon Age 2 Mes (.msh)",
	"warning": "",
	"wiki_url": "",
	"tracker_url": "",
	"category": "Import-Export"}

"""
Version': '1.0' 

This is a straight port of the 3DS Max Script from this forum
posting:

http://forum.xentax.com/viewtopic.php?f=16&t=6119&hilit=dragon+age+2

This version is based on the script posted with this timestamp

Posted: Mon Mar 14, 2011 3:22 am 

All credit to chrrox for figuring the format out.

"""

import bpy
import mathutils
import os
import sys
import string
import math
import re
from string import *
from struct import *
from math import *
import mathutils
from bpy.props import *


DEBUGLOG = False
LONGSIZE = 4
FLOATSIZE = 4
HALFFLOATSIZE = 2
SHORTSIZE = 2

def unpack_list(list_of_tuples):
	l = []
	for t in list_of_tuples:
		l.extend(t)
	return l

def halfToFloatPrivate(h):
	s = int((h >> 15) & 0x00000001)		# sign
	e = int((h >> 10) & 0x0000001f)		# exponent
	f = int(h &			0x000003ff)		# fraction

	if e == 0:
		if f == 0:
			return int(s << 31)
		else:
			while not (f & 0x00000400):
				f <<= 1
				e -= 1
			e += 1
			f &= ~0x00000400
	elif e == 31:
		if f == 0:
			return int((s << 31) | 0x7f800000)
		else:
			return int((s << 31) | 0x7f800000 | (f << 13))

	e = e + (127 -15)
	f = f << 13

	return int((s << 31) | (e << 23) | f)

def halfToFloat(h):
	result = halfToFloatPrivate(h)
	str = pack('I',result)
	f = unpack('f', str)
	return f[0]
	
def mshImport(infile, props):
	global DEBUGLOG
	print ("--------------------------------------------------")
	print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------")
	print ("--------------------------------------------------")
	print ("Importing file: ", infile)
	
	mshfile = open(infile,'rb')
	if (DEBUGLOG):
		logpath = infile.replace(".msh", ".txt")
		print("logpath:",logpath)
		logf = open(logpath,'w')
		
	def printlog(strdata):
		if (DEBUGLOG):
			logf.write(strdata + "\n")

	basename = os.path.basename(infile)	
	
	printlog("basename:" + basename)
	
	mshfile.seek(0x1A0)
	baseoff = 0x1A0
	

	namebase, garbage, unkbase, vertbase, facebase, garbage1, garbage2, meshcount = unpack('<8l', mshfile.read(8*LONGSIZE))

	printlog("baseoff: " + str(baseoff))
	printlog("unkbase: " + str(unkbase))
	printlog("vertbase: " + str(vertbase))
	printlog("facebase: " + str(facebase))
	printlog("meshcount: " + str(meshcount))
	
	vertSizeArray = []
	vertCountArray = []
	faceCountArray = []
	vertPosArray = []
	facePosArray = []
	
	for i in range(meshcount):
		printlog("assessing mesh " + str(i))
		float01, float02, float03, float04, float11, float12, float13, float14, float21, float22, float23, float34 = unpack('<12f', mshfile.read(12*FLOATSIZE))
		unk01, vertSize, vertCount, faceCount, vertPos, facePos, unk2, long01, long02, long03, long04, vertCount2 = unpack('<12l', mshfile.read(12*LONGSIZE))
		printlog("\tvertsize: " + str(vertSize))
		printlog("\tvertCount: " + str(vertCount))
		printlog("\tfaceCount: " + str(faceCount))
		printlog("\tvertPos: " + str(vertPos))
		printlog("\tfacePos: " + str(facePos))
		vertSizeArray.append(vertSize)
		vertCountArray.append(vertCount)
		faceCountArray.append(faceCount)
		vertPosArray.append(vertPos)
		facePosArray.append(facePos)
	
	faceStart = baseoff + facebase + 4
	vertStart = baseoff + vertbase + 4
	nameStart = baseoff + namebase
	unkStart = baseoff + unkbase
	
	if (DEBUGLOG):
		printlog("faceStart: " + str(faceStart))
		printlog("vertStart: " + str(vertStart))
		printlog("nameStart: " + str(nameStart))
		printlog("unkStart: " + str(unkStart))
	
	for a in range(meshcount):
		me_ob = bpy.data.meshes.new(basename + str(a))
		printlog(("New Mesh = " + me_ob.name))
		vertArray = []
		uvArray = []
		normalArray = []
		faceArray = []
		printlog("===Offset = " + str(vertStart + vertPosArray[a]))
		printlog("===vertStrt = " + str(vertStart))
		printlog("===vertPos[a] = " + str(vertPosArray[a]))
		mshfile.seek(vertStart + vertPosArray[a])
		for b in range(vertCountArray[a]):
			data = mshfile.read(3*FLOATSIZE)
			vx, vy, vz = unpack('<3f', data)
			bytesOfUnknown = (vertSizeArray[a] - 16)
			unknown = mshfile.read(bytesOfUnknown)
			tu_h = unpack('H', mshfile.read(HALFFLOATSIZE))
			tv_h = unpack('H', mshfile.read(HALFFLOATSIZE))
			tu = halfToFloat(tu_h[0])
			tv = halfToFloat(tv_h[0])
			vertArray.extend([(vx, vy, vz)])
			uvArray.extend([(tu, tv)])
	
		printlog("facePosArray: " + str(facePosArray[a]))
		mshfile.seek(faceStart + facePosArray[a] * 2)
		faceLen = faceCountArray[a]
		
		printlog("faceCountArray length: " + str(faceLen))
		
		if (faceLen > 0):
			faceLen = faceLen / 3
		else:
			faceLen = 0
		printlog("facelen: " + str(faceLen))
		
		faceUVArray = []
		
		for b in range(int(faceLen)):
			f1, f2, f3 = unpack('<3h', mshfile.read(3*SHORTSIZE))
			if (f1 < len(vertArray) and f2 < len(vertArray) and f3 < len(vertArray)):
				faceArray.extend([f1, f2, f3, 0])
				faceUVArray.extend([(uvArray[f1], uvArray[f2], uvArray[f3])])
			#printlog("Adding array:" + str(f1) + ", " + str(f2) + ", " + str(f3))
			
		printlog("vertArray length: " + str(len(vertArray)))
		printlog("faceArray length: " + str(len(faceArray)))
		me_ob.vertices.add(len(vertArray))
		me_ob.faces.add(len(faceArray)//4)
		me_ob.vertices.foreach_set("co", unpack_list(vertArray))
		me_ob.faces.foreach_set("vertices_raw", faceArray)
		me_ob.faces.foreach_set("use_smooth", [False] * len(me_ob.faces))
		
		texture = []
		texturename = basename + "_tex_" + str(a)
		if (len(faceUVArray) > 0):
			uvtex = me_ob.uv_textures.new() #add one uv texture
			uvtex.name = "Imported UV"
			for i, face in enumerate(me_ob.faces):
				blender_tface= uvtex.data[i] #face
				blender_tface.uv1 = faceUVArray[i][0] #uv = (0,0)
				blender_tface.uv2 = faceUVArray[i][1] #uv = (0,0)
				blender_tface.uv3 = faceUVArray[i][2] #uv = (0,0)
			texture.append(uvtex)
		
		materialname = "mat"
		materials = []

		matdata = bpy.data.materials.new(materialname)
		matdata.diffuse_color=(float(0.04),float(0.08),float(0.44))#blue color
		
		texdata = None
		texIndex = len(bpy.data.textures) - 1
		if (texIndex >= 0):
			texdata = bpy.data.textures[len(bpy.data.textures)-1]
			if (texdata != None):
				texdata.name = "texturelist1"
				matdata.active_texture = texdata
		materials.append(matdata)
		for material in materials:
			#add material to the mesh list of materials
			me_ob.materials.append(material)
			
		me_ob.update()
		
		obmesh = bpy.data.objects.new(basename,me_ob)
		bpy.context.scene.objects.link(obmesh)
		if props.rotate_z_180:
			mat_z180 = mathutils.Matrix.Rotation(math.pi, 4, 'Z')
			me_ob.transform(mat_z180)
		bpy.context.scene.update()
	
def getInputFilename(filename, props):
	checktype = filename.split('\\')[-1].split('.')[1]
	print ("------------",filename)
	if checktype.upper() != 'MSH':
		print ("  Selected file = ",filename)
		raise (IOError, "The selected input file is not a *.msh file")
	mshImport(filename, props)

class IMPORT_OT_dragonage_mesh(bpy.types.Operator):
	'''Import from Dragon Age Mesh file (.msh)'''
	bl_idname = "import_scene.dragonage_msh"
	bl_description = 'Import from Dragon Age mesh file (.msh)'
	bl_label = "Import Dragon Age Mesh"
	bl_space_type = "PROPERTIES"
	bl_region_type = "WINDOW"
	
	rotate_z_180 = BoolProperty(name="Rotate Z 180",
							description="Rotate 180 degrees around Z so model faces front.",
							default=True)


	# List of operator properties, the attributes will be assigned
	# to the class instance from the operator settings before calling.
	filepath = StringProperty(name="File Path", description="Filepath used for importing the MSH file", maxlen= 1024, default= "", subtype='FILE_PATH')

	def execute(self, context):
		props = self.properties
		getInputFilename(self.filepath, props)
		return {'FINISHED'}

	def invoke(self, context, event):
		wm = context.window_manager
		wm.fileselect_add(self)
		return {'RUNNING_MODAL'}

def menu_func(self, context):
	self.layout.operator(IMPORT_OT_dragonage_mesh.bl_idname, text="Dragon Age 2 Mesh (.msh)")


def register():
	bpy.utils.register_module(__name__)

	bpy.types.INFO_MT_file_import.append(menu_func)


def unregister():
	bpy.utils.unregister_module(__name__)
	bpy.types.INFO_MT_file_import.remove(menu_func)


if __name__ == "__main__":
	register()
Last edited by figuresculptor on Wed Apr 06, 2011 12:56 am, edited 1 time in total.
lpss
ultra-n00b
Posts: 5
Joined: Sat Apr 02, 2011 4:51 pm

Re: Dragon Age 2 (PC)

Post by lpss »

figuresculptor wrote:
lpss wrote:I still can't get the hair/beard meshes with UV maps on Blender... :[
Does anyone know a way to do it? I'm using the Blender 2.49 script as I already had Blender 2.49
lpss:

The same problem exists with the 2.5.6 script - I've actually combed through the beard and hair, and it just looks like all the UVs are set to 0,0 or 1,0. I've looked through the vertex data for other potential UV data, and found nothing. I'm not sure what's going on with the hair or beards, but it's not anything you're doing - it is the script.
Thanks, figuresculptor! I hope you guys find the UV maps soon. :keke:
figuresculptor
beginner
Posts: 33
Joined: Thu Jan 06, 2011 9:08 pm
Been thanked: 4 times

Re: Dragon Age 2 (PC)

Post by figuresculptor »

lpss wrote:Thanks, figuresculptor! I hope you guys find the UV maps soon. :keke:
We have… for everything else. I honestly think they're doing something weird at runtime with the hair and beards, so I'm not sure we're ever going to find them.
Szkaradek123
mega-veteran
mega-veteran
Posts: 292
Joined: Wed May 05, 2010 8:21 pm
Location: Poland Głogów
Has thanked: 21 times
Been thanked: 742 times

Re: Dragon Age 2 (PC)

Post by Szkaradek123 »

Update for Blender249 importer:
- add uv-mapping for hair and beards.
You do not have the required permissions to view the files attached to this post.
lpss
ultra-n00b
Posts: 5
Joined: Sat Apr 02, 2011 4:51 pm

Re: Dragon Age 2 (PC)

Post by lpss »

You rock, dude!
bullet333
ultra-n00b
Posts: 1
Joined: Sat May 07, 2011 3:41 pm

Re: Dragon Age 2 (PC)

Post by bullet333 »

I got the script to work in 3ds max, but I'm having a lot of trouble finding the face and hair textures. Can someone please help me out?

Oh and I'm also trying to get the Blender script to work as well, but I'm a noob and don't know how to create that .py file you guys are talking about. I've tried using those .blend files, but it just doesn't give me the option to import .msh files.
superchickensoup
ultra-n00b
Posts: 2
Joined: Fri May 13, 2011 1:32 pm

Re: Dragon Age 2 (PC)

Post by superchickensoup »

Hi, is it possible for anyone to e-mail me a obj of flemeth from da2. I just need the mesh and textures. Im building a high poly version and need the mesh for referance.
I managed to extract the msh files but could not find flemeth's model.
You can see my work Here
http://www.airflow3d.com
Any help would be appc.

E-mail
robangol @ [email protected]
superchickensoup @ [email protected]

Huge thanks.
anzolino
ultra-n00b
Posts: 5
Joined: Sat May 21, 2011 1:34 pm

Re: Dragon Age 2 (PC)

Post by anzolino »

Hi guys,
thanks a lot for your great work. It works really fine.

But (there is always a but... ;o)) now I've got the export problem. I didn't find a solution to export the mesh (i.e. as fbx) and to convert the exported file. The model doesn't appear in the game (DA2). So my question to the experts: exists a solution for direct model exporting to a DA2 msh file?

So long
anzolino
figuresculptor
beginner
Posts: 33
Joined: Thu Jan 06, 2011 9:08 pm
Been thanked: 4 times

Re: Dragon Age 2 (PC)

Post by figuresculptor »

anzolino wrote:I didn't find a solution to export the mesh (i.e. as fbx) and to convert the exported file. The model doesn't appear in the game (DA2). So my question to the experts: exists a solution for direct model exporting to a DA2 msh file?
The DA2 tools should allow you to convert from an OBJ, DAE, or FBX file to a Mesh. There's also the old IOTools for Blender that contains a .msh exporter, but I don't believe it's been updated for DA2.

I believe that PyGFF also has tools for converting and packaging files. I've only used it to import objects, but it may be able to get objects back in the game. http://social.bioware.com/project/1936/
anzolino
ultra-n00b
Posts: 5
Joined: Sat May 21, 2011 1:34 pm

Re: Dragon Age 2 (PC)

Post by anzolino »

Yes, the IO Tools does'nt work.
I've tried the DA2 Tools to convert the FBX to MSH and also to convert to XML for compiling with the DAO ResourceBuild processors. I'm also using the PyGFF for attribute changes etc. I will test if PyGFF can convert too.
Maybe I miss something else.
anzolino
ultra-n00b
Posts: 5
Joined: Sat May 21, 2011 1:34 pm

Re: Dragon Age 2 (PC)

Post by anzolino »

I've heard from others that the DA2Tools also doesn't work. I didn't found any convert options in pyGFF. So it seems there don't exists a convert solution :[
User avatar
OriginOfWaves
beginner
Posts: 38
Joined: Wed Jun 08, 2011 1:58 pm
Location: Nish, Serbia
Has thanked: 25 times
Been thanked: 11 times
Contact:

Re: Dragon Age 2 (PC)

Post by OriginOfWaves »

thanks so much for this importer guys
trumpdog
ultra-n00b
Posts: 5
Joined: Sun Aug 15, 2010 4:28 am

Re: Dragon Age 2 (PC)

Post by trumpdog »

There is one import/export script for lightwave 3d here http://social.bioware.com/project/2246/
I dont know anything about it or the capabilities of the plug in. All i know is that everything done to the model has to be done in Lightwave, for example....you cant do anything in blender and export it to lightwave format or it loses its weighting and some other stuff upon import to lightwave. IMHO lightwave kinda sucks.....Havent had a successful export yet since i dont know how to use it.
Post Reply