Skip to content

Commit 12532f0

Browse files
Merge branch 'cinder:master' into master
2 parents 96d7700 + 51c39a5 commit 12532f0

File tree

11 files changed

+947
-36
lines changed

11 files changed

+947
-36
lines changed

include/cinder/CinderMath.h

+67-1
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,75 @@ struct CI_API math<float>
123123
#define M_PI 3.14159265358979323846
124124
#endif
125125

126-
const double EPSILON_VALUE = 4.37114e-05;
126+
constexpr double EPSILON_VALUE = 4.37114e-05;
127127
#define EPSILON EPSILON_VALUE
128128

129+
CI_API inline bool approxZero( float n, float epsilon = float(EPSILON_VALUE) )
130+
{
131+
return std::abs( n ) < epsilon;
132+
}
133+
134+
CI_API inline bool approxZero( double n, double epsilon = EPSILON_VALUE )
135+
{
136+
return std::abs( n ) < epsilon;
137+
}
138+
139+
CI_API inline float roundToZero( float n, float epsilon = float(EPSILON_VALUE) )
140+
{
141+
return approxZero( n, epsilon ) ? 0.0f : n;
142+
}
143+
144+
CI_API inline double roundToZero( double n, double epsilon = EPSILON_VALUE )
145+
{
146+
return approxZero( n, epsilon ) ? 0.0 : n;
147+
}
148+
149+
CI_API inline bool approxEqual( float a, float b, float epsilon = float(EPSILON_VALUE) )
150+
{
151+
return std::abs( b - a ) < epsilon;
152+
}
153+
154+
CI_API inline bool approxEqual( double a, double b, double epsilon = EPSILON_VALUE )
155+
{
156+
return std::abs( b - a ) < epsilon;
157+
}
158+
159+
CI_API inline bool approxEqualRelative( float a, float b, float maxRelDiff = float(EPSILON_VALUE) )
160+
{
161+
// See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
162+
163+
// Calculate the difference.
164+
const float diff = std::abs( a - b );
165+
166+
// Find the largest.
167+
a = std::abs( a );
168+
b = std::abs( b );
169+
const float largest = ( b > a ) ? b : a;
170+
171+
if( diff <= largest * maxRelDiff )
172+
return true;
173+
174+
return false;
175+
}
176+
177+
CI_API inline bool approxEqualRelative( double a, double b, double maxRelDiff = EPSILON_VALUE )
178+
{
179+
// See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
180+
181+
// Calculate the difference.
182+
const double diff = std::abs( a - b );
183+
184+
// Find the largest.
185+
a = std::abs( a );
186+
b = std::abs( b );
187+
const double largest = ( b > a ) ? b : a;
188+
189+
if( diff <= largest * maxRelDiff )
190+
return true;
191+
192+
return false;
193+
}
194+
129195
inline float toRadians( float x )
130196
{
131197
return x * 0.017453292519943295769f; // ( x * PI / 180 )

include/cinder/Path2d.h

+68-4
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,75 @@ class CI_API Path2d {
4343
void moveTo( float x, float y ) { moveTo( vec2( x, y ) ); }
4444
void lineTo( const vec2 &p );
4545
void lineTo( float x, float y ) { lineTo( vec2( x, y ) ); }
46+
void horizontalLineTo( float x );
47+
void verticalLineTo( float y );
4648
void quadTo( const vec2 &p1, const vec2 &p2 );
4749
void quadTo( float x1, float y1, float x2, float y2 ) { quadTo( vec2( x1, y1 ), vec2( x2, y2 ) ); }
50+
void smoothQuadTo( const vec2 &p2 );
51+
void smoothQuadTo( float x2, float y2 ) { smoothQuadTo( vec2( x2, y2 ) ); }
4852
void curveTo( const vec2 &p1, const vec2 &p2, const vec2 &p3 );
4953
void curveTo( float x1, float y1, float x2, float y2, float x3, float y3 ) { curveTo( vec2( x1, y1 ), vec2( x2, y2 ), vec2( x3, y3 ) ); }
54+
void smoothCurveTo( const vec2 &p2, const vec2 &p3 );
55+
void smoothCurveTo( float x2, float y2, float x3, float y3 ) { smoothCurveTo( vec2( x2, y2 ), vec2( x3, y3 ) ); }
5056
void arc( const vec2 &center, float radius, float startRadians, float endRadians, bool forward = true );
5157
void arc( float centerX, float centerY, float radius, float startRadians, float endRadians, bool forward = true ) { arc( vec2( centerX, centerY ), radius, startRadians, endRadians, forward ); }
5258
void arcTo( const vec2 &p, const vec2 &t, float radius );
5359
void arcTo( float x, float y, float tanX, float tanY, float radius) { arcTo( vec2( x, y ), vec2( tanX, tanY ), radius ); }
60+
void arcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, const vec2 &p2 );
61+
62+
//!
63+
void relativeMoveTo( float dx, float dy ) { relativeMoveTo( vec2( dx, dy ) ); }
64+
void relativeMoveTo( const vec2 &delta );
65+
void relativeLineTo( float dx, float dy ) { relativeLineTo( vec2( dx, dy ) ); }
66+
void relativeLineTo( const vec2 &delta );
67+
void relativeHorizontalLineTo( float dx );
68+
void relativeVerticalLineTo( float dy );
69+
void relativeQuadTo( float dx1, float dy1, float dx2, float dy2 ) { relativeQuadTo( vec2( dx1, dy1 ), vec2( dx2, dy2 ) ); }
70+
void relativeQuadTo( const vec2 &delta1, const vec2 &delta2 );
71+
void relativeSmoothQuadTo( float dx, float dy ) { relativeSmoothQuadTo( vec2( dx, dy ) ); }
72+
void relativeSmoothQuadTo( const vec2 &delta );
73+
void relativeCurveTo( float dx1, float dy1, float dx2, float dy2, float dx3, float dy3 ) { relativeCurveTo( vec2( dx1, dy1 ), vec2( dx2, dy2 ), vec2( dx3, dy3 ) ); }
74+
void relativeCurveTo( const vec2 &delta1, const vec2 &delta2, const vec2 &delta3 );
75+
void relativeSmoothCurveTo( float dx2, float dy2, float dx3, float dy3 ) { relativeSmoothCurveTo( vec2( dx2, dy2 ), vec2( dx3, dy3 ) ); }
76+
void relativeSmoothCurveTo( const vec2 &delta2, const vec2 &delta3 );
77+
void relativeArcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, float dx, float dy ) { relativeArcTo( rx, ry, phi, largeArcFlag, sweepFlag, vec2( dx, dy ) ); }
78+
void relativeArcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, const vec2 &delta );
5479

5580
//! Closes the path, by drawing a straight line from the first to the last point. This is only legal as the last command.
5681
void close() { mSegments.push_back( CLOSE ); }
57-
bool isClosed() const { return ( mSegments.size() > 1 ) && mSegments.back() == CLOSE; }
82+
bool isClosed() const { return ! mSegments.empty() && mSegments.back() == CLOSE; }
83+
84+
//! Creates a circle with given \a center and \a radius and returns it as a Path2d.
85+
static Path2d circle( const vec2 &center, float radius );
86+
//! Creates an ellipse with given \a center and \a radiusX and \a radiusY and returns it as a Path2d.
87+
static Path2d ellipse( const vec2 &center, float radiusX, float radiusY );
88+
//! Creates a line with given start point \a p0 and end point \a p1 and returns it as a Path2d.
89+
static Path2d line( const vec2 &p0, const vec2 &p1 );
90+
//! Creates a polygon from the given \a points and returns it as a Path2d.
91+
static Path2d polygon( const std::vector<vec2> &points, bool closed = true );
92+
//! Creates a rectangle with given \a bounds and returns it as a Path2d.
93+
static Path2d rectangle( const Rectf &bounds ) { return rectangle( bounds.x1, bounds.y1, bounds.getWidth(), bounds.getHeight() ); }
94+
//! Creates a rectangle with given origin \a x, \a y and size \a width, \a height and returns it as a Path2d.
95+
static Path2d rectangle( float x, float y, float width, float height );
96+
//! Creates a rounded rectangle with given \a bounds and corner radius \a r and returns it as a Path2d.
97+
static Path2d roundedRectangle( const Rectf &bounds, float r ) { return roundedRectangle( bounds, r, r ); }
98+
//! Creates a rounded rectangle with given \a bounds and corner radii \a rx and \a ry and returns it as a Path2d.
99+
static Path2d roundedRectangle( const Rectf &bounds, float rx, float ry ) { return roundedRectangle( bounds.x1, bounds.y1, bounds.getWidth(), bounds.getHeight(), rx, ry ); }
100+
//! Creates a rounded rectangle with given origin \a x, \a y and size \a width, \a height and corner radius \a r returns it as a Path2d.
101+
static Path2d roundedRectangle( float x, float y, float width, float height, float r ) { return roundedRectangle( x, y, width, height, r, r ); }
102+
//! Creates a rounded rectangle with given origin \a x, \a y and size \a width, \a height and corner radii \a rx and \a ry and returns it as a Path2d.
103+
static Path2d roundedRectangle( float x, float y, float width, float height, float rx, float ry );
104+
//! Creates a star with the given \a center and number of \a points and returns it as a Path2d.
105+
static Path2d star( const vec2 &center, int points, float largeRadius, float smallRadius, float rotation = 0 );
106+
//! Creates an arrow from start point \a p0 to end point \a p1 and returns it as a Path2d. The arrow head can be shaped with parameters \a thickness, \a width, \a length and \a concavity.
107+
static Path2d arrow( const vec2 &p0, const vec2 &p1, float thickness, float width = 4, float length = 4, float concavity = 0 );
108+
//! Creates an arrow from start point \a x0, \a y0 to end point \a x1, \a y1 and returns it as a Path2d. The arrow head can be shaped with parameters \a thickness, \a width, \a length and \a concavity.
109+
static Path2d arrow( float x0, float y0, float x1, float y1, float thickness, float width = 4, float length = 4, float concavity = 0 ) { return arrow( vec2( x0, y0 ), vec2( x1, y1 ), thickness, width, length, concavity ); }
110+
//! Creates an Archimedean spiral at \a center and returns it as a Path2d. The spiral runs from \a innerRadius to \a outerRadius and the radius will increase by \a spacing every full revolution.
111+
//! You can provide an optional radial \a offset.
112+
static Path2d spiral( const vec2 &center, float innerRadius, float outerRadius, float spacing, float offset = 0 );
58113

59-
//! Reverses the order of the path's points, inverting its winding order
114+
//! Reverses the orientation of the path, changing CW to CCW and vice versa.
60115
void reverse();
61116

62117
bool empty() const { return mPoints.empty(); }
@@ -94,8 +149,12 @@ class CI_API Path2d {
94149

95150
const std::vector<vec2>& getPoints() const { return mPoints; }
96151
std::vector<vec2>& getPoints() { return mPoints; }
97-
const vec2& getPoint( size_t point ) const { return mPoints[point]; }
98-
vec2& getPoint( size_t point ) { return mPoints[point]; }
152+
const vec2& getPoint( size_t point ) const { return mPoints[ point % mPoints.size() ]; }
153+
vec2& getPoint( size_t point ) { return mPoints[ point % mPoints.size() ]; }
154+
const vec2& getPointBefore( size_t point ) const { return getPoint( point + mPoints.size() - 1 ); }
155+
vec2& getPointBefore( size_t point ) { return getPoint( point + mPoints.size() - 1 ); }
156+
const vec2& getPointAfter( size_t point ) const { return getPoint( point + 1 ); }
157+
vec2& getPointAfter( size_t point ) { return getPoint( point + 1 ); }
99158
const vec2& getCurrentPoint() const { return mPoints.back(); }
100159
void setPoint( size_t index, const vec2 &p ) { mPoints[index] = p; }
101160

@@ -115,6 +174,11 @@ class CI_API Path2d {
115174
//! Returns the precise bounding box around the curve itself. Slower to calculate than calcBoundingBox().
116175
Rectf calcPreciseBoundingBox() const;
117176

177+
//! Returns whether the path is defined in clockwise order.
178+
bool calcClockwise() const;
179+
//! Returns whether the path is defined in counter-clockwise order.
180+
bool calcCounterClockwise() const { return !calcClockwise(); }
181+
118182
//! Returns whether the point \a pt is contained within the boundaries of the Path2d. If \a evenOddFill is \c true (the default) then Even-Odd fill rule is used, otherwise, the Winding fill rule is applied.
119183
bool contains( const vec2 &pt, bool evenOddFill = true ) const;
120184

include/cinder/Shape2d.h

+28
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,43 @@ class CI_API Shape2d {
3737
void moveTo( float x, float y ) { moveTo( vec2( x, y ) ); }
3838
void lineTo( const vec2 &p );
3939
void lineTo( float x, float y ) { lineTo( vec2( x, y ) ); }
40+
void horizontalLineTo( float x );
41+
void verticalLineTo( float y );
4042
void quadTo( const vec2 &p1, const vec2 &p2 );
4143
void quadTo( float x1, float y1, float x2, float y2 ) { quadTo( vec2( x1, y1 ), vec2( x2, y2 ) ); }
44+
void smoothQuadTo( const vec2 &p2 );
45+
void smoothQuadTo( float x2, float y2 ) { smoothQuadTo( vec2( x2, y2 ) ); }
4246
void curveTo( const vec2 &p1, const vec2 &p2, const vec2 &p3 );
4347
void curveTo( float x1, float y1, float x2, float y2, float x3, float y3 ) { curveTo( vec2( x1, y1 ), vec2( x2, y2 ), vec2( x3, y3 ) ); }
48+
void smoothCurveTo( const vec2 &p2, const vec2 &p3 );
49+
void smoothCurveTo( float x2, float y2, float x3, float y3 ) { smoothCurveTo( vec2( x2, y2 ), vec2( x3, y3 ) ); }
4450
void arc( const vec2 &center, float radius, float startRadians, float endRadians, bool forward = true );
4551
void arc( float centerX, float centerY, float radius, float startRadians, float endRadians, bool forward = true ) { arc( vec2( centerX, centerY ), radius, startRadians, endRadians, forward ); }
4652
void arcTo( const vec2 &p, const vec2 &t, float radius );
4753
void arcTo( float x, float y, float tanX, float tanY, float radius) { arcTo( vec2( x, y ), vec2( tanX, tanY ), radius ); }
54+
void arcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, float px, float py ) { arcTo( rx, ry, phi, largeArcFlag, sweepFlag, vec2( px, py ) ); }
55+
void arcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, const vec2 &p2 );
4856
void close();
57+
58+
void relativeMoveTo( const vec2 &p );
59+
void relativeMoveTo( float dx, float dy ) { relativeMoveTo( vec2( dx, dy ) ); }
60+
void relativeLineTo( const vec2 &delta );
61+
void relativeLineTo( float dx, float dy ) { relativeLineTo( vec2( dx, dy ) ); }
62+
void relativeHorizontalLineTo( float dx );
63+
void relativeVerticalLineTo( float dy );
64+
void relativeQuadTo( const vec2 &delta1, const vec2 &delta2 );
65+
void relativeQuadTo( float x1, float y1, float x2, float y2 ) { relativeQuadTo( vec2( x1, y1 ), vec2( x2, y2 ) ); }
66+
void relativeSmoothQuadTo( const vec2 &delta );
67+
void relativeSmoothQuadTo( float x2, float y2 ) { relativeSmoothQuadTo( vec2( x2, y2 ) ); }
68+
void relativeCurveTo( const vec2 &delta1, const vec2 &delta2, const vec2 &delta3 );
69+
void relativeCurveTo( float x1, float y1, float x2, float y2, float x3, float y3 ) { relativeCurveTo( vec2( x1, y1 ), vec2( x2, y2 ), vec2( x3, y3 ) ); }
70+
void relativeSmoothCurveTo( const vec2 &delta2, const vec2 &delta3 );
71+
void relativeSmoothCurveTo( float x2, float y2, float x3, float y3 ) { relativeSmoothCurveTo( vec2( x2, y2 ), vec2( x3, y3 ) ); }
72+
void relativeArcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, float px, float py ) { relativeArcTo( rx, ry, phi, largeArcFlag, sweepFlag, vec2( px, py ) ); }
73+
void relativeArcTo( float rx, float ry, float phi, bool largeArcFlag, bool sweepFlag, const vec2 &delta );
74+
75+
//! Reverses the orientation of the shape's contours, changing CW to CCW and vice versa.
76+
void reverse();
4977

5078
bool empty() const { return mContours.empty(); }
5179
void clear() { mContours.clear(); }

include/cinder/gl/Context.h

+25
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,28 @@ class CI_API Context {
170170
void popFrontFace( bool forceRestore = false );
171171
//! Returns the winding order defining front-facing polygons, either \c GL_CW or \c GL_CCW (the default).
172172
GLenum getFrontFace();
173+
174+
//! Set the current color mask, which enables and disables writing of frame buffer color components.
175+
void colorMask( bool red, bool green, bool blue, bool alpha );
176+
//! Push the current color mask, which enables and disables writing of frame buffer color components.
177+
void pushColorMask( bool red, bool green, bool blue, bool alpha );
178+
//! Pops the current color mask, which enables and disables writing of frame buffer color components.
179+
void popColorMask( bool forceRestore = false );
180+
//! Returns the current color mask, which enables and disables writing of frame buffer color components. Default is \c GL_TRUE for all 4 components (red, green, blue, alpha).
181+
glm::bvec4 getColorMask();
182+
183+
//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
184+
void stencilMask( GLuint mask );
185+
//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
186+
void stencilMask( GLuint front, GLuint back );
187+
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
188+
void pushStencilMask( GLuint mask );
189+
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
190+
void pushStencilMask( GLuint front, GLuint back );
191+
//! Pops the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
192+
void popStencilMask( bool forceRestore = false );
193+
//! Returns the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
194+
glm::u8vec2 getStencilMask();
173195

174196
#if ! defined( CINDER_GL_ES )
175197
//! Analogous to glLogicOp( \a mode ). Valid arguments are \c GL_CLEAR, \c GL_SET, \c GL_COPY, \c GL_COPY_INVERTED, \c GL_NOOP, \c GL_INVERT, \c GL_AND, \c GL_NAND, \c GL_OR, \c GL_NOR, \c GL_XOR, \c GL_EQUIV, \c GL_AND_REVERSE, \c GL_AND_INVERTED, \c GL_OR_REVERSE, or \c GL_OR_INVERTED.
@@ -535,6 +557,9 @@ class CI_API Context {
535557
std::vector<GLenum> mCullFaceStack;
536558
std::vector<GLenum> mFrontFaceStack;
537559

560+
std::vector<glm::bvec4> mColorMaskStack;
561+
std::vector<glm::u8vec2> mStencilMaskStack;
562+
538563
#if ! defined( CINDER_GL_ES )
539564
std::vector<GLenum> mLogicOpStack;
540565
std::vector<GLenum> mPolygonModeStack;

include/cinder/gl/scoped.h

+24
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,30 @@ struct CI_API ScopedFrontFace : private Noncopyable {
360360
Context *mCtx;
361361
};
362362

363+
//! Scopes writing of frame buffer color components
364+
class ScopedColorMask : private Noncopyable {
365+
public:
366+
//! Values for \a red, \a green, \a blue and \a alpha may be \c GL_TRUE or \c GL_FALSE
367+
ScopedColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
368+
~ScopedColorMask();
369+
370+
private:
371+
Context *mCtx;
372+
};
373+
374+
//! Scopes the front and back writing of individual bits in the stencil planes (front and back)
375+
class ScopedStencilMask : private Noncopyable {
376+
public:
377+
//! Values for \a mask may be between \c 0x00 and \c 0xFF
378+
ScopedStencilMask( GLuint mask );
379+
//! Values for \a front and \a back may be between \c 0x00 and \c 0xFF
380+
ScopedStencilMask( GLuint front, GLuint back );
381+
~ScopedStencilMask();
382+
383+
private:
384+
Context *mCtx;
385+
};
386+
363387
#if defined( CINDER_GL_HAS_KHR_DEBUG )
364388

365389
//! Scopes debug group message

0 commit comments

Comments
 (0)