Important information: this site is currently scheduled to go offline indefinitely by end of the year.
Dragon Age 2 (PC)
-
- Moderator
- Posts: 2602
- Joined: Sun May 18, 2008 3:01 pm
- Has thanked: 57 times
- Been thanked: 1422 times
Dragon Age 2 (PC)
I am working on the mesh format it is going good so far trying to find out how to link all these files together.
You do not have the required permissions to view the files attached to this post.
- Rimbros
- ultra-veteran
- Posts: 495
- Joined: Fri Jul 09, 2010 12:23 am
- Has thanked: 41 times
- Been thanked: 16 times
Re: Dragon Age 2 (PC)
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.
Renders Art by Rimbros
http://s303.photobucket.com/albums/nn12 ... E/Renders/
Personal Game repository samples, send PM
http://s303.photobucket.com/albums/nn12 ... E/Renders/
Personal Game repository samples, send PM
-
- 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
-
- Moderator
- Posts: 2602
- Joined: Sun May 18, 2008 3:01 pm
- Has thanked: 57 times
- Been thanked: 1422 times
-
- Moderator
- Posts: 2602
- Joined: Sun May 18, 2008 3:01 pm
- Has thanked: 57 times
- Been thanked: 1422 times
Re: Dragon Age 2 (PC)
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
-
- veteran
- Posts: 138
- Joined: Mon Oct 04, 2010 1:15 am
- Has thanked: 5 times
- Been thanked: 3 times
- Tosyk
- double-veteran
- Posts: 1027
- Joined: Thu Oct 22, 2009 10:24 am
- Location: Russia, Siberia
- Has thanked: 269 times
- Been thanked: 154 times
- Contact:
-
- beginner
- Posts: 33
- Joined: Thu Jan 06, 2011 9:08 pm
- Been thanked: 4 times
Re: Dragon Age 2 (PC)
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
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
Last edited by figuresculptor on Tue Mar 15, 2011 5:02 am, edited 2 times in total.
-
- beginner
- Posts: 33
- Joined: Thu Jan 06, 2011 9:08 pm
- Been thanked: 4 times
Re: Dragon Age 2 (PC)
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)
Last edited by figuresculptor on Tue Mar 15, 2011 5:03 am, edited 1 time in total.
-
- veteran
- Posts: 138
- Joined: Mon Oct 04, 2010 1:15 am
- Has thanked: 5 times
- Been thanked: 3 times