py_igl_viewer.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #include <Eigen/Dense>
  2. #include <Eigen/Sparse>
  3. #include "python_shared.h"
  4. #define ENABLE_SERIALIZATION
  5. #include <igl/viewer/Viewer.h>
  6. #include <igl/viewer/ViewerCore.h>
  7. #include <igl/viewer/ViewerData.h>
  8. #include <igl/serialize.h>
  9. #include "nanogui/screen.h"
  10. #include "nanogui/formhelper.h"
  11. void python_export_igl_viewer(py::module &m)
  12. {
  13. // py::module::import("nanogui");
  14. // py::object FormHelper = (py::object) py::module::import("nanogui").attr("FormHelper");
  15. // py::object Screen = (py::object) py::module::import("nanogui").attr("Screen");
  16. py::module me = m.def_submodule(
  17. "viewer", "Mesh viewer");
  18. //// NANOGUI
  19. //py::class_<nanogui::FormHelper> formhelper_class(me, "FormHelper", FormHelper);
  20. //py::class_<nanogui::Screen> screen_class(me, "Screen", Screen);
  21. // py::class_<FormHelper>(m, "FormHelper", D(FormHelper))
  22. // .def(py::init<Screen *>(), D(FormHelper, FormHelper))
  23. // .def("addWindow", &FormHelper::addWindow, py::arg("pos"),
  24. // py::arg("title") = std::string("Untitled"),
  25. // D(FormHelper, addWindow))
  26. // .def("addGroup", &FormHelper::addGroup, D(FormHelper, addGroup))
  27. // .def("addButton", &FormHelper::addButton, py::arg("label"),
  28. // py::arg("cb"), D(FormHelper, addGroup))
  29. // .def("addBoolVariable",
  30. // [](FormHelper &h, const std::string &label,
  31. // const std::function<void(bool) > &setter,
  32. // const std::function<bool(void) > &getter, bool editable) -> CheckBox* {
  33. // return h.addVariable(label, setter, getter, editable);
  34. // },
  35. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  36. // py::arg("editable") = true)
  37. // .def("addIntVariable",
  38. // [](FormHelper &h, const std::string &label,
  39. // const std::function<void(int64_t) > &setter,
  40. // const std::function<int64_t(void) > &getter, bool editable) -> Int64Box* {
  41. // return h.addVariable(label, setter, getter, editable);
  42. // },
  43. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  44. // py::arg("editable") = true)
  45. // .def("addDoubleVariable",
  46. // [](FormHelper &h, const std::string &label,
  47. // const std::function<void(double) > &setter,
  48. // const std::function<double(void) > &getter, bool editable) -> FloatBox<double>* {
  49. // return h.addVariable(label, setter, getter, editable);
  50. // },
  51. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  52. // py::arg("editable") = true)
  53. // .def("addStringVariable",
  54. // [](FormHelper &h, const std::string &label,
  55. // const std::function<void(std::string) > &setter,
  56. // const std::function<std::string(void) > &getter, bool editable) -> TextBox* {
  57. // return h.addVariable(label, setter, getter, editable);
  58. // },
  59. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  60. // py::arg("editable") = true)
  61. // .def("addColorVariable",
  62. // [](FormHelper &h, const std::string &label,
  63. // const std::function<void(Color) > &setter,
  64. // const std::function<Color(void) > &getter, bool editable) -> ColorPicker* {
  65. // return h.addVariable(label, setter, getter, editable);
  66. // },
  67. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  68. // py::arg("editable") = true)
  69. // .def("addEnumVariable",
  70. // [](FormHelper &h, const std::string &label,
  71. // const std::function<void(int) > &setter,
  72. // const std::function<int(void) > &getter, bool editable) -> ComboBox* {
  73. // return h.addVariable(label,
  74. // reinterpret_cast<const std::function<void(DummyEnum)>&>(setter),
  75. // reinterpret_cast<const std::function<DummyEnum(void)>&>(getter),
  76. // editable);
  77. // },
  78. // py::arg("label"), py::arg("setter"), py::arg("getter"),
  79. // py::arg("editable") = true)
  80. // .def("addWidget", &FormHelper::addWidget, D(FormHelper, addWidget))
  81. // .def("refresh", &FormHelper::refresh, D(FormHelper, refresh))
  82. // .def("window", &FormHelper::window, D(FormHelper, window))
  83. // .def("setWindow", &FormHelper::setWindow, D(FormHelper, setWindow))
  84. // .def("fixedSize", &FormHelper::fixedSize, D(FormHelper, fixedSize))
  85. // .def("setFixedSize", &FormHelper::setFixedSize, D(FormHelper, setFixedSize))
  86. // .def("groupFontName", &FormHelper::groupFontName, D(FormHelper, groupFontName))
  87. // .def("setGroupFontName", &FormHelper::setGroupFontName, D(FormHelper, setGroupFontName))
  88. // .def("labelFontName", &FormHelper::labelFontName, D(FormHelper, labelFontName))
  89. // .def("setLabelFontName", &FormHelper::setLabelFontName, D(FormHelper, setLabelFontName))
  90. // .def("groupFontSize", &FormHelper::groupFontSize, D(FormHelper, groupFontSize))
  91. // .def("setGroupFontSize", &FormHelper::setGroupFontSize, D(FormHelper, setGroupFontSize))
  92. // .def("labelFontSize", &FormHelper::labelFontSize, D(FormHelper, labelFontSize))
  93. // .def("setLabelFontSize", &FormHelper::setLabelFontSize, D(FormHelper, setLabelFontSize))
  94. // .def("widgetFontSize", &FormHelper::widgetFontSize, D(FormHelper, widgetFontSize))
  95. // .def("setWidgetFontSize", &FormHelper::setWidgetFontSize, D(FormHelper, setWidgetFontSize));
  96. /////////////////////// DATA
  97. py::class_<igl::viewer::ViewerData> viewerdata_class(me, "ViewerData");
  98. py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
  99. .value("DIRTY_NONE", igl::viewer::ViewerData::DIRTY_NONE)
  100. .value("DIRTY_POSITION", igl::viewer::ViewerData::DIRTY_POSITION)
  101. .value("DIRTY_UV", igl::viewer::ViewerData::DIRTY_UV)
  102. .value("DIRTY_NORMAL", igl::viewer::ViewerData::DIRTY_NORMAL)
  103. .value("DIRTY_AMBIENT", igl::viewer::ViewerData::DIRTY_AMBIENT)
  104. .value("DIRTY_DIFFUSE", igl::viewer::ViewerData::DIRTY_DIFFUSE)
  105. .value("DIRTY_SPECULAR", igl::viewer::ViewerData::DIRTY_SPECULAR)
  106. .value("DIRTY_TEXTURE", igl::viewer::ViewerData::DIRTY_TEXTURE)
  107. .value("DIRTY_FACE", igl::viewer::ViewerData::DIRTY_FACE)
  108. .value("DIRTY_MESH", igl::viewer::ViewerData::DIRTY_MESH)
  109. .value("DIRTY_OVERLAY_LINES", igl::viewer::ViewerData::DIRTY_OVERLAY_LINES)
  110. .value("DIRTY_OVERLAY_POINTS", igl::viewer::ViewerData::DIRTY_OVERLAY_POINTS)
  111. .value("DIRTY_ALL", igl::viewer::ViewerData::DIRTY_ALL)
  112. .export_values();
  113. viewerdata_class
  114. .def(py::init<>())
  115. .def("set_mesh", &igl::viewer::ViewerData::set_mesh)
  116. .def("set_colors", &igl::viewer::ViewerData::set_colors)
  117. .def("clear", &igl::viewer::ViewerData::clear)
  118. .def("set_face_based", &igl::viewer::ViewerData::set_face_based)
  119. .def("set_vertices", &igl::viewer::ViewerData::set_vertices)
  120. .def("set_normals", &igl::viewer::ViewerData::set_normals)
  121. .def("set_uv",
  122. (void (igl::viewer::ViewerData::*) (const Eigen::MatrixXd &)) &igl::viewer::ViewerData::set_uv
  123. )
  124. .def("set_uv",
  125. (void (igl::viewer::ViewerData::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi&)) &igl::viewer::ViewerData::set_uv
  126. )
  127. .def("set_texture", &igl::viewer::ViewerData::set_texture)
  128. .def("set_points", &igl::viewer::ViewerData::set_points)
  129. .def("add_points", &igl::viewer::ViewerData::add_points)
  130. .def("set_edges", &igl::viewer::ViewerData::set_edges)
  131. .def("add_edges", &igl::viewer::ViewerData::add_edges)
  132. .def("add_label", [] (igl::viewer::ViewerData& data, const Eigen::MatrixXd& P, const std::string& str)
  133. {
  134. assert_is_VectorX("P",P);
  135. data.add_label(P,str);
  136. })
  137. .def("compute_normals", &igl::viewer::ViewerData::compute_normals)
  138. .def("uniform_colors", [] (igl::viewer::ViewerData& data, const Eigen::MatrixXd& ambient, const Eigen::MatrixXd& diffuse, const Eigen::MatrixXd& specular)
  139. {
  140. assert_is_Vector3("ambient",ambient);
  141. assert_is_Vector3("diffuse",diffuse);
  142. assert_is_Vector3("specular",specular);
  143. data.uniform_colors(ambient,diffuse, specular);
  144. })
  145. .def("grid_texture", &igl::viewer::ViewerData::grid_texture)
  146. .def_readwrite("V", &igl::viewer::ViewerData::V)
  147. .def_readwrite("F", &igl::viewer::ViewerData::F)
  148. .def_readwrite("F_normals", &igl::viewer::ViewerData::F_normals)
  149. .def_readwrite("F_material_ambient", &igl::viewer::ViewerData::F_material_ambient)
  150. .def_readwrite("F_material_diffuse", &igl::viewer::ViewerData::F_material_diffuse)
  151. .def_readwrite("F_material_specular", &igl::viewer::ViewerData::F_material_specular)
  152. .def_readwrite("V_normals", &igl::viewer::ViewerData::V_normals)
  153. .def_readwrite("V_material_ambient", &igl::viewer::ViewerData::V_material_ambient)
  154. .def_readwrite("V_material_diffuse", &igl::viewer::ViewerData::V_material_diffuse)
  155. .def_readwrite("V_material_specular", &igl::viewer::ViewerData::V_material_specular)
  156. .def_readwrite("V_uv", &igl::viewer::ViewerData::V_uv)
  157. .def_readwrite("F_uv", &igl::viewer::ViewerData::F_uv)
  158. .def_readwrite("texture_R", &igl::viewer::ViewerData::texture_R)
  159. .def_readwrite("texture_G", &igl::viewer::ViewerData::texture_G)
  160. .def_readwrite("texture_B", &igl::viewer::ViewerData::texture_B)
  161. .def_readwrite("lines", &igl::viewer::ViewerData::lines)
  162. .def_readwrite("points", &igl::viewer::ViewerData::points)
  163. .def_readwrite("labels_positions", &igl::viewer::ViewerData::labels_positions)
  164. .def_readwrite("labels_strings", &igl::viewer::ViewerData::labels_strings)
  165. .def_readwrite("dirty", &igl::viewer::ViewerData::dirty)
  166. .def_readwrite("face_based", &igl::viewer::ViewerData::face_based)
  167. .def("serialize", [](igl::viewer::ViewerData& data)
  168. {
  169. std::vector<char> a;
  170. igl::serialize(data,"Data",a);
  171. return a;
  172. })
  173. .def("deserialize", [](igl::viewer::ViewerData& data, const std::vector<char>& a)
  174. {
  175. igl::deserialize(data,"Data",a);
  176. return;
  177. })
  178. ;
  179. //////////////////////// CORE
  180. py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
  181. py::enum_<igl::viewer::ViewerCore::RotationType>(viewercore_class, "RotationType")
  182. .value("ROTATION_TYPE_TRACKBALL", igl::viewer::ViewerCore::ROTATION_TYPE_TRACKBALL)
  183. .value("ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP", igl::viewer::ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
  184. .value("NUM_ROTATION_TYPES", igl::viewer::ViewerCore::NUM_ROTATION_TYPES)
  185. .export_values();
  186. viewercore_class
  187. .def(py::init<>())
  188. //.def("align_camera_center", [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& V, const Eigen::MatrixXi& F){return core.align_camera_center(V,F);})
  189. .def("init", &igl::viewer::ViewerCore::init)
  190. .def("shut", &igl::viewer::ViewerCore::shut)
  191. //.def("InitSerialization", &igl::viewer::ViewerCore::InitSerialization)
  192. .def("align_camera_center",
  193. (void (igl::viewer::ViewerCore::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi &)) &igl::viewer::ViewerCore::align_camera_center
  194. )
  195. .def("align_camera_center",
  196. (void (igl::viewer::ViewerCore::*) (const Eigen::MatrixXd &)) &igl::viewer::ViewerCore::align_camera_center
  197. )
  198. .def("clear_framebuffers",&igl::viewer::ViewerCore::clear_framebuffers)
  199. .def("draw",&igl::viewer::ViewerCore::draw)
  200. .def("draw_buffer",&igl::viewer::ViewerCore::draw_buffer)
  201. .def_readwrite("shininess",&igl::viewer::ViewerCore::shininess)
  202. .def_property("background_color",
  203. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.background_color.cast<double>());},
  204. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  205. {
  206. assert_is_Vector4("background_color",v);
  207. core.background_color << Eigen::Vector4f(v.cast<float>());
  208. })
  209. .def_property("line_color",
  210. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.line_color.cast<double>());},
  211. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  212. {
  213. assert_is_Vector4("line_color",v);
  214. core.line_color = Eigen::Vector4f(v.cast<float>());
  215. })
  216. .def_property("light_position",
  217. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.light_position.cast<double>());},
  218. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  219. {
  220. assert_is_Vector3("light_position",v);
  221. core.light_position = Eigen::Vector3f(v.cast<float>());
  222. })
  223. .def_readwrite("lighting_factor",&igl::viewer::ViewerCore::lighting_factor)
  224. .def_readwrite("model_zoom",&igl::viewer::ViewerCore::model_zoom)
  225. .def_property("model_translation",
  226. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model_translation.cast<double>());},
  227. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  228. {
  229. assert_is_Vector3("model_translation",v);
  230. core.model_translation = Eigen::Vector3f(v.cast<float>());
  231. })
  232. .def_readwrite("model_zoom_uv",&igl::viewer::ViewerCore::model_zoom_uv)
  233. .def_property("model_translation_uv",
  234. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model_translation_uv.cast<double>());},
  235. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  236. {
  237. assert_is_Vector3("model_translation_uv",v);
  238. core.model_translation_uv = Eigen::Vector3f(v.cast<float>());
  239. })
  240. .def_readwrite("camera_zoom",&igl::viewer::ViewerCore::camera_zoom)
  241. .def_readwrite("orthographic",&igl::viewer::ViewerCore::orthographic)
  242. .def_property("camera_eye",
  243. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_eye.cast<double>());},
  244. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  245. {
  246. assert_is_Vector3("camera_eye",v);
  247. core.camera_eye = Eigen::Vector3f(v.cast<float>());
  248. })
  249. .def_property("camera_up",
  250. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_up.cast<double>());},
  251. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  252. {
  253. assert_is_Vector3("camera_up",v);
  254. core.camera_up = Eigen::Vector3f(v.cast<float>());
  255. })
  256. .def_property("camera_center",
  257. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_center.cast<double>());},
  258. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  259. {
  260. assert_is_Vector3("camera_center",v);
  261. core.camera_center = Eigen::Vector3f(v.cast<float>());
  262. })
  263. .def_readwrite("camera_view_angle",&igl::viewer::ViewerCore::camera_view_angle)
  264. .def_readwrite("camera_dnear",&igl::viewer::ViewerCore::camera_dnear)
  265. .def_readwrite("camera_dfar",&igl::viewer::ViewerCore::camera_dfar)
  266. .def_readwrite("show_overlay",&igl::viewer::ViewerCore::show_overlay)
  267. .def_readwrite("show_overlay_depth",&igl::viewer::ViewerCore::show_overlay_depth)
  268. .def_readwrite("show_texture",&igl::viewer::ViewerCore::show_texture)
  269. .def_readwrite("show_faces",&igl::viewer::ViewerCore::show_faces)
  270. .def_readwrite("show_lines",&igl::viewer::ViewerCore::show_lines)
  271. .def_readwrite("show_vertid",&igl::viewer::ViewerCore::show_vertid)
  272. .def_readwrite("show_faceid",&igl::viewer::ViewerCore::show_faceid)
  273. .def_readwrite("invert_normals",&igl::viewer::ViewerCore::invert_normals)
  274. .def_readwrite("depth_test",&igl::viewer::ViewerCore::depth_test)
  275. .def_readwrite("point_size",&igl::viewer::ViewerCore::point_size)
  276. .def_readwrite("line_width",&igl::viewer::ViewerCore::line_width)
  277. .def_readwrite("is_animating",&igl::viewer::ViewerCore::is_animating)
  278. .def_readwrite("animation_max_fps",&igl::viewer::ViewerCore::animation_max_fps)
  279. .def_readwrite("object_scale",&igl::viewer::ViewerCore::object_scale)
  280. .def_property("viewport",
  281. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.viewport.cast<double>());},
  282. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  283. {
  284. assert_is_Vector4("viewport",v);
  285. core.viewport = Eigen::Vector4f(v.cast<float>());
  286. })
  287. .def_property("view",
  288. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.view.cast<double>());},
  289. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  290. {
  291. assert_is_Matrix4("view",v);
  292. core.view = Eigen::Matrix4f(v.cast<float>());
  293. })
  294. .def_property("model",
  295. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model.cast<double>());},
  296. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  297. {
  298. assert_is_Matrix4("model",v);
  299. core.model = Eigen::Matrix4f(v.cast<float>());
  300. })
  301. .def_property("proj",
  302. [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.proj.cast<double>());},
  303. [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
  304. {
  305. assert_is_Matrix4("proj",v);
  306. core.proj = Eigen::Matrix4f(v.cast<float>());
  307. })
  308. .def_readwrite("rotation_type",&igl::viewer::ViewerCore::rotation_type)
  309. .def("serialize", [](igl::viewer::ViewerCore& core)
  310. {
  311. std::vector<char> a;
  312. igl::serialize(core,"Core",a);
  313. return a;
  314. })
  315. .def("deserialize", [](igl::viewer::ViewerCore& core, const std::vector<char>& a)
  316. {
  317. igl::deserialize(core,"Core",a);
  318. return;
  319. })
  320. // TODO: wrap this!
  321. // Eigen::Quaternionf trackball_angle;
  322. ;
  323. ///////////////////////// VIEWER
  324. // UI Enumerations
  325. py::class_<igl::viewer::Viewer> viewer_class(me, "Viewer");
  326. py::enum_<igl::viewer::Viewer::MouseButton>(viewer_class, "MouseButton")
  327. .value("Left", igl::viewer::Viewer::MouseButton::Left)
  328. .value("Middle", igl::viewer::Viewer::MouseButton::Middle)
  329. .value("Right", igl::viewer::Viewer::MouseButton::Right)
  330. .export_values();
  331. viewer_class
  332. .def(py::init<>())
  333. .def_readwrite("data", &igl::viewer::Viewer::data)
  334. .def_readwrite("core", &igl::viewer::Viewer::core)
  335. .def_readwrite("ngui", &igl::viewer::Viewer::ngui)
  336. .def_readwrite("screen", &igl::viewer::Viewer::screen)
  337. .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false)
  338. .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false)
  339. .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true)
  340. .def("launch_shut", &igl::viewer::Viewer::launch_shut)
  341. .def("init", &igl::viewer::Viewer::init)
  342. .def("serialize", [](igl::viewer::Viewer& viewer)
  343. {
  344. std::vector<char> a;
  345. igl::serialize(viewer.core,"Core",a);
  346. igl::serialize(viewer.data,"Data",a);
  347. return a;
  348. })
  349. .def("deserialize", [](igl::viewer::Viewer& viewer, const std::vector<char>& a)
  350. {
  351. igl::deserialize(viewer.core,"Core",a);
  352. igl::deserialize(viewer.data,"Data",a);
  353. return;
  354. })
  355. // Scene IO
  356. .def("load_scene", [](igl::viewer::Viewer& viewer)
  357. {
  358. viewer.load_scene();
  359. })
  360. .def("load_scene", [](igl::viewer::Viewer& viewer, std::string str)
  361. {
  362. viewer.load_scene(str);
  363. })
  364. .def("save_scene", &igl::viewer::Viewer::save_scene)
  365. // Draw everything
  366. .def("draw", &igl::viewer::Viewer::draw)
  367. // OpenGL context resize
  368. .def("resize", &igl::viewer::Viewer::resize)
  369. // Helper functions
  370. .def("snap_to_canonical_quaternion", &igl::viewer::Viewer::snap_to_canonical_quaternion)
  371. .def("open_dialog_load_mesh", &igl::viewer::Viewer::open_dialog_load_mesh)
  372. .def("open_dialog_save_mesh", &igl::viewer::Viewer::open_dialog_save_mesh)
  373. // Input handling
  374. .def_readwrite("current_mouse_x", &igl::viewer::Viewer::current_mouse_x)
  375. .def_readwrite("current_mouse_y", &igl::viewer::Viewer::current_mouse_y)
  376. // Callbacks
  377. .def_readwrite("callback_init", &igl::viewer::Viewer::callback_init)
  378. .def_readwrite("callback_pre_draw", &igl::viewer::Viewer::callback_pre_draw)
  379. .def_readwrite("callback_post_draw", &igl::viewer::Viewer::callback_post_draw)
  380. .def_readwrite("callback_mouse_down", &igl::viewer::Viewer::callback_mouse_down)
  381. .def_readwrite("callback_mouse_up", &igl::viewer::Viewer::callback_mouse_up)
  382. .def_readwrite("callback_mouse_move", &igl::viewer::Viewer::callback_mouse_move)
  383. .def_readwrite("callback_mouse_scroll", &igl::viewer::Viewer::callback_mouse_scroll)
  384. .def_readwrite("callback_key_pressed", &igl::viewer::Viewer::callback_key_pressed)
  385. .def_readwrite("callback_key_down", &igl::viewer::Viewer::callback_key_down)
  386. .def_readwrite("callback_key_up", &igl::viewer::Viewer::callback_key_up)
  387. ;
  388. }