Page 1 of 7

Dragon Age 2 (PC)

Posted: Mon Feb 21, 2011 10:14 pm
by chrrox
I am working on the mesh format it is going good so far trying to find out how to link all these files together.

Re: Dragon Age 2 (PC)

Posted: Mon Feb 21, 2011 10:23 pm
by Rimbros
Amazing preview chroxxx, good advance. Also i finally kow how the gameassasin tool works any question or help you need only ask. i posted a answer in the section of gameassassin tool too.

Re: Dragon Age 2 (PC)

Posted: Wed Feb 23, 2011 5:42 pm
by Szkaradek123
Great work
For import .msh files to Blender there is "DragonAge_Tools_020".

Re: Dragon Age 2 (PC)

Posted: Thu Feb 24, 2011 12:39 am
by chrrox
they are a new format for the second game.

Re: Dragon Age 2 (PC)

Posted: Thu Feb 24, 2011 12:49 am
by jaden
wow you rock chrrox

Re: Dragon Age 2 (PC)

Posted: Sat Feb 26, 2011 4:42 am
by sirew
what tools did you use to rip the model?

Re: Dragon Age 2 (PC)

Posted: Fri Mar 11, 2011 11:46 pm
by Erik24
sirew wrote:what tools did you use to rip the model?
answer plz

Re: Dragon Age 2 (PC)

Posted: Sun Mar 13, 2011 11:51 am
by Ares722
Probably he is working at a script to import the Dagon Age2 mesh, uv map and bones format directly into max (max script)...as he usually do.....amazing!!

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 3:22 am
by chrrox
Here is the script but i cant find any bones they must use a global skeleton somewhere but i don't know where it is.

Code: Select all

if (heapSize < 20000000) then
	heapSize = 200000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \ 
caption:"Open DA2 Model File" \
types:"DA2 Model File(*.msh)|*.msh" \
historyCategory:"DA2ObjectPresets"
f = fopen fname "rb"

fn PrintOffset Var =
(
	local Var = Var
print ("This is the offset 0x" + (bit.intAsHex Var) as string)
	Var
)
fn PrintCount Var =
(
	local Var = Var
print ("This is the Count 0x" + (bit.intAsHex Var) as string)
	Var
)

fn Readword fstream = (
return readshort fstream #unsigned
)

fn ReadFixedString bstream fixedLen =
(
	local str = ""
	for i = 1 to fixedLen do
	(
		str += bit.intAsChar (ReadByte bstream #unsigned)
	)
	str
)
fn ReadFixedUString bstream fixedLen =
(
	local str = ""
	for i = 1 to fixedLen do
	(
		str += bit.intAsChar (ReadByte bstream #unsigned)
		fseek bstream 0x1#seek_cur
	)
	str
)
 	fn convertTo32 input16 = (
 		inputAsInt = input16
 		sign = bit.get inputAsInt 16
 		exponent = (bit.shift (bit.and inputAsInt (bit.hexasint "7C00")) -10) as integer - 16
 		fraction = bit.and inputAsInt (bit.hexasint "03FF")
 		if sign==true then sign = 1 else sign = 0
 		exponentF = exponent + 127
 		--Ouput 32 bit integer representing a 32 bit float
 		outputAsFloat = bit.or (bit.or (bit.shift fraction 13) (bit.shift exponentF 23)) (bit.shift sign 31)
 		--Output Check	
 		return bit.intasfloat outputasfloat * 2
 	)

fn ReadHalfFloat fstream = (
return convertTo32(Readshort fstream)
)

struct Mesh_Info_Struct
(
	vertsize,VertCount,FaceCount,VertPos,FacePos
)

fseek f 0x1A0#seek_set
baseoff = (ftell f)
namebase = readlong f
null = readlong f
unkbase = readlong f
vertbase = readlong f
facebase = readlong f
null = readlong f
null = readlong f
MeshCount = readlong f
Mesh_Info_Array = #()
for a = 1 to MeshCount Do (
float01 = readfloat f
float02 = readfloat f
float03 = readfloat f
float04 = readfloat f
float11 = readfloat f
float12 = readfloat f
float13 = readfloat f
float14 = readfloat f
float21 = readfloat f
float22 = readfloat f
float23 = readfloat f
float34 = readfloat f
unk01 = readlong f
vertsize = readlong f
VertCount = readlong f
FaceCount = readlong f
VertPos = readlong f
FacePos = readlong f
unk02 = readlong f
long01 = readlong f
long02 = readlong f
long03 = readlong f
long04 = readlong f
VertCount2 = readlong f
append Mesh_Info_Array (Mesh_Info_Struct vertsize:vertsize VertCount:VertCount FaceCount:FaceCount VertPos:VertPos FacePos:FacePos)
)
print Mesh_Info_Array

FaceStart = (baseoff + facebase) + 4
VertStart = (baseoff + vertbase) + 4
NameStart = (baseoff + namebase)
UnkStart = (baseoff + unkbase)
/*
fseek f UnkStart#seek_set
MeshCount2 = readlong f
for a = 1 to MeshCount2 Do (
unk03 = readlong f
)
FileNameSize = readlong f
MeshFile = ReadFixedUString f FileNameSize
*/
/*
fseek f NameStart#seek_set
MeshName_Array = #()
for a = 1 to MeshCount Do (
MeshNameSize = readlong f
MeshName = ReadFixedUString f MeshNameSize
append MeshName_Array MeshName
test = readshort f
if test != -1 do (
fseek f -2#seek_cur
)
fseek f 0x90#seek_cur
print MeshName
)
print MeshName_Array
*/
for a = 1 to MeshCount Do (
Vert_array = #()
UV_array = #()
Normal_array = #()
Face_array = #()
fseek f (VertStart + Mesh_Info_Array[a].VertPos)#seek_set
for b = 1 to Mesh_Info_Array[a].VertCount Do (
if Mesh_Info_Array[a].vertsize == 40 do (
vx = readfloat f
vy = readfloat f
vz = readfloat f
unk10 = readfloat f
unk11 = readfloat f
unk12 = readfloat f
unk13 = readfloat f
unk13 = readfloat f
tu = ReadHalfFloat f
tv = ReadHalfFloat f * -1
unk13 = readfloat f

append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
if Mesh_Info_Array[a].vertsize == 36 do (
vx = readfloat f
vy = readfloat f
vz = readfloat f
unk10 = readfloat f
unk11 = readfloat f
unk12 = readfloat f
unk13 = readfloat f
unk13 = readfloat f
tu = ReadHalfFloat f
tv = ReadHalfFloat f * -1
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
if Mesh_Info_Array[a].vertsize == 32 do (
vx = readfloat f
vy = readfloat f
vz = readfloat f
unk10 = readfloat f
unk11 = readfloat f
unk12 = readfloat f
unk13 = readfloat f
tu = ReadHalfFloat f
tv = ReadHalfFloat f * -1
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
if Mesh_Info_Array[a].vertsize == 28 do (
vx = readfloat f
vy = readfloat f
vz = readfloat f
unk10 = readfloat f
unk11 = readfloat f
unk13 = readfloat f
tu = ReadHalfFloat f
tv = ReadHalfFloat f * -1
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
if Mesh_Info_Array[a].vertsize == 24 do (
vx = readfloat f
vy = readfloat f
vz = readfloat f
unk10 = readfloat f
unk11 = readfloat f
tu = ReadHalfFloat f
tv = ReadHalfFloat f * -1
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
	
)
fseek f (FaceStart + (Mesh_Info_Array[a].FacePos * 2))#seek_set
for b = 1 to Mesh_Info_Array[a].FaceCount / 3 do (
f1 = (readshort f) + 1
f2 = (readshort f) + 1
f3 = (readshort f) + 1
append Face_array [f1,f2,f3]
)

msh = mesh vertices:Vert_array faces:Face_array name:(a as string)
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count     do setTVert  msh j UV_array[j]
for j = 1 to Face_array.count   do setTVFace msh j Face_array[j]
for j = 1 to Normal_array.count do setNormal msh j Normal_array[j]

)

fclose f

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 11:30 am
by logansan25
This script for 3dmax? or extract?

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 12:00 pm
by Tosyk
logansan25 wrote:This script for 3dmax? or extract?
Max

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 7:49 pm
by figuresculptor
Chroxx - you rock.

I hope you don't mind, I ported your script to Blender 2.5.6 , for those without 3DS Max.

Thanks for all your hard work, I dunno how you figure this stuff out.

NB: Updated with fix for problem affecting certain models.

Put the code into a file with a .py extension (I used "io_import_dragon_age_2_msh.py"), then add it using the Add On tab of the User Preferences.
fs


Look later in thread for updated code

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 11:02 pm
by figuresculptor
Python script that will convert .msh to .obj file for those of you who don't like either 3DS Max or Blender, or for those who want to do batch conversions:

Code: Select all

#! /usr/bin/env python

import os
import sys
import string
import math
import re
from string import *
from struct import *
from math import *

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):

	print ("Converting file: ", infile)
	
	mshfile = open(infile,'rb')
	
	objPath = infile.replace(".msh", ".obj")
	print("\toutput file: " + objPath)
	objfile = open(objPath,'w')

	basename = os.path.basename(infile)
	# basename = os.path.splitext(infile)[0]		
	
	
	mshfile.seek(0x1A0)
	baseoff = 0x1A0
	

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

	vertSizeArray = []
	vertCountArray = []
	faceCountArray = []
	vertPosArray = []
	facePosArray = []
	
	for i in range(meshcount):
		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))
		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
	
	vertexOffset = 1
	
	for a in range(meshcount):
		objfile.write("o " + basename + str(a) + "\n")
		vertArray = []
		uvArray = []
		normalArray = []
		faceArray = []
		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)])
	
		mshfile.seek(faceStart + facePosArray[a] * 2)
		faceLen = faceCountArray[a]
		
		for i in range(len(vertArray)):
			objfile.write("v " + str(vertArray[i][0]) + " " + str(vertArray[i][1]) + " " + str(vertArray[i][2]) + "\n")
			
		for i in range(len(uvArray)):
			objfile.write("vt " + str(uvArray[i][0]) + " " + str(uvArray[i][1]) + "\n")
		
		if (faceLen > 0):
			faceLen = faceLen / 3
		else:
			faceLen = 0
		
		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)])

		for i in range(len(faceArray)):
			objfile.write("f " + str(faceArray[i][0] + vertexOffset) + "/" + str(faceArray[i][0] + vertexOffset) + " " + str(faceArray[i][1] + vertexOffset) + "/" + str(faceArray[i][1] + vertexOffset) + " " + str(faceArray[i][2] + vertexOffset) + "/" + str(faceArray[i][2] + vertexOffset) + "\n")
			
		vertexOffset = vertexOffset + (len(vertArray))
			

for grp in sys.argv[1:]:
	mshImport(grp)

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 11:22 pm
by logansan25
Who use this phyton? I am a noob in phyton!

Re: Dragon Age 2 (PC)

Posted: Mon Mar 14, 2011 11:47 pm
by sirew
Actually, what I need to do first, before putting it into blender/max?