Bläddra i källkod

Updated tutorial 404 to use features of newer pybind11 version,
Introduced typedefs


Former-commit-id: a6b2fd045ac65a0f848b160d8c6ff64e13e2e71f

Sebastian Koch 9 år sedan
förälder
incheckning
d07d324403

+ 13 - 7
python/modules/py_igl_viewer.cpp

@@ -188,9 +188,15 @@ py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
     })
 
     .def_readwrite("lighting_factor",&igl::viewer::ViewerCore::lighting_factor)
-
     .def_readwrite("model_zoom",&igl::viewer::ViewerCore::model_zoom)
 
+    .def_property("trackball_angle",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::Quaterniond(core.trackball_angle.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::Quaterniond& q)
+    {
+      core.trackball_angle = Eigen::Quaternionf(q.cast<float>());
+    })
+
     .def_property("model_translation",
     [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model_translation.cast<double>());},
     [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
@@ -316,13 +322,13 @@ py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
 // UI Enumerations
     py::class_<igl::viewer::Viewer> viewer_class(me, "Viewer");
 
-    #ifdef IGL_VIEWER_WITH_NANOGUI
-    py::object fh = (py::object) py::module::import("nanogui").attr("FormHelper");
-    py::class_<nanogui::FormHelper> form_helper_class(me, "FormHelper", fh);
+//    #ifdef IGL_VIEWER_WITH_NANOGUI
+//    py::object fh = (py::object) py::module::import("nanogui").attr("FormHelper");
+//    py::class_<nanogui::FormHelper> form_helper_class(me, "FormHelper", fh);
 
-    py::object screen = (py::object) py::module::import("nanogui").attr("Screen");
-    py::class_<nanogui::Screen> screen_class(me, "Screen", screen);
-    #endif
+//    py::object screen = (py::object) py::module::import("nanogui").attr("Screen");
+//    py::class_<nanogui::Screen> screen_class(me, "Screen", screen);
+//    #endif
 
     py::enum_<igl::viewer::Viewer::MouseButton>(viewer_class, "MouseButton")
         .value("Left", igl::viewer::Viewer::MouseButton::Left)

+ 12 - 0
python/modules/py_typedefs.cpp

@@ -0,0 +1,12 @@
+py::class_<RotationList>(m, "RotationList")
+    .def(py::init<>())
+    .def("pop_back", &RotationList::pop_back)
+    /* There are multiple versions of push_back(), etc. Select the right ones. */
+    .def("append", (void (RotationList::*)(const Eigen::Quaterniond &)) &RotationList::push_back)
+    .def("back", (Eigen::Quaterniond &(RotationList::*)()) &RotationList::back)
+    .def("__len__", [](const RotationList &v) { return v.size(); })
+    .def("__getitem__", [](const RotationList &v, int b) { return v.at(b); })
+    .def("__setitem__", [](RotationList &v, int b, Eigen::Quaterniond &c) { return v.at(b) = c; })
+    .def("__iter__", [](RotationList &v) {
+       return py::make_iterator(v.begin(), v.end());
+}, py::keep_alive<0, 1>());

+ 5 - 0
python/modules/py_typedefs.h

@@ -0,0 +1,5 @@
+typedef std::vector<Eigen::Quaterniond,Eigen::aligned_allocator<Eigen::Quaterniond> > RotationList;
+PYBIND11_MAKE_OPAQUE(RotationList);
+
+//typedef std::vector<Eigen::Vector3d> TranslationList;
+//PYBIND11_MAKE_OPAQUE(TranslationList);

+ 5 - 2
python/modules/py_vector.cpp

@@ -68,7 +68,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         })
         .def("__init__", [](Type &m, py::buffer b) {
             py::buffer_info info = b.request();
-            if (info.format != py::format_descriptor<Scalar>::value())
+            if (info.format != py::format_descriptor<Scalar>::value)
                 throw std::runtime_error("Incompatible buffer format!");
             if (info.ndim == 1) {
                 new (&m) Type(info.shape[0], 1);
@@ -319,7 +319,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
                 m.data(),                /* Pointer to buffer */
                 sizeof(Scalar),          /* Size of one scalar */
                 /* Python struct-style format descriptor */
-                py::format_descriptor<Scalar>::value(),
+                py::format_descriptor<Scalar>::value,
                 2,                       /* Number of dimensions */
                 { (size_t) m.rows(),     /* Buffer dimensions */
                   (size_t) m.cols() },
@@ -735,6 +735,9 @@ void python_export_vector(py::module &m) {
     .def("conjugate",[](Eigen::Quaterniond& q) {
         return q.conjugate();
     })
+    .def("normalize",[](Eigen::Quaterniond& q) {
+        return q.normalize();
+    })
     .def("slerp",[](Eigen::Quaterniond& q, double & t, Eigen::Quaterniond other) {
         return q.slerp(t, other);
     })

+ 3 - 0
python/py_igl.cpp

@@ -1,6 +1,7 @@
 #include <Eigen/Dense>
 
 #include "python_shared.h"
+#include "modules/py_typedefs.h"
 
 #include <igl/AABB.h>
 #include <igl/ARAPEnergyType.h>
@@ -85,6 +86,8 @@
 
 void python_export_igl(py::module &m)
 {
+#include "modules/py_typedefs.cpp"
+
 #include "py_igl/py_AABB.cpp"
 #include "py_igl/py_ARAPEnergyType.cpp"
 #include "py_igl/py_MeshBooleanType.cpp"

+ 2 - 7
python/py_igl/py_directed_edge_orientations.cpp

@@ -3,15 +3,10 @@ m.def("directed_edge_orientations", []
 (
   const Eigen::MatrixXd& C,
   const Eigen::MatrixXi& E,
-  py::list Q
+  RotationList& Q
 )
 {
-  std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond> > Ql;
-  igl::directed_edge_orientations(C, E, Ql);
-  for (auto item : Ql) {
-    py::object obj = py::cast(item);
-    Q.append(obj);
-  }
+  return igl::directed_edge_orientations(C, E, Q);
 }, __doc_igl_directed_edge_orientations,
 py::arg("C"), py::arg("E"), py::arg("Q"));
 

+ 1 - 1
python/py_igl/py_dqs.cpp

@@ -4,7 +4,7 @@ m.def("dqs", []
 (
   const Eigen::MatrixXd& V,
   const Eigen::MatrixXd& W,
-  const std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond> > & vQ,
+  const RotationList& vQ,
   const std::vector<Eigen::MatrixXd> & vT,
   Eigen::MatrixXd& U
 )

+ 3 - 8
python/py_igl/py_forward_kinematics.cpp

@@ -19,18 +19,13 @@ m.def("forward_kinematics", []
   const Eigen::MatrixXd& C,
   const Eigen::MatrixXi& BE,
   const Eigen::MatrixXi& P,
-  const std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond> > dQ,
-  py::list vQ,
+  const RotationList& dQ,
+  RotationList& vQ,
   py::list vT
 )
 {
-  std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond> > vQl;
   std::vector<Eigen::Vector3d> vTl;
-  igl::forward_kinematics(C, BE, P, dQ, vQl, vTl);
-  for (auto item : vQl) {
-    py::object obj = py::cast(item);
-    vQ.append(obj);
-  }
+  igl::forward_kinematics(C, BE, P, dQ, vQ, vTl);
   for (auto item : vTl) {
     py::object obj = py::cast(Eigen::MatrixXd(item));
     vT.append(obj);

+ 3 - 0
python/scripts/py_igl.mako

@@ -1,6 +1,7 @@
 #include <Eigen/Dense>
 
 #include "python_shared.h"
+#include "modules/py_typedefs.h"
 
 % for f in functions:
 #include <igl/${f}.h>
@@ -9,6 +10,8 @@
 
 void python_export_igl(py::module &m)
 {
+#include "modules/py_typedefs.cpp"
+
 % for f in functions:
 #include "py_igl/py_${f}.cpp"
 % endfor

+ 19 - 9
python/tutorial/404_DualQuaternionSkinning.py

@@ -14,7 +14,7 @@ check_dependencies(dependencies)
 
 
 def pre_draw(viewer):
-    global recompute, anim_t, poses, C, BE, P, U
+    global recompute, anim_t, poses, C, BE, P, U, M, anim_t_dir
 
     if recompute:
         # Find pose interval
@@ -23,12 +23,12 @@ def pre_draw(viewer):
         t = anim_t - math.floor(anim_t)
 
         # Interpolate pose and identity
-        anim_pose = []
+        anim_pose = igl.RotationList()
         for e in range(len(poses[begin])):
             anim_pose.append(poses[begin][e].slerp(t, poses[end][e]))
 
         # Propogate relative rotations via FK to retrieve absolute transformations
-        vQ = []
+        vQ = igl.RotationList()
         vT = []
         igl.forward_kinematics(C, BE, P, anim_pose, vQ, vT)
         dim = C.cols()
@@ -62,14 +62,23 @@ def pre_draw(viewer):
 
 
 def key_down(viewer, key, mods):
-    global recompute, use_dqs
+    global recompute, use_dqs, animation
     recompute = True
     if key == ord('D') or key == ord('d'):
         use_dqs = not use_dqs
-        return True
+        viewer.core.is_animating = False
+        animation = False
+        if use_dqs:
+            print("Switched to Dual Quaternion Skinning")
+        else:
+            print("Switched to Linear Blend Skinning")
     elif key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
-        return True
+        if animation:
+            viewer.core.is_animating = False
+            animation = False
+        else:
+            viewer.core.is_animating = True
+            animation = True
     return False
 
 
@@ -93,6 +102,7 @@ if __name__ == "__main__":
     anim_t_dir = 0.015
     use_dqs = False
     recompute = True
+    animation = False  # Flag needed as there is some synchronization problem with viewer.core.is_animating
 
     poses = [[]]
 
@@ -102,7 +112,7 @@ if __name__ == "__main__":
 
     # retrieve parents for forward kinematics
     igl.directed_edge_parents(BE, P)
-    rest_pose = []
+    rest_pose = igl.RotationList()
     igl.directed_edge_orientations(C, BE, rest_pose)
     poses = [[igl.eigen.Quaterniond.Identity() for i in range(4)] for j in range(4)]
 
@@ -121,7 +131,7 @@ if __name__ == "__main__":
     viewer.core.show_lines = False
     viewer.core.show_overlay_depth = False
     viewer.core.line_width = 1
-    # viewer.core.trackball_angle.normalize()
+    viewer.core.trackball_angle.normalize()
     viewer.callback_pre_draw = pre_draw
     viewer.callback_key_down = key_down
     viewer.core.is_animating = False