lib3ddevil1/bindings/py3devil1geo.py

255 lines
7.9 KiB
Python
Raw Permalink Normal View History

import ctypes
import os, sys
sys.path.append(
os.path.abspath(
os.path.join(
os.path.dirname(__file__), "../../")))
from lib3ddevil1.bindings import libc
del os, sys
2018-05-16 01:12:16 +05:30
#--------------------------------------+
# Basic Struct
#--------------------------------------+
class Header(ctypes.Structure):
_pack_ = 1
_fields_ = [
("numMesh", ctypes.c_ubyte),
("unknownNumberB", ctypes.c_ubyte),
("unknownNumberC", ctypes.c_ubyte),
("unknownNumberD", ctypes.c_ubyte),
("padding", ctypes.c_int),
("unknownOffset", ctypes.c_ulonglong)
]
class MeshHeader(ctypes.Structure):
_pack_ = 1
_fields_ = [
("numBatch", ctypes.c_short),
("numVertex", ctypes.c_short),
("u", ctypes.c_uint),
("offsetBatches", ctypes.c_ulonglong),
("flags", ctypes.c_ulonglong)
]
class Coordinate(ctypes.Structure):
_pack_ = 1
_fields_ = [
("x", ctypes.c_float),
("y", ctypes.c_float),
("z", ctypes.c_float)
]
def __str__(self):
return "(%s, %s, %s)" % (str(self.x), str(self.y), str(self.z))
class UVs(ctypes.Structure):
_pack_ = 1
_fields_ = [
("u", ctypes.c_short),
("v", ctypes.c_short)
]
def __str__(self):
return "(%s, %s)" % (str(self.u), str(self.v))
class BoneIndexes(ctypes.Structure):
_pack_ = 1
_fields_ = [
("indexes", ctypes.c_ubyte * 4),
]
class BoneWeights(ctypes.Structure):
_pack_ = 1
_fields_ = [
("weights", ctypes.c_short)
]
class BatchData(ctypes.Structure):
_pack_ = 1
_fields_ = [
("numVertex", ctypes.c_short),
("uB", ctypes.c_short),
("padding", ctypes.c_uint),
("offsetPositions", ctypes.c_ulonglong),
("offsetNormals", ctypes.c_ulonglong),
("offsetUVs", ctypes.c_ulonglong),
("offsetBoneIndexes", ctypes.c_ulonglong),
("offsetBoneWeights", ctypes.c_ulonglong),
("offsets", ctypes.c_ulonglong)
]
class VertexData(ctypes.Structure):
_pack_ = 1
_fields_ = [
("positions", ctypes.POINTER(Coordinate)),
("normals", ctypes.POINTER(Coordinate)),
("u", ctypes.POINTER(UVs)),
("bi", ctypes.POINTER(BoneIndexes)),
("bw", ctypes.POINTER(BoneWeights))
]
class Batch(ctypes.Structure):
_pack_ = 1
_fields_ = [
("bd", ctypes.POINTER(BatchData)),
("vd", VertexData)
]
class Mesh(ctypes.Structure):
_pack_ = 1
_fields_ = [
("b", ctypes.POINTER(Batch))
]
class Devil1GEO_FN(ctypes.Structure):
_fields_ = [
("printheader", ctypes.CFUNCTYPE(
None,
ctypes.POINTER(Header))),
("printmeshheader", ctypes.CFUNCTYPE(
None,
ctypes.POINTER(MeshHeader))),
("printbatch", ctypes.CFUNCTYPE(
None,
ctypes.POINTER(Batch))),
("printcoordinate", ctypes.CFUNCTYPE(
None,
ctypes.POINTER(Coordinate))),
("getheader", ctypes.CFUNCTYPE(
ctypes.c_bool,
2018-05-16 01:12:16 +05:30
ctypes.POINTER(ctypes.POINTER(Header)),
ctypes.c_char_p)),
("getmeshheader", ctypes.CFUNCTYPE(
ctypes.c_bool,
ctypes.POINTER(ctypes.POINTER(MeshHeader)),
ctypes.c_uint,
ctypes.c_char_p)),
("getbatch", ctypes.CFUNCTYPE(
ctypes.c_bool,
ctypes.POINTER(Batch),
ctypes.c_uint,
ctypes.c_char_p)),
("getmesh", ctypes.CFUNCTYPE(
ctypes.c_bool,
ctypes.POINTER(Mesh),
ctypes.c_uint,
ctypes.c_char_p,
ctypes.c_uint))
]
devil1geo = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO")
del libc
2018-05-16 01:12:16 +05:30
#--------------------------------------+
# Pythonic Object
#--------------------------------------+
class pyGeoHeader:
2018-05-16 01:12:16 +05:30
def __init__(self, filedata):
self.cstruct = ctypes.pointer(Header())
ptrofptr = ctypes.byref(self.cstruct)
if filedata:
if not devil1geo.getheader(ptrofptr, filedata):
raise RuntimeError("failed to get geometry file header")
2018-05-16 01:12:16 +05:30
return
def show(self):
devil1geo.printheader(self.cstruct)
def getnummesh(self):
2018-05-16 01:12:16 +05:30
return self.cstruct.contents.numMesh
def getunknownb(self):
return self.cstruct.contents.unknownNumberB
def getunknownc(self):
return self.cstruct.contents.unknownNumberC
def getunknownd(self):
return self.cstruct.contents.unknownNumberD
def getpadding(self):
return hex(self.cstruct.contents.padding)
def getunknownoffset(self):
return hex(self.cstruct.contents.unknownOffset)
class pyMeshHeader:
2018-05-16 01:12:16 +05:30
def __init__(self, i, filedata):
self.cstruct = ctypes.pointer(MeshHeader())
ptrofptr = ctypes.byref(self.cstruct)
if filedata:
if not devil1geo.getmeshheader(ptrofptr, i, filedata):
raise RuntimeError("failed to get mesh header #" + str(i))
2018-05-16 01:12:16 +05:30
return
pass
def show(self):
devil1geo.printmeshheader(self.cstruct)
def getnumbatch(self):
2018-05-16 01:12:16 +05:30
return self.cstruct.contents.numBatch
def getnumvertex(self):
return self.cstruct.contents.numVertex
def getunknown(self):
return hex(self.cstruct.contents.u)
def getoffsetbatches(self):
return self.cstruct.contents.offsetBatches
def getflags(self):
return self.cstruct.contents.flags
class pyMesh:
2018-05-16 01:12:16 +05:30
def __init__(self, i, filedata):
self.cstruct = Mesh()
if filedata:
mh = pyMeshHeader(i, filedata)
2018-05-16 01:12:16 +05:30
# allocate memory for the size of batch * number of batches
memsize = ctypes.sizeof(Batch) * mh.getnumbatch()
2018-05-16 01:12:16 +05:30
self.cstruct.b = ctypes.cast(
ctypes.create_string_buffer(memsize),
ctypes.POINTER(Batch))
if not devil1geo.getmesh(
ctypes.byref(self.cstruct),
i,
filedata,
len(filedata)):
raise RuntimeError("failed to get mesh")
2018-05-16 01:12:16 +05:30
del mh, memsize
return
def show(self):
if self.cstruct.b:
devil1geo.printbatch(self.cstruct.b)
else:
print("nothing to show")
def getbatchdata(self):
return self.cstruct.b.contents.bd.contents
def getpositions(self):
length = self.cstruct.b.contents.bd.contents.numVertex
return self.cstruct.b.contents.vd.positions[:length]
def getnormals(self):
length = self.cstruct.b.contents.bd.contents.numVertex
return self.cstruct.b.contents.vd.normals[:length]
def getuvs(self):
length = self.cstruct.b.contents.bd.contents.numVertex
return self.cstruct.b.contents.vd.u[:length]
def getboneindexes(self):
length = self.cstruct.b.contents.bd.contents.numVertex
return self.cstruct.b.contents.vd.bi[:length]
def getboneweights(self):
length = self.cstruct.b.contents.bd.contents.numVertex
return self.cstruct.b.contents.vd.bw[:length]