#ifndef PtexTriangleKernel_h
#define PtexTriangleKernel_h
#include <assert.h>
#include <algorithm>
#include <numeric>
#include "Ptexture.h"
#include "PtexUtils.h"
static const float PtexTriangleKernelWidth = 3.5;
class PtexTriangleKernelIter : public Ptex {
public:
int rowlen;
double u, v;
int u1, v1, w1;
int u2, v2, w2;
double A,B,C;
bool valid;
double wscale;
double weight;
void apply(double* dst, void* data, DataType dt, int nChan, int nTxChan)
{
ApplyFn fn = applyFunctions[(nChan!=nTxChan)*20 + ((unsigned)nChan<=4)*nChan*4 + dt];
fn(*this, dst, data, nChan, nTxChan);
}
void applyConst(double* dst, void* data, DataType dt, int nChan);
private:
typedef void (*ApplyFn)(PtexTriangleKernelIter& k, double* dst, void* data, int nChan, int nTxChan);
static ApplyFn applyFunctions[40];
};
class PtexTriangleKernel : public Ptex {
public:
Res res;
double u, v;
double u1, v1, w1;
double u2, v2, w2;
double A,B,C;
void set(Res resVal, double uVal, double vVal,
double u1Val, double v1Val, double w1Val,
double u2Val, double v2Val, double w2Val,
double AVal, double BVal, double CVal)
{
res = resVal;
u = uVal; v = vVal;
u1 = u1Val; v1 = v1Val; w1 = w1Val;
u2 = u2Val; v2 = v2Val; w2 = w2Val;
A = AVal; B = BVal; C = CVal;
}
void set(double uVal, double vVal,
double u1Val, double v1Val, double w1Val,
double u2Val, double v2Val, double w2Val)
{
u = uVal; v = vVal;
u1 = u1Val; v1 = v1Val; w1 = w1Val;
u2 = u2Val; v2 = v2Val; w2 = w2Val;
}
void setABC(double AVal, double BVal, double CVal)
{
A = AVal; B = BVal; C = CVal;
}
void splitU(PtexTriangleKernel& ka)
{
ka = *this;
u1 = 0;
ka.u2 = 0;
}
void splitV(PtexTriangleKernel& ka)
{
ka = *this;
v1 = 0;
ka.v2 = 0;
}
void splitW(PtexTriangleKernel& ka)
{
ka = *this;
w1 = 0;
ka.w2 = 0;
}
void rotate1()
{
setABC(C, 2*C-B, A+C-B);
}
void rotate2()
{
setABC(A+C-B, 2*A-B, A);
}
void reorient(int eid, int aeid)
{
double w = 1-u-v;
#define C(eid, aeid) (eid*3 + aeid)
switch (C(eid, aeid)) {
case C(0, 0): set(1-u, -v, 1-u2, -v2, 1-w2, 1-u1, -v1, 1-w1); break;
case C(0, 1): set(1-w, 1-u, 1-w2, 1-u2, -v2, 1-w1, 1-u1, -v1); rotate1(); break;
case C(0, 2): set( -v, 1-w, -v2, 1-w2, 1-u2, -v1, 1-w1, 1-u1); rotate2(); break;
case C(1, 0): set(1-v, -w, 1-v2, -w2, 1-u2, 1-v1, -w1, 1-u1); rotate2(); break;
case C(1, 1): set(1-u, 1-v, 1-u2, 1-v2, -w2, 1-u1, 1-v1, -w1); break;
case C(1, 2): set( -w, 1-u, -w2, 1-u2, 1-v2, -w1, 1-u1, 1-v1); rotate1(); break;
case C(2, 0): set(1-w, -u, 1-w2, -u2, 1-v2, 1-w1, -u1, 1-v1); rotate1(); break;
case C(2, 1): set(1-v, 1-w, 1-v2, 1-w2, -u2, 1-v1, 1-w1, -u1); rotate2(); break;
case C(2, 2): set( -u, 1-v, -u2, 1-v2, 1-w2, -u1, 1-v1, 1-w1); break;
#undef C
}
}
void clampRes(Res fres)
{
res.ulog2 = PtexUtils::min(res.ulog2, fres.ulog2);
res.vlog2 = res.ulog2;
}
void clampExtent()
{
u1 = PtexUtils::max(u1, 0.0);
v1 = PtexUtils::max(v1, 0.0);
w1 = PtexUtils::max(w1, 0.0);
u2 = PtexUtils::min(u2, 1-(v1+w1));
v2 = PtexUtils::min(v2, 1-(w1+u1));
w2 = PtexUtils::min(w2, 1-(u1+v1));
}
void getIterators(PtexTriangleKernelIter& ke, PtexTriangleKernelIter& ko)
{
int resu = res.u();
double Finv = 1.0/(resu*resu*(A*C - 0.25 * B * B));
double Ak = A*Finv, Bk = B*Finv, Ck = C*Finv;
ke.rowlen = resu;
ke.wscale = 1.0/(resu*resu);
double scale = ke.rowlen;
ke.u = u * scale - 1/3.0;
ke.v = v * scale - 1/3.0;
ke.u1 = int(ceil(u1 * scale - 1/3.0));
ke.v1 = int(ceil(v1 * scale - 1/3.0));
ke.w1 = int(ceil(w1 * scale - 1/3.0));
ke.u2 = int(ceil(u2 * scale - 1/3.0));
ke.v2 = int(ceil(v2 * scale - 1/3.0));
ke.w2 = int(ceil(w2 * scale - 1/3.0));
ke.A = Ak; ke.B = Bk; ke.C = Ck;
ke.valid = (ke.u2 > ke.u1 && ke.v2 > ke.v1 && ke.w2 > ke.w1);
ke.weight = 0;
ko.rowlen = ke.rowlen;
ko.wscale = ke.wscale;
ko.u = (1-v) * scale - 1/3.0;
ko.v = (1-u) * scale - 1/3.0;
ko.u1 = int(ceil((1-v2) * scale - 1/3.0));
ko.v1 = int(ceil((1-u2) * scale - 1/3.0));
ko.w1 = int(ceil(( -w2) * scale - 1/3.0));
ko.u2 = int(ceil((1-v1) * scale - 1/3.0));
ko.v2 = int(ceil((1-u1) * scale - 1/3.0));
ko.w2 = int(ceil(( -w1) * scale - 1/3.0));
ko.A = Ck; ko.B = Bk; ko.C = Ak;
ko.valid = (ko.u2 > ko.u1 && ko.v2 > ko.v1 && ko.w2 > ko.w1);
ko.weight = 0;
}
};
#endif