mirror of
https://notabug.org/scuti/lib3ddevil1
synced 2024-11-29 10:12:02 +05:30
255 lines
7.9 KiB
Python
255 lines
7.9 KiB
Python
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
|
|
|
|
#--------------------------------------+
|
|
# 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,
|
|
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
|
|
|
|
#--------------------------------------+
|
|
# Pythonic Object
|
|
#--------------------------------------+
|
|
|
|
class pyGeoHeader:
|
|
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")
|
|
return
|
|
|
|
def show(self):
|
|
devil1geo.printheader(self.cstruct)
|
|
|
|
def getmeshno(self):
|
|
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:
|
|
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))
|
|
return
|
|
pass
|
|
|
|
def show(self):
|
|
devil1geo.printmeshheader(self.cstruct)
|
|
|
|
def getbatchno(self):
|
|
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:
|
|
def __init__(self, i, filedata):
|
|
self.cstruct = Mesh()
|
|
if filedata:
|
|
mh = pyMeshHeader(i, filedata)
|
|
# allocate memory for the size of batch * number of batches
|
|
memsize = ctypes.sizeof(Batch) * mh.getbatchno()
|
|
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")
|
|
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]
|