1 /* This file is part of Dilay 2 * Copyright © 2015-2018 Alexander Bau 3 * Use and redistribute under the terms of the GNU General Public License 4 */ 5 #include <QCheckBox> 6 #include "cache.hpp" 7 #include "distance.hpp" 8 #include "dynamic/mesh.hpp" 9 #include "isosurface-extraction.hpp" 10 #include "mesh.hpp" 11 #include "primitive/aabox.hpp" 12 #include "primitive/cone-sphere.hpp" 13 #include "scene.hpp" 14 #include "sketch/mesh-intersection.hpp" 15 #include "sketch/mesh.hpp" 16 #include "sketch/path.hpp" 17 #include "state.hpp" 18 #include "tool/sculpt/util/action.hpp" 19 #include "tools.hpp" 20 #include "view/pointing-event.hpp" 21 #include "view/resolution-slider.hpp" 22 #include "view/tool-tip.hpp" 23 #include "view/two-column-grid.hpp" 24 #include "view/util.hpp" 25 26 struct ToolConvertSketch::Impl 27 { 28 ToolConvertSketch* self; 29 float resolution; 30 ImplToolConvertSketch::Impl31 Impl (ToolConvertSketch* s) 32 : self (s) 33 , resolution (s->cache ().get<float> ("resolution", 0.06)) 34 { 35 } 36 runInitializeToolConvertSketch::Impl37 ToolResponse runInitialize () 38 { 39 this->setupProperties (); 40 this->setupToolTip (); 41 42 return ToolResponse::Redraw; 43 } 44 setupPropertiesToolConvertSketch::Impl45 void setupProperties () 46 { 47 ViewTwoColumnGrid& properties = this->self->properties (); 48 49 ViewResolutionSlider& resolutionEdit = 50 ViewUtil::resolutionSlider (0.01f, this->resolution, 0.1f); 51 ViewUtil::connect (resolutionEdit, [this](float r) { 52 this->resolution = r; 53 this->self->cache ().set ("resolution", r); 54 }); 55 properties.addStacked (QObject::tr ("Resolution"), resolutionEdit); 56 } 57 setupToolTipToolConvertSketch::Impl58 void setupToolTip () 59 { 60 ViewToolTip toolTip; 61 toolTip.add (ViewInputEvent::MouseLeft, QObject::tr ("Convert selection")); 62 this->self->state ().setToolTip (&toolTip); 63 } 64 convertToolConvertSketch::Impl65 DynamicMesh& convert (SketchMesh& sketch) 66 { 67 glm::vec3 min, max; 68 sketch.minMax (min, max); 69 70 const IsosurfaceExtraction::DistanceCallback getDistance = [&sketch](const glm::vec3& pos) { 71 float distance = Util::maxFloat (); 72 73 if (sketch.tree ().hasRoot ()) 74 { 75 sketch.tree ().root ().forEachConstNode ([&pos, &distance](const SketchNode& node) { 76 const float d = 77 node.parent () 78 ? Distance::distance (PrimConeSphere (node.data (), node.parent ()->data ()), pos) 79 : Distance::distance (node.data (), pos); 80 81 distance = glm::min (distance, d); 82 }); 83 } 84 for (const SketchPath& p : sketch.paths ()) 85 { 86 for (const PrimSphere& s : p.spheres ()) 87 { 88 distance = glm::min (distance, Distance::distance (s, pos)); 89 } 90 } 91 return distance; 92 }; 93 94 sketch.optimizePaths (); 95 DynamicMesh mesh; 96 IsosurfaceExtraction::extract (getDistance, PrimAABox (min, max), this->resolution, mesh); 97 98 State& state = this->self->state (); 99 return state.scene ().newDynamicMesh (state.config (), mesh); 100 } 101 runReleaseEventToolConvertSketch::Impl102 ToolResponse runReleaseEvent (const ViewPointingEvent& e) 103 { 104 if (e.leftButton ()) 105 { 106 SketchMeshIntersection intersection; 107 if (this->self->intersectsScene (e, intersection)) 108 { 109 SketchMesh& sMesh = intersection.mesh (); 110 111 this->self->snapshotAll (); 112 113 ToolSculptAction::smoothMesh (this->convert (sMesh)); 114 this->self->state ().scene ().deleteMesh (sMesh); 115 return ToolResponse::Redraw; 116 } 117 } 118 return ToolResponse::None; 119 } 120 }; 121 122 DELEGATE_TOOL (ToolConvertSketch) 123 DELEGATE_TOOL_RUN_RELEASE_EVENT (ToolConvertSketch) 124