mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-11 15:12:08 +00:00
common/math: introduced custom atan2()
the custom atan2 algorithm by Remez. see: https://en.wikipedia.org/wiki/Remez_algorithm This improved the Lottie example by ~2ms. Total atan2 performance time was reduced by 43%
This commit is contained in:
parent
8c4102362f
commit
79cf7ca5af
9 changed files with 29 additions and 12 deletions
|
@ -238,7 +238,7 @@ float bezAngleAt(const Bezier& bz, float t)
|
||||||
pt.x *= 3;
|
pt.x *= 3;
|
||||||
pt.y *= 3;
|
pt.y *= 3;
|
||||||
|
|
||||||
return mathRad2Deg(atan2(pt.y, pt.x));
|
return mathRad2Deg(mathAtan2(pt.y, pt.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,20 @@
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
|
|
||||||
|
//see: https://en.wikipedia.org/wiki/Remez_algorithm
|
||||||
|
float mathAtan2(float y, float x)
|
||||||
|
{
|
||||||
|
if (y == 0.0f) return 0.0f;
|
||||||
|
|
||||||
|
auto a = std::min(fabsf(x), fabsf(y)) / std::max(fabsf(x), fabsf(y));
|
||||||
|
auto s = a * a;
|
||||||
|
auto r = ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a;
|
||||||
|
if (fabsf(y) > fabsf(x)) r = 1.57079637f - r;
|
||||||
|
if (x < 0) r = 3.14159274f - r;
|
||||||
|
if (y < 0) return -r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool mathInverse(const Matrix* m, Matrix* out)
|
bool mathInverse(const Matrix* m, Matrix* out)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
/* General functions */
|
/* General functions */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
float mathAtan2(float y, float x);
|
||||||
|
|
||||||
static inline float mathDeg2Rad(float degree)
|
static inline float mathDeg2Rad(float degree)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +77,7 @@ bool operator==(const Matrix& lhs, const Matrix& rhs);
|
||||||
|
|
||||||
static inline bool mathRightAngle(const Matrix* m)
|
static inline bool mathRightAngle(const Matrix* m)
|
||||||
{
|
{
|
||||||
auto radian = fabsf(atan2f(m->e21, m->e11));
|
auto radian = fabsf(mathAtan2(m->e21, m->e11));
|
||||||
if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
|
if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -724,10 +724,10 @@ static void _updateStar(LottieGroup* parent, LottiePolyStar* star, Matrix* trans
|
||||||
y = radius * sinf(angle);
|
y = radius * sinf(angle);
|
||||||
|
|
||||||
if (hasRoundness) {
|
if (hasRoundness) {
|
||||||
auto cp1Theta = (atan2f(previousY, previousX) - MATH_PI2 * direction);
|
auto cp1Theta = (mathAtan2(previousY, previousX) - MATH_PI2 * direction);
|
||||||
auto cp1Dx = cosf(cp1Theta);
|
auto cp1Dx = cosf(cp1Theta);
|
||||||
auto cp1Dy = sinf(cp1Theta);
|
auto cp1Dy = sinf(cp1Theta);
|
||||||
auto cp2Theta = (atan2f(y, x) - MATH_PI2 * direction);
|
auto cp2Theta = (mathAtan2(y, x) - MATH_PI2 * direction);
|
||||||
auto cp2Dx = cosf(cp2Theta);
|
auto cp2Dx = cosf(cp2Theta);
|
||||||
auto cp2Dy = sinf(cp2Theta);
|
auto cp2Dy = sinf(cp2Theta);
|
||||||
|
|
||||||
|
@ -810,10 +810,10 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr
|
||||||
y = (radius * sinf(angle));
|
y = (radius * sinf(angle));
|
||||||
|
|
||||||
if (hasRoundness) {
|
if (hasRoundness) {
|
||||||
auto cp1Theta = atan2f(previousY, previousX) - MATH_PI2 * direction;
|
auto cp1Theta = mathAtan2(previousY, previousX) - MATH_PI2 * direction;
|
||||||
auto cp1Dx = cosf(cp1Theta);
|
auto cp1Dx = cosf(cp1Theta);
|
||||||
auto cp1Dy = sinf(cp1Theta);
|
auto cp1Dy = sinf(cp1Theta);
|
||||||
auto cp2Theta = atan2f(y, x) - MATH_PI2 * direction;
|
auto cp2Theta = mathAtan2(y, x) - MATH_PI2 * direction;
|
||||||
auto cp2Dx = cosf(cp2Theta);
|
auto cp2Dx = cosf(cp2Theta);
|
||||||
auto cp2Dy = sinf(cp2Theta);
|
auto cp2Dy = sinf(cp2Theta);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "tvgMath.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
#include "tvgLottieModel.h"
|
#include "tvgLottieModel.h"
|
||||||
|
@ -249,7 +250,7 @@ Fill* LottieGradient::fill(float frameNo, LottieExpressions* exps)
|
||||||
P(static_cast<RadialGradient*>(fill))->radial(s.x, s.y, r, s.x, s.y, 0.0f);
|
P(static_cast<RadialGradient*>(fill))->radial(s.x, s.y, r, s.x, s.y, 0.0f);
|
||||||
} else {
|
} else {
|
||||||
if (mathEqual(progress, 1.0f)) progress = 0.99f;
|
if (mathEqual(progress, 1.0f)) progress = 0.99f;
|
||||||
auto startAngle = mathRad2Deg(atan2(e.y - s.y, e.x - s.x));
|
auto startAngle = mathRad2Deg(mathAtan2(e.y - s.y, e.x - s.x));
|
||||||
auto angle = mathDeg2Rad((startAngle + this->angle(frameNo, exps)));
|
auto angle = mathDeg2Rad((startAngle + this->angle(frameNo, exps)));
|
||||||
auto fx = s.x + cos(angle) * progress * r;
|
auto fx = s.x + cos(angle) * progress * r;
|
||||||
auto fy = s.y + sin(angle) * progress * r;
|
auto fy = s.y + sin(angle) * progress * r;
|
||||||
|
|
|
@ -156,7 +156,7 @@ struct LottieVectorFrame
|
||||||
{
|
{
|
||||||
if (!hasTangent) {
|
if (!hasTangent) {
|
||||||
Point dp = next->value - value;
|
Point dp = next->value - value;
|
||||||
return mathRad2Deg(atan2(dp.y, dp.x));
|
return mathRad2Deg(mathAtan2(dp.y, dp.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = (frameNo - no) / (next->no - no);
|
auto t = (frameNo - no) / (next->no - no);
|
||||||
|
|
|
@ -194,10 +194,10 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P
|
||||||
//We dont' use arccos (as per w3c doc), see
|
//We dont' use arccos (as per w3c doc), see
|
||||||
//http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
|
//http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
|
||||||
//Note: atan2 (0.0, 1.0) == 0.0
|
//Note: atan2 (0.0, 1.0) == 0.0
|
||||||
at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
at = mathAtan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
||||||
theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
|
theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
|
||||||
|
|
||||||
nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
nat = mathAtan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
||||||
deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
|
deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
|
||||||
|
|
||||||
if (sweep) {
|
if (sweep) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "tvgMath.h"
|
||||||
#include "tvgGlTessellator.h"
|
#include "tvgGlTessellator.h"
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
#include "tvgGlList.h"
|
#include "tvgGlList.h"
|
||||||
|
@ -780,7 +781,7 @@ static int32_t _bezierCurveCount(const Bezier &curve)
|
||||||
|
|
||||||
static Bezier _bezFromArc(const GlPoint& start, const GlPoint& end, float radius) {
|
static Bezier _bezFromArc(const GlPoint& start, const GlPoint& end, float radius) {
|
||||||
// Calculate the angle between the start and end points
|
// Calculate the angle between the start and end points
|
||||||
float angle = atan2(end.y - start.y, end.x - start.x);
|
float angle = mathAtan2(end.y - start.y, end.x - start.x);
|
||||||
|
|
||||||
// Calculate the control points of the cubic bezier curve
|
// Calculate the control points of the cubic bezier curve
|
||||||
float c = radius * 0.552284749831; // c = radius * (4/3) * tan(pi/8)
|
float c = radius * 0.552284749831; // c = radius * (4/3) * tan(pi/8)
|
||||||
|
|
|
@ -179,7 +179,7 @@ SwFixed mathTan(SwFixed angle)
|
||||||
SwFixed mathAtan(const SwPoint& pt)
|
SwFixed mathAtan(const SwPoint& pt)
|
||||||
{
|
{
|
||||||
if (pt.zero()) return 0;
|
if (pt.zero()) return 0;
|
||||||
return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
return SwFixed(mathAtan2(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue