God Of War 3
Добавлено: 24 окт 2014, 22:23
Код: Выделить всё
#############################################################
# God of War III model import script by maver1k_XVII #
#############################################################
# Version 0.65 beta #
#############################################################
# Special thanks to: #
# * 3dformat from http://ps23dformat.wikispaces.com for #
# the gow3WAD.bms script which I used as a base for further #
# research of this format #
# * HaCKer_UTD for finding a way to decode triangle indices #
# and for the help with various other issues #
#############################################################
from inc_noesis import *
from decimal import *
import noesis
import rapi
def registerNoesisTypes():
handle = noesis.register("God of War 3 model", ".wad")
noesis.setHandlerTypeCheck(handle, noepyCheckType)
noesis.setHandlerLoadModel(handle, noepyLoadModel) #see also noepyLoadModelRPG
#noesis.setHandlerWriteModel(handle, noepyWriteModel)
#noesis.setHandlerWriteAnim(handle, noepyWriteAnim)
noesis.logPopup()
return 1
NOEPY_HEADER = ""
#check if it's this type based on the data
def noepyCheckType(data):
return 1
#load the model
def noepyLoadModel(data, mdlList):
ctx = rapi.rpgCreateContext()
model = GOWIII_WAD(data)
mdlList.append(model.mdl)
rapi.rpgClearBufferBinds()
return 1
class GOWIII_WAD:
def __init__(self, data):
self.bs = NoeBitStream(data)
self.bs.setEndian(NOE_BIGENDIAN)
rapi.rpgSetOption(noesis.RPGOPT_BIGENDIAN, 1)
rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1)
self.FileInfo = []
self.TriGrpInfo = []
self.boneList = []
#self.animList = []
self.matList = []
self.texList = []
self.meshInfoTmp = []
self.MeshNum = 0
self.__parse__()
return
def __parse__(self):
filesize = self.bs.getSize()
filesizeDiv4 = filesize//4
off2lastMesh = 0
for i in range(0, filesizeDiv4-1):
Temp = self.bs.readUInt64()
offset = self.bs.tell()
if (Temp == 0xFFFFFF9C00000000) or (Temp == 0xFFFFFF8C00000000):
print('Model data found at offset {}...'.format(hex(offset - 0x8)))
off2lastMesh = offset
self.MeshNum += 1
self.Vertex(offset - 0x8)
#Temporary code to only view selected mesh
"""if self.MeshNum == 3:
self.Vertex(offset - 0x8)
else:
continue
self.bs.seek(offset, NOESEEK_ABS)"""
#break
self.bs.seek(offset - 0x4, NOESEEK_ABS)
#self.FindSkeleton(filesize, off2lastMesh)
self.mdl = rapi.rpgConstructModel()
self.mdl.setModelMaterials(NoeModelMaterials(self.texList, self.matList))
self.mdl.setBones(self.boneList)
#self.Animations()
#self.mdl.setAnims(self.Animations())
return
def Vertex(self, off2vtx):
self.meshInfoTmp = []
self.bs.seek(off2vtx - 0x3C, NOESEEK_ABS)
#VtxBytes = 0x18
VtxNum = self.bs.readUShort()
IdxNum = self.bs.readUShort()
self.bs.seek(0x8, NOESEEK_REL)
IdxOff = self.bs.readUInt()
TempOff = self.bs.tell()
self.bs.seek(IdxOff - 0x4, NOESEEK_REL)
IdxOff = self.bs.tell()
self.bs.seek(TempOff, NOESEEK_ABS)
IdxSize = self.bs.readUShort()
self.bs.seek(0x6, NOESEEK_REL)
VtxOff = self.bs.readInt()
self.bs.seek(0x4, NOESEEK_REL)
VtxSize = self.bs.readUShort()
self.bs.seek(VtxOff - 0xA, NOESEEK_REL)
VtxBytes = VtxSize//VtxNum
print(hex(self.bs.tell()))
print(VtxNum)
if VtxNum < 6:
return
elif (VtxNum == 512) or (VtxNum == 511):
TempOff = self.bs.tell()
VtxNum = self.ValidateVtxNum(off2vtx - 0x44)
self.bs.seek(TempOff, NOESEEK_ABS)
print(VtxNum)
#print(self.meshInfoTmp)
else:
meshInf = [VtxNum, IdxNum, IdxOff, IdxSize, ]
self.meshInfoTmp.append(meshInf)
#print(self.meshInfoTmp)
VtxOffCurr = self.bs.tell()
if VtxNum % 2 == 0:
UVOffCurr = VtxOffCurr + VtxNum * VtxBytes
else:
UVOffCurr = VtxOffCurr + VtxNum * VtxBytes + 0x8
self.bs.seek(off2vtx - 0x4, NOESEEK_ABS)
WeightOffCurr = self.bs.readInt()
if WeightOffCurr != 0:
WeightOffCurr += off2vtx - 0x4
rapi.rpgSetMaterial(str(self.MeshNum))
material = NoeMaterial(str(self.MeshNum), "")
#material.setTexture('0')
material.setDiffuseColor(NoeVec4([1.0, 1.0, 1.0, 0.0]))
material.setDefaultBlend(0)
self.matList.append(material)
for MeshNum in range(0, len(self.meshInfoTmp)):
if MeshNum != 0:
if self.meshInfoTmp[MeshNum-1][0] % 2 != 0:
VtxOffCurr += 0x8
#UVOffCurr += 0x8
self.bs.seek(VtxOffCurr, NOESEEK_ABS)
vtxBuff = self.bs.readBytes(self.meshInfoTmp[MeshNum][0]*VtxBytes)
rapi.rpgBindPositionBuffer(vtxBuff, noesis.RPGEODATA_FLOAT, VtxBytes, 0)
#if VtxBytes > 0x16:
#rapi.rpgBindNormalBuffer(vtxBuff, noesis.RPGEODATA_FLOAT, VtxBytes, 0xC)
VtxOffCurr += self.meshInfoTmp[MeshNum][0]*VtxBytes
self.bs.seek(UVOffCurr, NOESEEK_ABS)
uvBuff = self.bs.readBytes(self.meshInfoTmp[MeshNum][0]*0x8)
rapi.rpgBindUV1Buffer(uvBuff, noesis.RPGEODATA_FLOAT, 0x8)
UVOffCurr += self.meshInfoTmp[MeshNum][0]*0x8
self.bs.seek(self.meshInfoTmp[MeshNum][2], NOESEEK_ABS)
edgeData = self.bs.readBytes(self.meshInfoTmp[MeshNum][3])
edgeDecomp = rapi.decompressEdgeIndices(edgeData, self.meshInfoTmp[MeshNum][1])
for i in range(0, self.meshInfoTmp[MeshNum][1]):
t = edgeDecomp[i*2]
edgeDecomp[i*2] = edgeDecomp[i*2 + 1]
edgeDecomp[i*2 + 1] = t
rapi.rpgCommitTriangles(edgeDecomp, noesis.RPGEODATA_USHORT, self.meshInfoTmp[MeshNum][1], noesis.RPGEO_TRIANGLE, 1)
#if WeightOffCurr != 0:
#self.bs.seek(WeightOffCurr, NOESEEK_ABS)
#weightBuff = self.bs.readBytes(VtxNum*0x8)
#rapi.rpgBindBoneIndexBuffer(weightBuff, noesis.RPGEODATA_BYTE, 4*fw.weightsPerVert, fw.weightsPerVert)
#rapi.rpgBindBoneWeightBuffer(weightBuff, noesis.RPGEODATA_BYTE, 4*fw.weightsPerVert, fw.weightsPerVert)
return
def ValidateVtxNum(self, off2vtx):
self.bs.seek(off2vtx, NOESEEK_ABS)
VtxNumTrue = 0
ID = self.bs.readByte()
self.bs.seek(off2vtx, NOESEEK_ABS)
for i in range(0, 0xFF):
#self.bs.seek(0x14, NOESEEK_REL)
Temp1 = self.bs.readByte()
if Temp1 == ID:
self.bs.seek(0x7, NOESEEK_REL)
VtxNumTmp = self.bs.readShort()
IdxNumTmp = self.bs.readShort()
self.bs.seek(0x8, NOESEEK_REL)
IdxOff = self.bs.readUInt()
TempOff = self.bs.tell()
self.bs.seek(IdxOff - 0x4, NOESEEK_REL)
IdxOff = self.bs.tell()
self.bs.seek(TempOff, NOESEEK_ABS)
IdxSize = self.bs.readShort()
meshInf = [VtxNumTmp, IdxNumTmp, IdxOff, IdxSize, ]
self.meshInfoTmp.append(meshInf)
VtxNumTrue += VtxNumTmp
self.bs.seek(0x46, NOESEEK_REL)
else:
break
#self.bs.seek(off2vtx, NOESEEK_ABS)
return VtxNumTrue
def FindSkeleton(self, filesize, offset):
self.bs.seek(offset, NOESEEK_ABS)
filesizeDiv4 = (filesize - offset)//4
for i in range(0, filesizeDiv4-1):
Temp = self.bs.readUInt()
offTmp = self.bs.tell()
if (Temp == 0x00010001):
self.bs.seek(0x14, NOESEEK_REL)
Temp = self.bs.readUInt()
if (Temp == 0xFFFFFFFF):
print('Skeleton data found at offset {}...'.format(hex(offTmp - 0x4)))
self.Skeleton(offTmp - 0x4)
break
else:
self.bs.seek(offTmp, NOESEEK_ABS)
return
def Skeleton(self, off2skel):
self.bs.seek(off2skel, NOESEEK_ABS)
self.bs.seek(0x4, NOESEEK_REL)
BoneNum = self.bs.readInt()
self.bs.seek(0x8, NOESEEK_REL)
MatxOffCurr = self.bs.readInt()
MatxOffCurr += self.bs.tell() - 0x4
self.bs.seek(BoneNum*0x8, NOESEEK_REL)
NameOffCurr = self.bs.tell()
for i in range(0, BoneNum):
self.bs.seek(NameOffCurr, NOESEEK_ABS)
boneName = self.bs.readString()
NameOffCurr += 0x38
#self.bs.seek(MatxOffCurr, NOESEEK_ABS)
BoneMatrix = [[1,0,0,0,], [0,1,0,0,], [0,0,1,0,], [0,0,0,1,],]
BoneMatrix = NoeMat44(BoneMatrix)
"""for j in range(0, 4):
Vec4 = NoeVec4.fromBytes(self.bs.readBytes(16))
BoneMatrix[j] = Vec4"""
BoneMatrix = BoneMatrix.toMat43()
#MatxOffCurr += 0x40
if i == 0:
newBone = NoeBone(i, boneName, BoneMatrix, None, -1)
else:
newBone = NoeBone(i, boneName, BoneMatrix, None, 0)
print(newBone)
self.boneList.append(newBone)
return
Код: Выделить всё
# God of War 3 texture extractor by maver1k_XVII
from inc_noesis import *
import noesis
import rapi
#import str
def registerNoesisTypes():
handle = noesis.register("God of War 3 texture archive", ".ts")
noesis.setHandlerTypeCheck(handle, noepyCheckType)
noesis.setHandlerExtractArc(handle, GoW3ExtractArc)
#noesis.logPopup()
return 1
#check if it's this type based on the data
def noepyCheckType(data):
return 1
headerOffsets = []
textureOffsets = []
textureNames = []
#load the archive
def GoW3ExtractArc(fileName, fileLen, justChecking):
with open(fileName, "rb") as TS:
ctx = rapi.rpgCreateContext()
if justChecking:
return 1
WAD = NoeBitStream(rapi.loadPairedFile("God of War 3 model", ".wad"))
WAD.setEndian(NOE_BIGENDIAN)
texNum = 0
fileSize = WAD.getSize()
fileSizeDiv4 = fileSize//4
for i in range(0, fileSizeDiv4-1):
Temp = WAD.readInt()
if Temp == 0x44445320: #1145328416:
texNum = texNum+1
headerOffsets.append(i*4)
WAD.seek(headerOffsets[texNum-1]-16, NOESEEK_ABS)
textureOffsets.append(WAD.readInt())
WAD.seek(headerOffsets[texNum-1]+4, NOESEEK_ABS)
print('Texture number - {}'.format(texNum))
if texNum != 0:
for i in range(0, texNum-2):
if textureOffsets[i] != -1:
WAD.seek(headerOffsets[i], NOESEEK_ABS)
ddsHeader = WAD.readBytes(0x80)
if textureOffsets[i+1] - textureOffsets[i] > 0:
ddsImage = TS.read(textureOffsets[i+1] - textureOffsets[i])
else:
q = i + 1
Temp = textureOffsets[i+1]
while (Temp < 0) & (q < texNum - 1):
Temp = textureOffsets[q]
q = q + 1
if Temp > 0:
ddsImage = TS.read(Temp - textureOffsets[i])
else:
ddsImage = TS.read(fileLen - textureOffsets[i])
rapi.exportArchiveFile('{}.dds'.format(i), ddsHeader+ddsImage)
rapi.rpgClearBufferBinds()
return 1
Tosyk писал(а):спс. а поправить руками uv реально?
а кости реально вытащить?