wg_engine: added math and polyline structures for geometry generating optimizations

[issues 1479: lottie](#1479)
This commit is contained in:
Sergii Liebodkin 2024-04-16 11:18:27 +03:00 committed by Hermet Park
parent 3a03fd7080
commit 90ce9d81bc
3 changed files with 206 additions and 24 deletions

View file

@ -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
//*********************************************************************** //***********************************************************************

View file

@ -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{};

View file

@ -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;