export_geno.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import numpy as np
  2. import pymel.core as pm
  3. import struct
  4. def quat_from_xform(ts, eps=1e-10):
  5. qs = np.empty_like(ts[..., :1, 0].repeat(4, axis=-1))
  6. t = ts[..., 0, 0] + ts[..., 1, 1] + ts[..., 2, 2]
  7. s = 0.5 / np.sqrt(np.maximum(t + 1, eps))
  8. qs = np.where((t > 0)[..., np.newaxis].repeat(4, axis=-1), np.concatenate([
  9. (0.25 / s)[..., np.newaxis],
  10. (s * (ts[..., 2, 1] - ts[..., 1, 2]))[..., np.newaxis],
  11. (s * (ts[..., 0, 2] - ts[..., 2, 0]))[..., np.newaxis],
  12. (s * (ts[..., 1, 0] - ts[..., 0, 1]))[..., np.newaxis]
  13. ], axis=-1), qs)
  14. c0 = (ts[..., 0, 0] > ts[..., 1, 1]) & (ts[..., 0, 0] > ts[..., 2, 2])
  15. s0 = 2.0 * np.sqrt(np.maximum(1.0 + ts[..., 0, 0] - ts[..., 1, 1] - ts[..., 2, 2], eps))
  16. qs = np.where(((t <= 0) & c0)[..., np.newaxis].repeat(4, axis=-1), np.concatenate([
  17. ((ts[..., 2, 1] - ts[..., 1, 2]) / s0)[..., np.newaxis],
  18. (s0 * 0.25)[..., np.newaxis],
  19. ((ts[..., 0, 1] + ts[..., 1, 0]) / s0)[..., np.newaxis],
  20. ((ts[..., 0, 2] + ts[..., 2, 0]) / s0)[..., np.newaxis]
  21. ], axis=-1), qs)
  22. c1 = (~c0) & (ts[..., 1, 1] > ts[..., 2, 2])
  23. s1 = 2.0 * np.sqrt(np.maximum(1.0 + ts[..., 1, 1] - ts[..., 0, 0] - ts[..., 2, 2], eps))
  24. qs = np.where(((t <= 0) & c1)[..., np.newaxis].repeat(4, axis=-1), np.concatenate([
  25. ((ts[..., 0, 2] - ts[..., 2, 0]) / s1)[..., np.newaxis],
  26. ((ts[..., 0, 1] + ts[..., 1, 0]) / s1)[..., np.newaxis],
  27. (s1 * 0.25)[..., np.newaxis],
  28. ((ts[..., 1, 2] + ts[..., 2, 1]) / s1)[..., np.newaxis]
  29. ], axis=-1), qs)
  30. c2 = (~c0) & (~c1)
  31. s2 = 2.0 * np.sqrt(np.maximum(1.0 + ts[..., 2, 2] - ts[..., 0, 0] - ts[..., 1, 1], eps))
  32. qs = np.where(((t <= 0) & c2)[..., np.newaxis].repeat(4, axis=-1), np.concatenate([
  33. ((ts[..., 1, 0] - ts[..., 0, 1]) / s2)[..., np.newaxis],
  34. ((ts[..., 0, 2] + ts[..., 2, 0]) / s2)[..., np.newaxis],
  35. ((ts[..., 1, 2] + ts[..., 2, 1]) / s2)[..., np.newaxis],
  36. (s2 * 0.25)[..., np.newaxis]
  37. ], axis=-1), qs)
  38. return qs
  39. geno = pm.PyNode('GenoShape')
  40. pm.polyTriangulate(geno)
  41. joints = [
  42. 'Hips',
  43. 'Spine',
  44. 'Spine1',
  45. 'Spine2',
  46. 'Spine3',
  47. 'Neck',
  48. 'Neck1',
  49. 'Head',
  50. 'HeadEnd',
  51. 'RightShoulder',
  52. 'RightArm',
  53. 'RightForeArm',
  54. 'RightHand',
  55. 'RightHandThumb1',
  56. 'RightHandThumb2',
  57. 'RightHandThumb3',
  58. 'RightHandThumb4',
  59. 'RightHandIndex1',
  60. 'RightHandIndex2',
  61. 'RightHandIndex3',
  62. 'RightHandIndex4',
  63. 'RightHandMiddle1',
  64. 'RightHandMiddle2',
  65. 'RightHandMiddle3',
  66. 'RightHandMiddle4',
  67. 'RightHandRing1',
  68. 'RightHandRing2',
  69. 'RightHandRing3',
  70. 'RightHandRing4',
  71. 'RightHandPinky1',
  72. 'RightHandPinky2',
  73. 'RightHandPinky3',
  74. 'RightHandPinky4',
  75. 'RightForeArmEnd',
  76. 'RightArmEnd',
  77. 'LeftShoulder',
  78. 'LeftArm',
  79. 'LeftForeArm',
  80. 'LeftHand',
  81. 'LeftHandThumb1',
  82. 'LeftHandThumb2',
  83. 'LeftHandThumb3',
  84. 'LeftHandThumb4',
  85. 'LeftHandIndex1',
  86. 'LeftHandIndex2',
  87. 'LeftHandIndex3',
  88. 'LeftHandIndex4',
  89. 'LeftHandMiddle1',
  90. 'LeftHandMiddle2',
  91. 'LeftHandMiddle3',
  92. 'LeftHandMiddle4',
  93. 'LeftHandRing1',
  94. 'LeftHandRing2',
  95. 'LeftHandRing3',
  96. 'LeftHandRing4',
  97. 'LeftHandPinky1',
  98. 'LeftHandPinky2',
  99. 'LeftHandPinky3',
  100. 'LeftHandPinky4',
  101. 'LeftForeArmEnd',
  102. 'LeftArmEnd',
  103. 'RightUpLeg',
  104. 'RightLeg',
  105. 'RightFoot',
  106. 'RightToeBase',
  107. 'RightToeBaseEnd',
  108. 'RightLegEnd',
  109. 'RightUpLegEnd',
  110. 'LeftUpLeg',
  111. 'LeftLeg',
  112. 'LeftFoot',
  113. 'LeftToeBase',
  114. 'LeftToeBaseEnd',
  115. 'LeftLegEnd',
  116. 'LeftUpLegEnd',
  117. ]
  118. joint_nodes = [pm.PyNode(n) for n in joints]
  119. parents = np.asarray([
  120. joints.index(str(j.getParent().getName())) if j.getParent() else -1
  121. for j in joint_nodes
  122. ])
  123. print(parents)
  124. skinning = pm.PyNode('skinCluster1')
  125. influences = skinning.influenceObjects()
  126. influence_index = np.asarray([joints.index(node.getName()) for node in influences])
  127. print(influence_index)
  128. weights_all = np.asarray(list(skinning.getWeights('GenoShape')))
  129. weights_order = weights_all.argsort(axis=1)[:,::-1]
  130. vert_bone_weis = np.zeros([len(weights_all), 4], dtype=np.float32)
  131. vert_bone_inds = np.zeros([len(weights_all), 4], dtype=np.uint8)
  132. for i in range(len(weights_all)):
  133. vert_bone_inds[i] = influence_index[weights_order[i,:4]]
  134. vert_bone_weis[i] = weights_all[i,weights_order[i,:4]]
  135. vert_bone_weis[i] = vert_bone_weis[i] / np.sum(vert_bone_weis[i])
  136. vert_bone_inds[i][vert_bone_weis[i] == 0.0] = 0
  137. print(vert_bone_inds.shape, vert_bone_inds)
  138. print(vert_bone_weis.shape, vert_bone_weis)
  139. vert_posns = np.asarray(geno.getPoints(space='world'))
  140. vert_norms = np.asarray(geno.getNormals(space='world'))
  141. vert_uvs = np.asarray(geno.getUVs()).T
  142. print(vert_norms.shape)
  143. print(vert_posns.shape)
  144. print(vert_uvs.shape)
  145. tris_posns_num, tris_posns = geno.getTriangles()
  146. tris_posns_num, tris_posns = np.asarray(tris_posns_num), np.asarray(tris_posns)
  147. assert np.all(tris_posns_num == 1)
  148. tris_posns = tris_posns.reshape([-1, 3])
  149. tris_uvs_num, tris_uvs = geno.getAssignedUVs()
  150. tris_uvs_num, tris_uvs = np.asarray(tris_uvs_num), np.asarray(tris_uvs)
  151. assert np.all(tris_uvs_num == 3)
  152. tris_uvs = tris_uvs.reshape([-1, 3])
  153. tris_norms_num, tris_norms = geno.getNormalIds()
  154. tris_norms_num, tris_norms = np.asarray(tris_norms_num), np.asarray(tris_norms)
  155. assert np.all(tris_norms_num == 3)
  156. tris_norms = tris_norms.reshape([-1, 3])
  157. print(tris_posns.shape)
  158. print(tris_uvs.shape)
  159. print(tris_norms.shape)
  160. tri_num = len(tris_posns)
  161. assert tri_num == len(tris_posns)
  162. assert tri_num == len(tris_norms)
  163. assert tri_num == len(tris_uvs)
  164. vert_map = {}
  165. final_tris = []
  166. final_posns = []
  167. final_norms = []
  168. final_uvs = []
  169. final_bone_inds = []
  170. final_bone_weis = []
  171. for t in range(tri_num):
  172. pi0, pi1, pi2 = tris_posns[t]
  173. ni0, ni1, ni2 = tris_norms[t]
  174. ui0, ui1, ui2 = tris_uvs[t]
  175. p0, p1, p2 = vert_posns[pi0], vert_posns[pi1], vert_posns[pi2]
  176. n0, n1, n2 = vert_norms[ni0], vert_norms[ni1], vert_norms[ni2]
  177. u0, u1, u2 = vert_uvs[ui0], vert_uvs[ui1], vert_uvs[ui2]
  178. bi0, bi1, bi2 = vert_bone_inds[pi0], vert_bone_inds[pi1], vert_bone_inds[pi2]
  179. bw0, bw1, bw2 = vert_bone_weis[pi0], vert_bone_weis[pi1], vert_bone_weis[pi2]
  180. vert0 = (tuple(p0), tuple(n0), tuple(u0), tuple(bi0), tuple(bw0))
  181. vert1 = (tuple(p1), tuple(n1), tuple(u1), tuple(bi1), tuple(bw1))
  182. vert2 = (tuple(p2), tuple(n2), tuple(u2), tuple(bi2), tuple(bw2))
  183. if vert0 in vert_map:
  184. i0 = vert_map[vert0]
  185. else:
  186. i0 = len(final_posns)
  187. vert_map[vert0] = i0
  188. final_posns.append(p0)
  189. final_norms.append(n0)
  190. final_uvs.append(u0)
  191. final_bone_inds.append(bi0)
  192. final_bone_weis.append(bw0)
  193. if vert1 in vert_map:
  194. i1 = vert_map[vert1]
  195. else:
  196. i1 = len(final_posns)
  197. vert_map[vert1] = i1
  198. final_posns.append(p1)
  199. final_norms.append(n1)
  200. final_uvs.append(u1)
  201. final_bone_inds.append(bi1)
  202. final_bone_weis.append(bw1)
  203. if vert2 in vert_map:
  204. i2 = vert_map[vert2]
  205. else:
  206. i2 = len(final_posns)
  207. vert_map[vert2] = i2
  208. final_posns.append(p2)
  209. final_norms.append(n2)
  210. final_uvs.append(u2)
  211. final_bone_inds.append(bi2)
  212. final_bone_weis.append(bw2)
  213. final_tris.append((i0, i1, i2))
  214. final_tris = np.asarray(final_tris).astype(np.uint16)
  215. final_posns = np.asarray(final_posns).astype(np.float32)
  216. final_norms = np.asarray(final_norms).astype(np.float32)
  217. final_uvs = np.asarray(final_uvs).astype(np.float32)
  218. final_bone_inds = np.asarray(final_bone_inds).astype(np.uint8)
  219. final_bone_weis = np.asarray(final_bone_weis).astype(np.float32)
  220. print(final_tris.shape, final_tris[:10])
  221. print(final_posns.shape, final_posns[:10])
  222. print(final_norms.shape, final_norms[:10])
  223. print(final_uvs.shape, final_uvs[:10])
  224. print(final_bone_inds.shape, final_bone_inds[:10])
  225. print(final_bone_weis.shape, final_bone_weis[:10])
  226. bone_xforms = np.asarray([pm.xform(j, q=True, ws=True, m=True) for j in joints]).reshape([len(joints), 4, 4]).transpose([0, 2, 1])
  227. #print(bone_xforms)
  228. bone_positions = bone_xforms[:,:3,3].copy().astype(np.float32)
  229. bone_rotations = quat_from_xform(bone_xforms).astype(np.float32)
  230. bone_parents = parents.astype(np.int32)
  231. bone_rotations = np.concatenate([
  232. bone_rotations[:,1:2],
  233. bone_rotations[:,2:3],
  234. bone_rotations[:,3:4],
  235. bone_rotations[:,0:1],
  236. ], axis=-1)
  237. #print(bone_positions)
  238. #print(bone_rotations)
  239. final_posns = 0.01 * final_posns
  240. bone_positions = 0.01 * bone_positions
  241. with open('C:/Projects/GenoView/resources/Geno.bin', 'wb') as f:
  242. f.write(struct.pack('I', len(final_posns)))
  243. f.write(struct.pack('I', len(final_tris)))
  244. f.write(struct.pack('I', len(joints)))
  245. f.write(final_posns.tobytes())
  246. f.write(final_uvs.tobytes())
  247. f.write(final_norms.tobytes())
  248. f.write(final_bone_inds.tobytes())
  249. f.write(final_bone_weis.tobytes())
  250. f.write(final_tris.tobytes())
  251. for i in range(len(bone_parents)):
  252. f.write(struct.pack('32si', bytes(joints[i], encoding='ascii'), bone_parents[i]))
  253. for i in range(len(bone_parents)):
  254. f.write(struct.pack('ffffffffff',
  255. bone_positions[i,0], bone_positions[i,1], bone_positions[i,2],
  256. bone_rotations[i,0], bone_rotations[i,1], bone_rotations[i,2], bone_rotations[i,3],
  257. 1.0, 1.0, 1.0))