commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,549 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cmath>
#include "geometry/curve.h"
#include "sort/sort.h"
using namespace GS;
//------------------------------------------------------------------------------
void Curve::Update(const CurvePoint &p, const Time &t_epsilon)
{
for (uint n = 0; n < points.GetCount(); ++n)
{
CurvePoint *point = points[n];
if ((p.t >= (point->t - t_epsilon)) && (p.t <= (point->t + t_epsilon)))
{
point->v = p.v;
return;
}
}
Insert(p);
}
void Curve::Insert(const CurvePoint &k)
{
int idx = GetPointIndex(k.t);
points.Insert(new CurvePoint(k), (idx == -1) ? points.GetCount() : idx);
}
void Curve::Append(const CurvePoint &k)
{
points.Insert(new CurvePoint(k), points.GetCount());
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Curve::Delete(CurvePoint *k)
{
points.Remove(k);
delete k;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int Curve::GetPointIndex(const Time &t, bool t_greater) const
{
if (points.GetCount() == 0)
return -1;
if (t_greater)
{
for (uint n = 0; n < points.GetCount(); ++n)
if (points[n]->t > t)
return n;
}
else
{
for (int n = points.GetCount() - 1; n >= 0; --n)
if (points[n]->t <= t)
return n;
}
return -1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
TimeRange Curve::GetTimeRange() const
{
return points.GetCount() == 0 ? TimeRange() : TimeRange(points[0]->t, points[points.GetCount() - 1]->t);
}
Range <float> Curve::GetValueRange() const
{
if (points.GetCount() == 0)
return Range <float> ();
Range <float> range(points[0]->v, points[0]->v);
for (uint n = 1; n < points.GetCount(); ++n)
{
range.start = Types::Min(range.start, points[n]->v);
range.end = Types::Max(range.end, points[n]->v);
}
return range;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint Curve::Optimize(uint point_count, const CurvePoint *skf, CurvePoint *dkf, float threshold)
{
if (point_count < 3)
return 0;
uint ckf = 0, n;
for (n = 1; n < (point_count - 1); n += 2)
{
float k = (skf[n].t - skf[n - 1].t).toSec() / (skf[n + 1].t - skf[n - 1].t).toSec();
float iv = (skf[n - 1].v * k) + (skf[n + 1].v * (1.f - k));
dkf[ckf++] = skf[n - 1];
if (fabs(skf[n].v - iv) > threshold)
dkf[ckf++] = skf[n];
}
if (n == (point_count - 1))
dkf[ckf++] = skf[point_count - 2];
dkf[ckf++] = skf[point_count - 1];
return point_count - ckf;
}
uint Curve::Optimize(float threshold)
{
if (!points.GetCount())
return 0;
Array <CurvePoint> skf(points.GetCount(), Alloc::Curve), dkf(points.GetCount(), Alloc::Curve);
if (skf.IsNull() || dkf.IsNull())
__ERR__(__LOG__ << "Not enough memory.\n", 0);
// Freeze array.
for (uint n = 0; n < points.GetCount(); ++n)
skf[n] = *points[n];
// Optimize curve.
uint gain = Optimize(points.GetCount(), skf.c_ptr(), dkf.c_ptr(), threshold), out = points.GetCount() - gain;
if (gain)
{
// Send back to curve.
if (!AllocatePoint(out))
__ERR__(__LOG__ << "Failed to reallocate optimized array.\n", 0);
for (uint n = 0; n < points.GetCount(); ++n)
SetPoint(n, dkf[n]);
}
return gain;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Curve::AllocatePoint(uint n)
{
ArrayListDeleteAllPtr(CurvePoint *, points)
while (n--)
if (!points.Add(new CurvePoint))
return false;
return true;
}
void Curve::SetPoint(uint i, const CurvePoint &p) const
{ *points[i] = p; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Curve::Sort()
{
// Make sure there is work to do.
bool need_sorting = false;
for (uint n = 1; n < points.GetCount(); ++n)
if (points[n - 1]->t > points[n]->t)
{
need_sorting = true;
break;
}
if (!need_sorting)
return;
// Sort keys.
uint count = points.GetCount();
Array <GS::Sort<Time, CurvePoint *>::Entry> entries(count);
for (uint n = 0; n < count; ++n)
{
entries[n].v = points[n]->t;
entries[n].o = points[n];
}
GS::Sort<Time, CurvePoint *>::QuickSort(count, entries);
// Drop current array and rewrite ordered one.
points.Clear(false);
for (uint n = 0; n < count; ++n)
points.Add(entries[n].o);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static float range(float v, float lo, float hi, int *i)
{
float r = hi - lo;
if (r == 0.f)
{
if (i)
*i = 0;
return lo;
}
float v2 = v - lo;
if (v2 >= 0.f)
v2 = lo + v2 - r * floor(v2 / r);
else
v2 = hi + v2 - r * ceil(v2 / r);
if (i)
*i = -(int)((v2 - v) / r + (v2 > v ? 0.5f : -0.5f));
return Types::Clamp(v2, lo, hi);
}
static void hermite(float t, float *h1, float *h2, float *h3, float *h4)
{
float t2 = t * t, t3 = t * t2;
*h2 = 3.f * t2 - t3 - t3;
*h1 = 1.f - *h2;
*h4 = t3 - t2;
*h3 = *h4 - t2 + t;
}
static float bezier(float x0, float x1, float x2, float x3, float t)
{
float a, b, c, t2 = t * t, t3 = t * t2;
c = 3.f * (x1 - x0);
b = 3.f * (x2 - x1) - c;
a = x3 - x0 - c - b;
return a * t3 + b * t2 + c * t + x0;
}
static float bez2_time(float x0, float x1, float x2, float x3, float time, float *t0, float *t1)
{
float t = *t0 + (*t1 - *t0) * 0.5f, v = bezier(x0, x1, x2, x3, t);
if ((fabs(*t1 - *t0) > .0001f) && (fabs(time - v) > .0001f))
{
if (v > time)
*t1 = t;
else
*t0 = t;
return bez2_time(x0, x1, x2, x3, time, t0, t1);
}
return t;
}
static float bez2(const CurvePoint *key0, const CurvePoint *key1, float time)
{
float x, y, t, t0 = 0.f, t1 = 1.f;
if (key0->shape == CurvePoint::Shape_Bezier2)
x = key0->t.toSec() + key0->param[2];
else
x = key0->t.toSec() + (key1->t - key0->t).toSec() / 3.f;
t = bez2_time(key0->t.toSec(), x, key1->t.toSec() + key1->param[0], key1->t.toSec(), time, &t0, &t1);
if (key0->shape == CurvePoint::Shape_Bezier2)
y = key0->v + key0->param[3];
else
y = key0->v + key0->param[1] / 3.f;
return bezier(key0->v, y, key1->param[1] + key1->v, key1->v, t);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float Curve::Outgoing(const CurvePoint *key0, const CurvePoint *key1, const CurvePoint *keyp) const
{
float a, b, d, t, out;
switch (key1->shape)
{
case CurvePoint::Shape_Linear:
d = key1->v - key0->v;
if (keyp)
{
t = (key1->t - key0->t).toSec() / (key1->t - keyp->t).toSec();
out = t * ((key0->v - keyp->v) + d);
}
else
out = d;
break;
case CurvePoint::Shape_TCB:
a = (1 - key0->tension)
* (1 + key0->continuity)
* (1 + key0->bias);
b = (1 - key0->tension)
* (1 - key0->continuity)
* (1 - key0->bias);
d = key1->v - key0->v;
if (keyp)
{
t = (key1->t - key0->t).toSec() / (key1->t - keyp->t).toSec();
out = t * (a * (key0->v - keyp->v) + b * d);
}
else
out = b * d;
break;
case CurvePoint::Shape_Bezier:
case CurvePoint::Shape_Hermite:
out = key0->param[0];
if (keyp)
out *= (key1->t - key0->t).toSec() / (key1->t - keyp->t).toSec();
break;
case CurvePoint::Shape_Bezier2:
out = key0->param[3] * (key1->t - key0->t).toSec();
if (fabs(key0->param[2]) > 1e-5f)
out /= key0->param[2];
else
out *= 1e5f;
break;
case CurvePoint::Shape_Step:
default:
out = 0;
break;
}
return out;
}
float Curve::Incoming(const CurvePoint *key0, const CurvePoint *key1, const CurvePoint *key2) const
{
float a, b, d, t, in;
switch (key1->shape)
{
case CurvePoint::Shape_Linear:
d = key1->v - key0->v;
if (key2)
{
t = (key1->t - key0->t).toSec() / (key2->t - key0->t).toSec();
in = t * ((key2->v - key1->v) + d);
}
else
in = d;
break;
case CurvePoint::Shape_TCB:
a = (1 - key1->tension)
* (1 - key1->continuity)
* (1 + key1->bias);
b = (1 - key1->tension)
* (1 + key1->continuity)
* (1 - key1->bias);
d = key1->v - key0->v;
if (key2)
{
t = (key1->t - key0->t).toSec() / (key2->t - key0->t).toSec();
in = t * (b * (key2->v - key1->v) + a * d);
}
else
in = a * d;
break;
case CurvePoint::Shape_Bezier:
case CurvePoint::Shape_Hermite:
in = key1->param[0];
if (key2)
in *= (key1->t - key0->t).toSec() / (key2->t - key0->t).toSec();
break;
case CurvePoint::Shape_Bezier2:
in = key1->param[1] * (key1->t - key0->t).toSec();
if (fabs(key1->param[0]) > 1e-5f)
in /= key1->param[0];
else in *= 1e5f;
break;
case CurvePoint::Shape_Step:
default:
in = 0;
break;
}
return in;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Curve::Evaluate(Time t, float *p, LoopMode loop, Time loop_start, Time loop_end) const
{
int point_count = points.GetCount();
if (point_count == 0)
{
*p = 0;
return;
}
if (point_count == 1)
{
*p = points[0]->v;
return;
}
// Loop mode.
CurvePoint *skey = points[0], *ekey = points[point_count - 1];
loop_start = (loop_start == Time::Inf) ? skey->t : Types::Clamp(loop_start, skey->t, ekey->t);
loop_end = (loop_end == Time::Inf) ? ekey->t : Types::Clamp(loop_end, skey->t, ekey->t);
int noff = 0;
float offset = 0;
if (t < loop_start)
{
switch (loop)
{
case Reset:
*p = 0.f;
return;
default:
case Constant:
Evaluate(loop_start, p, loop, loop_start, loop_end);
return;
case Repeat:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), NULL));
break;
case Oscillate:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
if (noff % 2)
t = loop_end + loop_start - t;
break;
case OffsetAndRepeat:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
offset = noff * (ekey->v - skey->v); // Broken on custom loop point.
break;
}
}
else if (t > loop_end)
{
switch (loop)
{
case Reset:
*p = 0.f;
return;
default:
case Constant:
Evaluate(loop_end, p, loop, loop_start, loop_end);
return;
case Repeat:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), NULL));
break;
case Oscillate:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
if (noff % 2)
t = loop_end + loop_start - t;
break;
case OffsetAndRepeat:
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
offset = noff * (ekey->v - skey->v);
break;
}
}
// Seek to current key.
int ikey0;
#if 1
{
uint lo = 0, hi = points.GetCount() - 1;
forever
{
uint mid = (lo + hi) / 2;
if (points[mid]->t > t)
hi = mid;
else
{
if (lo == mid)
{
ikey0 = lo;
break;
}
else
lo = mid;
}
}
}
#else
ikey0 = 0;
while (((ikey0 + 1) < point_count) && (t > points[ikey0 + 1]->t))
ikey0++;
#endif
CurvePoint *pkey0 = points[ikey0];
if (pkey0 == NULL)
return;
// Sample curve.
CurvePoint *pkeyp = ikey0 > 0 ? points[ikey0 - 1] : NULL;
int ikey1 = ikey0 + 1;
CurvePoint *pkey1 = points[ikey1], *pkey2 = ikey1 < (point_count - 1) ? points[ikey1 + 1] : NULL;
if (t == pkey0->t)
*p = pkey0->v + offset;
else if (t == pkey1->t)
*p = pkey1->v + offset;
else
{
const float k_t = (t - pkey0->t).toSec() / (pkey1->t - pkey0->t).toSec();
switch (pkey0->shape)
{
case CurvePoint::Shape_TCB:
case CurvePoint::Shape_Bezier:
case CurvePoint::Shape_Hermite:
{
float out = Outgoing(pkey0, pkey1, pkeyp), in = Incoming(pkey0, pkey1, pkey2);
float h1, h2, h3, h4;
hermite(k_t, &h1, &h2, &h3, &h4);
*p = h1 * pkey0->v + h2 * pkey1->v + h3 * out + h4 * in + offset;
}
break;
case CurvePoint::Shape_Bezier2:
*p = bez2(pkey0, pkey1, k_t) + offset;
break;
case CurvePoint::Shape_Linear:
*p = pkey0->v + k_t * (pkey1->v - pkey0->v) + offset;
break;
case CurvePoint::Shape_Step:
*p = pkey0->v + offset;
break;
default:
*p = offset;
break;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Curve::Clear()
{
ArrayListDeleteAllPtr(CurvePoint *, points)
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Curve::~Curve()
{ Clear(); }
//------------------------------------------------------------------------------