1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
19 /** \file
20  * \ingroup freestyle
21  * \brief Detects/flags/builds extended features edges on the WXEdge structure
22  */
23 
24 #include <vector>
25 
26 #include "../geometry/Geom.h"
27 
28 #include "../system/FreestyleConfig.h"
29 #include "../system/ProgressBar.h"
30 #include "../system/RenderMonitor.h"
31 
32 #include "../winged_edge/Curvature.h"
33 #include "../winged_edge/WXEdge.h"
34 
35 #include "BLI_math.h"
36 
37 #ifdef WITH_CXX_GUARDEDALLOC
38 #  include "MEM_guardedalloc.h"
39 #endif
40 
41 namespace Freestyle {
42 
43 using namespace Geometry;
44 
45 /*! This class takes as input a WXEdge structure and fills it */
46 class FEdgeXDetector {
47  public:
FEdgeXDetector()48   FEdgeXDetector()
49   {
50     _pProgressBar = NULL;
51     _pRenderMonitor = NULL;
52     _computeViewIndependent = true;
53 #if 0
54     _bbox_diagonal = 1.0;
55 #endif
56     _meanEdgeSize = 0;
57     _computeRidgesAndValleys = true;
58     _computeSuggestiveContours = true;
59     _computeMaterialBoundaries = true;
60     _sphereRadius = 1.0;
61     _orthographicProjection = false;
62     _faceSmoothness = false;
63     _changes = false;
64     _kr_derivative_epsilon = 0.0;
65     _creaseAngle = 0.7;  // angle of 134.43 degrees
66   }
67 
~FEdgeXDetector()68   virtual ~FEdgeXDetector()
69   {
70   }
71 
72   /*! Process shapes from a WingedEdge containing a list of WShapes */
73   virtual void processShapes(WingedEdge &);
74 
75   // GENERAL STUFF
76   virtual void preProcessShape(WXShape *iWShape);
77   virtual void preProcessFace(WXFace *iFace);
78   virtual void computeCurvatures(WXVertex *iVertex);
79 
80   // SILHOUETTE
81   virtual void processSilhouetteShape(WXShape *iWShape);
82   virtual void ProcessSilhouetteFace(WXFace *iFace);
83   virtual void ProcessSilhouetteEdge(WXEdge *iEdge);
84 
85   // CREASE
86   virtual void processCreaseShape(WXShape *iWShape);
87   virtual void ProcessCreaseEdge(WXEdge *iEdge);
88 
89   /*! Sets the minimum angle for detecting crease edges
90    *  \param angle:
91    *    The angular threshold in degrees (between 0 and 180) for detecting crease edges. An edge is
92    * considered a crease edge if the angle between two faces sharing the edge is smaller than the
93    * given threshold.
94    */
95   // XXX angle should be in radian...
setCreaseAngle(float angle)96   inline void setCreaseAngle(float angle)
97   {
98     if (angle < 0.0) {
99       angle = 0.0;
100     }
101     else if (angle > 180.0) {
102       angle = 180.0;
103     }
104     angle = cos(M_PI * (180.0 - angle) / 180.0);
105     if (angle != _creaseAngle) {
106       _creaseAngle = angle;
107       _changes = true;
108     }
109   }
110 
111   // BORDER
112   virtual void processBorderShape(WXShape *iWShape);
113   virtual void ProcessBorderEdge(WXEdge *iEdge);
114 
115   // RIDGES AND VALLEYS
116   virtual void processRidgesAndValleysShape(WXShape *iWShape);
117   virtual void ProcessRidgeFace(WXFace *iFace);
118 
119   // SUGGESTIVE CONTOURS
120   virtual void processSuggestiveContourShape(WXShape *iWShape);
121   virtual void ProcessSuggestiveContourFace(WXFace *iFace);
122   virtual void postProcessSuggestiveContourShape(WXShape *iShape);
123   virtual void postProcessSuggestiveContourFace(WXFace *iFace);
124   /*! Sets the minimal derivative of the radial curvature for suggestive contours
125    *  \param dkr:
126    *    The minimal derivative of the radial curvature
127    */
setSuggestiveContourKrDerivativeEpsilon(float dkr)128   inline void setSuggestiveContourKrDerivativeEpsilon(float dkr)
129   {
130     if (dkr != _kr_derivative_epsilon) {
131       _kr_derivative_epsilon = dkr;
132       _changes = true;
133     }
134   }
135 
136   // MATERIAL BOUNDARY
137   virtual void processMaterialBoundaryShape(WXShape *iWShape);
138   virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge);
139 
140   // EDGE MARKS
141   virtual void processEdgeMarksShape(WXShape *iShape);
142   virtual void ProcessEdgeMarks(WXEdge *iEdge);
143 
144   // EVERYBODY
145   virtual void buildSmoothEdges(WXShape *iShape);
146 
147   /*! Sets the current viewpoint */
setViewpoint(const Vec3f & ivp)148   inline void setViewpoint(const Vec3f &ivp)
149   {
150     _Viewpoint = ivp;
151   }
152 
enableOrthographicProjection(bool b)153   inline void enableOrthographicProjection(bool b)
154   {
155     _orthographicProjection = b;
156   }
157 
enableRidgesAndValleysFlag(bool b)158   inline void enableRidgesAndValleysFlag(bool b)
159   {
160     _computeRidgesAndValleys = b;
161   }
162 
enableSuggestiveContours(bool b)163   inline void enableSuggestiveContours(bool b)
164   {
165     _computeSuggestiveContours = b;
166   }
167 
enableMaterialBoundaries(bool b)168   inline void enableMaterialBoundaries(bool b)
169   {
170     _computeMaterialBoundaries = b;
171   }
172 
enableFaceSmoothness(bool b)173   inline void enableFaceSmoothness(bool b)
174   {
175     if (b != _faceSmoothness) {
176       _faceSmoothness = b;
177       _changes = true;
178     }
179   }
180 
enableFaceMarks(bool b)181   inline void enableFaceMarks(bool b)
182   {
183     if (b != _faceMarks) {
184       _faceMarks = b;
185       _changes = true;
186     }
187   }
188 
189   /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation)
190    *  \param r:
191    *    The radius of the sphere expressed as a ratio of the mean edge size
192    */
setSphereRadius(float r)193   inline void setSphereRadius(float r)
194   {
195     if (r != _sphereRadius) {
196       _sphereRadius = r;
197       _changes = true;
198     }
199   }
200 
setProgressBar(ProgressBar * iProgressBar)201   inline void setProgressBar(ProgressBar *iProgressBar)
202   {
203     _pProgressBar = iProgressBar;
204   }
205 
setRenderMonitor(RenderMonitor * iRenderMonitor)206   inline void setRenderMonitor(RenderMonitor *iRenderMonitor)
207   {
208     _pRenderMonitor = iRenderMonitor;
209   }
210 
211  protected:
212   Vec3f _Viewpoint;
213 #if 0
214   real _bbox_diagonal;  // diagonal of the current processed shape bbox
215 #endif
216   // oldtmp values
217   bool _computeViewIndependent;
218   real _meanK1;
219   real _meanKr;
220   real _minK1;
221   real _minKr;
222   real _maxK1;
223   real _maxKr;
224   unsigned _nPoints;
225   real _meanEdgeSize;
226   bool _orthographicProjection;
227 
228   bool _computeRidgesAndValleys;
229   bool _computeSuggestiveContours;
230   bool _computeMaterialBoundaries;
231   bool _faceSmoothness;
232   bool _faceMarks;
233   float _sphereRadius;  // expressed as a ratio of the mean edge size
234   float _creaseAngle;   // [-1, 1] compared with the inner product of face normals
235   bool _changes;
236 
237   float _kr_derivative_epsilon;
238 
239   ProgressBar *_pProgressBar;
240   RenderMonitor *_pRenderMonitor;
241 
242 #ifdef WITH_CXX_GUARDEDALLOC
243   MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeXDetector")
244 #endif
245 };
246 
247 } /* namespace Freestyle */
248