mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
wg_engine: added math and polyline structures for geometry generating optimizations
[issues 1479: lottie](#1479)
This commit is contained in:
parent
3a03fd7080
commit
90ce9d81bc
3 changed files with 206 additions and 24 deletions
|
@ -22,6 +22,159 @@
|
||||||
|
|
||||||
#include "tvgWgGeometry.h"
|
#include "tvgWgGeometry.h"
|
||||||
|
|
||||||
|
//***********************************************************************
|
||||||
|
// WgPolyline
|
||||||
|
//***********************************************************************
|
||||||
|
|
||||||
|
WgMath* WgGeometryData::gMath = nullptr;
|
||||||
|
|
||||||
|
void WgMath::initialize()
|
||||||
|
{
|
||||||
|
if (initialized) return;
|
||||||
|
initialized = true;
|
||||||
|
const uint32_t nPoints = 360;
|
||||||
|
sinus.reserve(360);
|
||||||
|
cosin.reserve(360);
|
||||||
|
for (uint32_t i = 0; i < nPoints; i++) {
|
||||||
|
float angle = i * (2 * M_PI) / nPoints;
|
||||||
|
sinus.push(sin(angle));
|
||||||
|
cosin.push(cos(angle));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void WgMath::release() {
|
||||||
|
sinus.clear();
|
||||||
|
cosin.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
//***********************************************************************
|
||||||
|
// WgPolyline
|
||||||
|
//***********************************************************************
|
||||||
|
|
||||||
|
WgPolyline::WgPolyline()
|
||||||
|
{
|
||||||
|
pts.reserve(1024);
|
||||||
|
dist.reserve(1014);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::appendPoint(WgPoint pt)
|
||||||
|
{
|
||||||
|
if (pts.count > 0) {
|
||||||
|
float distance = pts.last().dist(pt);
|
||||||
|
if (distance > 0) {
|
||||||
|
// update min and max indexes
|
||||||
|
iminx = pts[iminx].x >= pt.x ? pts.count : iminx;
|
||||||
|
imaxx = pts[imaxx].x <= pt.x ? pts.count : imaxx;
|
||||||
|
iminy = pts[iminy].y >= pt.y ? pts.count : iminy;
|
||||||
|
imaxy = pts[imaxy].y <= pt.y ? pts.count : imaxy;
|
||||||
|
// update total length
|
||||||
|
len += distance;
|
||||||
|
// update points and distances
|
||||||
|
pts.push(pt);
|
||||||
|
dist.push(distance);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// reset min and max indexes and total length
|
||||||
|
iminx = imaxx = iminy = imaxy = 0;
|
||||||
|
len = 0.0f;
|
||||||
|
// update points and distances
|
||||||
|
pts.push(pt);
|
||||||
|
dist.push(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::appendCubic(WgPoint p1, WgPoint p2, WgPoint p3)
|
||||||
|
{
|
||||||
|
WgPoint p0 = pts.count > 0 ? pts.last() : WgPoint(0.0f, 0.0f);
|
||||||
|
size_t segs = ((uint32_t)(p0.dist(p3) / 8.0f));
|
||||||
|
segs = segs == 0 ? 1 : segs;
|
||||||
|
for (size_t i = 1; i <= segs; i++) {
|
||||||
|
float t = i / (float)segs;
|
||||||
|
// get cubic spline interpolation coefficients
|
||||||
|
float t0 = 1.0f * (1.0f - t) * (1.0f - t) * (1.0f - t);
|
||||||
|
float t1 = 3.0f * (1.0f - t) * (1.0f - t) * t;
|
||||||
|
float t2 = 3.0f * (1.0f - t) * t * t;
|
||||||
|
float t3 = 1.0f * t * t * t;
|
||||||
|
appendPoint(p0 * t0 + p1 * t1 + p2 * t2 + p3 * t3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::trim(WgPolyline* polyline, float trimBegin, float trimEnd) const
|
||||||
|
{
|
||||||
|
assert(polyline);
|
||||||
|
polyline->clear();
|
||||||
|
float begLen = len * trimBegin;
|
||||||
|
float endLen = len * trimEnd;
|
||||||
|
float currentLength = 0.0f;
|
||||||
|
// find start point
|
||||||
|
uint32_t indexStart = 0;
|
||||||
|
WgPoint pointStart{};
|
||||||
|
currentLength = 0.0f;
|
||||||
|
for (indexStart = 1; indexStart < pts.count; indexStart++) {
|
||||||
|
currentLength += dist[indexStart];
|
||||||
|
if(currentLength >= begLen) {
|
||||||
|
float t = 1.0f - (currentLength - begLen) / dist[indexStart];
|
||||||
|
pointStart = pts[indexStart-1] * (1.0f - t) + pts[indexStart] * t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indexStart >= pts.count) return;
|
||||||
|
// find end point
|
||||||
|
uint32_t indexEnd = 0;
|
||||||
|
WgPoint pointEnd{};
|
||||||
|
currentLength = 0.0f;
|
||||||
|
for (indexEnd = 1; indexEnd < pts.count; indexEnd++) {
|
||||||
|
currentLength += dist[indexEnd];
|
||||||
|
if(currentLength >= endLen) {
|
||||||
|
float t = 1.0f - (currentLength - endLen) / dist[indexEnd];
|
||||||
|
pointEnd = pts[indexEnd-1] * (1.0f - t) + pts[indexEnd] * t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indexEnd >= pts.count) return;
|
||||||
|
// fill polyline
|
||||||
|
polyline->appendPoint(pointStart);
|
||||||
|
for (uint32_t i = indexStart; i <= indexEnd - 1; i++)
|
||||||
|
polyline->appendPoint(pts[i]);
|
||||||
|
polyline->appendPoint(pointEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::close()
|
||||||
|
{
|
||||||
|
if (pts.count > 0) appendPoint(pts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WgPolyline::isClosed() const
|
||||||
|
{
|
||||||
|
return (pts.count >= 2) && (pts[0].dist2(pts.last()) == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::clear()
|
||||||
|
{
|
||||||
|
// reset min and max indexes and total length
|
||||||
|
iminx = imaxx = iminy = imaxy = 0;
|
||||||
|
len = 0.0f;
|
||||||
|
// clear points and distances
|
||||||
|
pts.clear();
|
||||||
|
dist.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgPolyline::getBBox(WgPoint& pmin, WgPoint& pmax) const
|
||||||
|
{
|
||||||
|
pmin.x = pts[iminx].x;
|
||||||
|
pmin.y = pts[iminy].y;
|
||||||
|
pmax.x = pts[imaxx].x;
|
||||||
|
pmax.y = pts[imaxy].y;
|
||||||
|
}
|
||||||
|
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
// WgGeometryData
|
// WgGeometryData
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
|
@ -49,34 +49,59 @@ public:
|
||||||
WgPoint operator / (const float c) const { return { x / c, y / c }; }
|
WgPoint operator / (const float c) const { return { x / c, y / c }; }
|
||||||
|
|
||||||
WgPoint negative() const { return {-x, -y}; }
|
WgPoint negative() const { return {-x, -y}; }
|
||||||
void negate() { x = -x; y = -y; }
|
inline void negate() { x = -x; y = -y; }
|
||||||
float length() const { return sqrt(x*x + y*y); }
|
inline float length() const { return sqrt(x*x + y*y); }
|
||||||
|
inline float dot(const WgPoint& p) const { return x * p.x + y * p.y; }
|
||||||
float dot(const WgPoint& p) const { return x * p.x + y * p.y; }
|
inline float dist(const WgPoint& p) const { return sqrt(dist2(p)); }
|
||||||
float dist(const WgPoint& p) const
|
inline float dist2(const WgPoint& p) const { return ((p.x - x)*(p.x - x) + (p.y - y)*(p.y - y)); }
|
||||||
{
|
inline void normalize() { float rlen = 1.0f / length(); x *= rlen; y *= rlen; }
|
||||||
return sqrt(
|
inline WgPoint normal() const { float rlen = 1.0f / length(); return { x * rlen, y * rlen }; }
|
||||||
(p.x - x)*(p.x - x) +
|
inline WgPoint lerp(const WgPoint& p, float t) const { return { x + (p.x - x) * t, y + (p.y - y) * t }; };
|
||||||
(p.y - y)*(p.y - y)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void normalize()
|
|
||||||
{
|
|
||||||
float rlen = 1.0f / length();
|
|
||||||
x *= rlen;
|
|
||||||
y *= rlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
WgPoint normal() const
|
|
||||||
{
|
|
||||||
float rlen = 1.0f / length();
|
|
||||||
return { x * rlen, y * rlen };
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct WgMath
|
||||||
|
{
|
||||||
|
Array<float> sinus;
|
||||||
|
Array<float> cosin;
|
||||||
|
bool initialized{};
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void release();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct WgPolyline
|
||||||
|
{
|
||||||
|
Array<WgPoint> pts;
|
||||||
|
Array<float> dist;
|
||||||
|
// polyline bbox points indexes
|
||||||
|
uint32_t iminx{};
|
||||||
|
uint32_t iminy{};
|
||||||
|
uint32_t imaxx{};
|
||||||
|
uint32_t imaxy{};
|
||||||
|
// total polyline length
|
||||||
|
float len{};
|
||||||
|
|
||||||
|
WgPolyline();
|
||||||
|
|
||||||
|
void appendPoint(WgPoint pt);
|
||||||
|
void appendCubic(WgPoint p1, WgPoint p2, WgPoint p3);
|
||||||
|
|
||||||
|
void trim(WgPolyline* polyline, float trimBegin, float trimEnd) const;
|
||||||
|
|
||||||
|
void close();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
bool isClosed() const;
|
||||||
|
void getBBox(WgPoint& pmin, WgPoint& pmax) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct WgGeometryData
|
struct WgGeometryData
|
||||||
{
|
{
|
||||||
|
static WgMath* gMath;
|
||||||
|
|
||||||
Array<WgPoint> positions{};
|
Array<WgPoint> positions{};
|
||||||
Array<WgPoint> texCoords{};
|
Array<WgPoint> texCoords{};
|
||||||
Array<uint32_t> indexes{};
|
Array<uint32_t> indexes{};
|
||||||
|
|
|
@ -49,11 +49,15 @@ void WgRenderer::initialize()
|
||||||
mBlendMethodPool.initialize(mContext);
|
mBlendMethodPool.initialize(mContext);
|
||||||
mCompositeMethodPool.initialize(mContext);
|
mCompositeMethodPool.initialize(mContext);
|
||||||
WgMeshDataGroup::MeshDataPool = new WgMeshDataPool();
|
WgMeshDataGroup::MeshDataPool = new WgMeshDataPool();
|
||||||
|
WgGeometryData::gMath = new WgMath();
|
||||||
|
WgGeometryData::gMath->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderer::release()
|
void WgRenderer::release()
|
||||||
{
|
{
|
||||||
|
WgGeometryData::gMath->release();
|
||||||
|
delete WgGeometryData::gMath;
|
||||||
mRenderDataShapePool.release(mContext);
|
mRenderDataShapePool.release(mContext);
|
||||||
WgMeshDataGroup::MeshDataPool->release(mContext);
|
WgMeshDataGroup::MeshDataPool->release(mContext);
|
||||||
delete WgMeshDataGroup::MeshDataPool;
|
delete WgMeshDataGroup::MeshDataPool;
|
||||||
|
|
Loading…
Add table
Reference in a new issue