py3devil1geo.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import ctypes
  2. import os, sys
  3. sys.path.append(
  4. os.path.abspath(
  5. os.path.join(
  6. os.path.dirname(__file__), "../../")))
  7. from lib3ddevil1.bindings import libc
  8. del os, sys
  9. #--------------------------------------+
  10. # Basic Struct
  11. #--------------------------------------+
  12. class Header(ctypes.Structure):
  13. _pack_ = 1
  14. _fields_ = [
  15. ("numMesh", ctypes.c_ubyte),
  16. ("unknownNumberB", ctypes.c_ubyte),
  17. ("unknownNumberC", ctypes.c_ubyte),
  18. ("unknownNumberD", ctypes.c_ubyte),
  19. ("padding", ctypes.c_int),
  20. ("unknownOffset", ctypes.c_ulonglong)
  21. ]
  22. class MeshHeader(ctypes.Structure):
  23. _pack_ = 1
  24. _fields_ = [
  25. ("numBatch", ctypes.c_short),
  26. ("numVertex", ctypes.c_short),
  27. ("u", ctypes.c_uint),
  28. ("offsetBatches", ctypes.c_ulonglong),
  29. ("flags", ctypes.c_ulonglong)
  30. ]
  31. class Coordinate(ctypes.Structure):
  32. _pack_ = 1
  33. _fields_ = [
  34. ("x", ctypes.c_float),
  35. ("y", ctypes.c_float),
  36. ("z", ctypes.c_float)
  37. ]
  38. def __str__(self):
  39. return "(%s, %s, %s)" % (str(self.x), str(self.y), str(self.z))
  40. class UVs(ctypes.Structure):
  41. _pack_ = 1
  42. _fields_ = [
  43. ("u", ctypes.c_short),
  44. ("v", ctypes.c_short)
  45. ]
  46. def __str__(self):
  47. return "(%s, %s)" % (str(self.u), str(self.v))
  48. class BoneIndexes(ctypes.Structure):
  49. _pack_ = 1
  50. _fields_ = [
  51. ("indexes", ctypes.c_ubyte * 4),
  52. ]
  53. class BoneWeights(ctypes.Structure):
  54. _pack_ = 1
  55. _fields_ = [
  56. ("weights", ctypes.c_short)
  57. ]
  58. class BatchData(ctypes.Structure):
  59. _pack_ = 1
  60. _fields_ = [
  61. ("numVertex", ctypes.c_short),
  62. ("uB", ctypes.c_short),
  63. ("padding", ctypes.c_uint),
  64. ("offsetPositions", ctypes.c_ulonglong),
  65. ("offsetNormals", ctypes.c_ulonglong),
  66. ("offsetUVs", ctypes.c_ulonglong),
  67. ("offsetBoneIndexes", ctypes.c_ulonglong),
  68. ("offsetBoneWeights", ctypes.c_ulonglong),
  69. ("offsets", ctypes.c_ulonglong)
  70. ]
  71. class VertexData(ctypes.Structure):
  72. _pack_ = 1
  73. _fields_ = [
  74. ("positions", ctypes.POINTER(Coordinate)),
  75. ("normals", ctypes.POINTER(Coordinate)),
  76. ("u", ctypes.POINTER(UVs)),
  77. ("bi", ctypes.POINTER(BoneIndexes)),
  78. ("bw", ctypes.POINTER(BoneWeights))
  79. ]
  80. class Batch(ctypes.Structure):
  81. _pack_ = 1
  82. _fields_ = [
  83. ("bd", ctypes.POINTER(BatchData)),
  84. ("vd", VertexData)
  85. ]
  86. class Mesh(ctypes.Structure):
  87. _pack_ = 1
  88. _fields_ = [
  89. ("b", ctypes.POINTER(Batch))
  90. ]
  91. class Devil1GEO_FN(ctypes.Structure):
  92. _fields_ = [
  93. ("printheader", ctypes.CFUNCTYPE(
  94. None,
  95. ctypes.POINTER(Header))),
  96. ("printmeshheader", ctypes.CFUNCTYPE(
  97. None,
  98. ctypes.POINTER(MeshHeader))),
  99. ("printbatch", ctypes.CFUNCTYPE(
  100. None,
  101. ctypes.POINTER(Batch))),
  102. ("printcoordinate", ctypes.CFUNCTYPE(
  103. None,
  104. ctypes.POINTER(Coordinate))),
  105. ("getheader", ctypes.CFUNCTYPE(
  106. ctypes.c_bool,
  107. ctypes.POINTER(ctypes.POINTER(Header)),
  108. ctypes.c_char_p)),
  109. ("getmeshheader", ctypes.CFUNCTYPE(
  110. ctypes.c_bool,
  111. ctypes.POINTER(ctypes.POINTER(MeshHeader)),
  112. ctypes.c_uint,
  113. ctypes.c_char_p)),
  114. ("getbatch", ctypes.CFUNCTYPE(
  115. ctypes.c_bool,
  116. ctypes.POINTER(Batch),
  117. ctypes.c_uint,
  118. ctypes.c_char_p)),
  119. ("getmesh", ctypes.CFUNCTYPE(
  120. ctypes.c_bool,
  121. ctypes.POINTER(Mesh),
  122. ctypes.c_uint,
  123. ctypes.c_char_p,
  124. ctypes.c_uint))
  125. ]
  126. devil1geo = Devil1GEO_FN.in_dll(libc, "DEVIL1GEO")
  127. del libc
  128. #--------------------------------------+
  129. # Pythonic Object
  130. #--------------------------------------+
  131. class pyGeoHeader:
  132. def __init__(self, filedata):
  133. self.cstruct = ctypes.pointer(Header())
  134. ptrofptr = ctypes.byref(self.cstruct)
  135. if filedata:
  136. if not devil1geo.getheader(ptrofptr, filedata):
  137. raise RuntimeError("failed to get geometry file header")
  138. return
  139. def show(self):
  140. devil1geo.printheader(self.cstruct)
  141. def getnummesh(self):
  142. return self.cstruct.contents.numMesh
  143. def getunknownb(self):
  144. return self.cstruct.contents.unknownNumberB
  145. def getunknownc(self):
  146. return self.cstruct.contents.unknownNumberC
  147. def getunknownd(self):
  148. return self.cstruct.contents.unknownNumberD
  149. def getpadding(self):
  150. return hex(self.cstruct.contents.padding)
  151. def getunknownoffset(self):
  152. return hex(self.cstruct.contents.unknownOffset)
  153. class pyMeshHeader:
  154. def __init__(self, i, filedata):
  155. self.cstruct = ctypes.pointer(MeshHeader())
  156. ptrofptr = ctypes.byref(self.cstruct)
  157. if filedata:
  158. if not devil1geo.getmeshheader(ptrofptr, i, filedata):
  159. raise RuntimeError("failed to get mesh header #" + str(i))
  160. return
  161. pass
  162. def show(self):
  163. devil1geo.printmeshheader(self.cstruct)
  164. def getnumbatch(self):
  165. return self.cstruct.contents.numBatch
  166. def getnumvertex(self):
  167. return self.cstruct.contents.numVertex
  168. def getunknown(self):
  169. return hex(self.cstruct.contents.u)
  170. def getoffsetbatches(self):
  171. return self.cstruct.contents.offsetBatches
  172. def getflags(self):
  173. return self.cstruct.contents.flags
  174. class pyMesh:
  175. def __init__(self, i, filedata):
  176. self.cstruct = Mesh()
  177. if filedata:
  178. mh = pyMeshHeader(i, filedata)
  179. # allocate memory for the size of batch * number of batches
  180. memsize = ctypes.sizeof(Batch) * mh.getnumbatch()
  181. self.cstruct.b = ctypes.cast(
  182. ctypes.create_string_buffer(memsize),
  183. ctypes.POINTER(Batch))
  184. if not devil1geo.getmesh(
  185. ctypes.byref(self.cstruct),
  186. i,
  187. filedata,
  188. len(filedata)):
  189. raise RuntimeError("failed to get mesh")
  190. del mh, memsize
  191. return
  192. def show(self):
  193. if self.cstruct.b:
  194. devil1geo.printbatch(self.cstruct.b)
  195. else:
  196. print("nothing to show")
  197. def getbatchdata(self):
  198. return self.cstruct.b.contents.bd.contents
  199. def getpositions(self):
  200. length = self.cstruct.b.contents.bd.contents.numVertex
  201. return self.cstruct.b.contents.vd.positions[:length]
  202. def getnormals(self):
  203. length = self.cstruct.b.contents.bd.contents.numVertex
  204. return self.cstruct.b.contents.vd.normals[:length]
  205. def getuvs(self):
  206. length = self.cstruct.b.contents.bd.contents.numVertex
  207. return self.cstruct.b.contents.vd.u[:length]
  208. def getboneindexes(self):
  209. length = self.cstruct.b.contents.bd.contents.numVertex
  210. return self.cstruct.b.contents.vd.bi[:length]
  211. def getboneweights(self):
  212. length = self.cstruct.b.contents.bd.contents.numVertex
  213. return self.cstruct.b.contents.vd.bw[:length]