403_BoundedBiharmonicWeights.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env python
  2. #
  3. # This file is part of libigl, a simple c++ geometry processing library.
  4. #
  5. # Copyright (C) 2017 Sebastian Koch <s.koch@tu-berlin.de> and Daniele Panozzo <daniele.panozzo@gmail.com>
  6. #
  7. # This Source Code Form is subject to the terms of the Mozilla Public License
  8. # v. 2.0. If a copy of the MPL was not distributed with this file, You can
  9. # obtain one at http://mozilla.org/MPL/2.0/.
  10. import sys, os
  11. # Add the igl library to the modules search path
  12. sys.path.insert(0, os.getcwd() + "/../")
  13. import pyigl as igl
  14. from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage
  15. dependencies = ["glfw"]
  16. check_dependencies(dependencies)
  17. def pre_draw(viewer):
  18. global pose, anim_t, C, BE, P, U, M, anim_t_dir
  19. if viewer.core.is_animating:
  20. # Interpolate pose and identity
  21. anim_pose = igl.RotationList(len(pose))
  22. for e in range(len(pose)):
  23. anim_pose[e] = pose[e].slerp(anim_t, igl.eigen.Quaterniond.Identity())
  24. # Propagate relative rotations via FK to retrieve absolute transformations
  25. vQ = igl.RotationList()
  26. vT = []
  27. igl.forward_kinematics(C, BE, P, anim_pose, vQ, vT)
  28. dim = C.cols()
  29. T = igl.eigen.MatrixXd(BE.rows() * (dim + 1), dim)
  30. for e in range(BE.rows()):
  31. a = igl.eigen.Affine3d.Identity()
  32. a.translate(vT[e])
  33. a.rotate(vQ[e])
  34. T.setBlock(e * (dim + 1), 0, dim + 1, dim, a.matrix().transpose().block(0, 0, dim + 1, dim))
  35. # Compute deformation via LBS as matrix multiplication
  36. U = M * T
  37. # Also deform skeleton edges
  38. CT = igl.eigen.MatrixXd()
  39. BET = igl.eigen.MatrixXi()
  40. igl.deform_skeleton(C, BE, T, CT, BET)
  41. viewer.data().set_vertices(U)
  42. viewer.data().set_edges(CT, BET, sea_green)
  43. viewer.data().compute_normals()
  44. anim_t += anim_t_dir
  45. anim_t_dir *= -1.0 if (0.0 >= anim_t or anim_t >= 1.0) else 1.0
  46. return False
  47. def key_down(viewer, key, mods):
  48. global selected, W
  49. if key == ord('.'):
  50. selected += 1
  51. selected = min(max(selected, 0), W.cols()-1)
  52. set_color(viewer)
  53. elif key == ord(','):
  54. selected -= 1
  55. selected = min(max(selected, 0), W.cols()-1)
  56. set_color(viewer)
  57. elif key == ord(' '):
  58. viewer.core.is_animating = not viewer.core.is_animating
  59. return True
  60. def set_color(viewer):
  61. global selected, W
  62. C = igl.eigen.MatrixXd()
  63. igl.jet(W.col(selected), True, C)
  64. viewer.data().set_colors(C)
  65. if __name__ == "__main__":
  66. keys = {".": "show next weight function",
  67. ",": "show previous weight function",
  68. "space": "toggle animation"}
  69. print_usage(keys)
  70. V = igl.eigen.MatrixXd()
  71. W = igl.eigen.MatrixXd()
  72. U = igl.eigen.MatrixXd()
  73. C = igl.eigen.MatrixXd()
  74. M = igl.eigen.MatrixXd()
  75. Q = igl.eigen.MatrixXd()
  76. T = igl.eigen.MatrixXi()
  77. F = igl.eigen.MatrixXi()
  78. BE = igl.eigen.MatrixXi()
  79. P = igl.eigen.MatrixXi()
  80. sea_green = igl.eigen.MatrixXd([[70. / 255., 252. / 255., 167. / 255.]])
  81. selected = 0
  82. pose = igl.RotationList()
  83. anim_t = 1.0
  84. anim_t_dir = -0.03
  85. igl.readMESH(TUTORIAL_SHARED_PATH + "hand.mesh", V, T, F)
  86. U = igl.eigen.MatrixXd(V)
  87. igl.readTGF(TUTORIAL_SHARED_PATH + "hand.tgf", C, BE)
  88. # Retrieve parents for forward kinematics
  89. igl.directed_edge_parents(BE, P)
  90. # Read pose as matrix of quaternions per row
  91. igl.readDMAT(TUTORIAL_SHARED_PATH + "hand-pose.dmat", Q)
  92. igl.column_to_quats(Q, pose)
  93. assert (len(pose) == BE.rows())
  94. # List of boundary indices (aka fixed value indices into VV)
  95. b = igl.eigen.MatrixXi()
  96. # List of boundary conditions of each weight function
  97. bc = igl.eigen.MatrixXd()
  98. igl.boundary_conditions(V, T, C, igl.eigen.MatrixXi(), BE, igl.eigen.MatrixXi(), b, bc)
  99. # compute BBW weights matrix
  100. bbw_data = igl.BBWData()
  101. # only a few iterations for sake of demo
  102. bbw_data.active_set_params.max_iter = 8
  103. bbw_data.verbosity = 2
  104. if not igl.bbw(V, T, b, bc, bbw_data, W):
  105. exit(-1)
  106. # Normalize weights to sum to one
  107. igl.normalize_row_sums(W, W)
  108. # precompute linear blend skinning matrix
  109. igl.lbs_matrix(V, W, M)
  110. # Plot the mesh with pseudocolors
  111. viewer = igl.glfw.Viewer()
  112. viewer.data().set_mesh(U, F)
  113. set_color(viewer)
  114. viewer.data().set_edges(C, BE, sea_green)
  115. viewer.data().show_lines = False
  116. viewer.data().show_overlay_depth = False
  117. viewer.data().line_width = 1
  118. viewer.core.trackball_angle.normalize()
  119. viewer.callback_pre_draw = pre_draw
  120. viewer.callback_key_down = key_down
  121. viewer.core.is_animating = False
  122. viewer.core.animation_max_fps = 30.0
  123. viewer.launch()