1 #ifndef PtexSeparableKernel_h
2 #define PtexSeparableKernel_h
55 static const int kmax = 10;
61 : res(0), u(0), v(0), uw(0), vw(0), ku(kubuff), kv(kvbuff), rot(0)
81 const float* kuVal,
const float* kvVal,
int rotVal=0)
83 assert(uwVal <= kmax && vwVal <= kmax);
89 memcpy(kubuff, kuVal,
sizeof(*ku)*uw);
90 memcpy(kvbuff, kvVal,
sizeof(*kv)*vw);
98 while (ku[0] == 0) { ku++; u++; uw--; }
99 while (ku[uw-1] == 0) { uw--; }
100 while (kv[0] == 0) { kv++; v++; vw--; }
101 while (kv[vw-1] == 0) { vw--; }
102 assert(uw > 0 && vw > 0);
122 int w = uw + u - res.u();
123 float* kp = ku + uw - w;
141 int w = vw + v - res.v();
142 float* kp = kv + vw - w;
174 int w = u + uw - res.u();
179 k.
set(res, 0, v, w, vw, ku + uw - w, kv);
217 int w = v + vw - res.v();
221 k.
set(res, u, 0, uw, w, ku, kv + vw - w);
236 u = res.u() - u -
uw;
237 std::reverse(ku, ku+uw);
242 v = res.v() - v -
vw;
243 std::reverse(kv, kv+vw);
257 switch (rotVal & 3) {
263 rot = (rot + rotVal)&3;
270 if (res.ulog2 == 0)
upresU();
271 if (res.vlog2 == 0)
upresV();
273 if (res.ulog2 > 0) res.ulog2--;
274 if (res.vlog2 > 0) res.vlog2--;
278 int resu = res.u(), resv = res.v();
281 primary = (u < resu);
283 if (!primary) u -= resu;
286 primary = (v < resv);
287 if (!primary) v -= resv;
290 primary = (u >= resu);
291 if (primary) u -= resu;
294 primary = (v >= resv);
296 if (primary) v -= resv;
307 case e_top: u += res.u();
break;
308 case e_left: u += res.u(); v += res.v();
break;
310 res.ulog2++; res.vlog2++;
326 for (
int i = uw/2; i > 0; i--) {
327 *dst++ = src[0] + src[1];
355 for (
int i = vw/2; i > 0; i--) {
356 *dst++ = src[0] + src[1];
373 float* src = ku + uw-1;
374 float* dst = ku + uw*2-2;
375 for (
int i = uw; i > 0; i--) {
376 dst[0] = dst[1] = *src-- / 2;
386 float* src = kv + vw-1;
387 float* dst = kv + vw*2-2;
388 for (
int i = vw; i > 0; i--) {
389 dst[0] = dst[1] = *src-- / 2;
399 assert(u == 0 && v == 0);
402 if (res.ulog2 > res.vlog2) {
403 do {
downresU(); }
while(res.ulog2 > res.vlog2);
405 else if (res.vlog2 > res.ulog2) {
406 do {
downresV(); }
while (res.vlog2 > res.ulog2);
414 for (
int i = 0; i <
uw; i++) {
415 float sum = ku[i] + kv[i];
419 newWeight *= newWeight;
422 float scale = newWeight == 0 ? 1.f : initialWeight / newWeight;
445 for (
int i = 0; i <
uw; i++) ku[i] *= -1;
446 newWeight = -newWeight;
450 for (
int i = 0; i <
uw; i++) ku[i] *= scale;
451 newWeight = initialWeight;
461 fn(*
this, dst, data, nChan, nTxChan);
477 for (
const float* e = p + n; p != e; p++) result += *p;
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
void applyConst(float *dst, void *data, DataType dt, int nChan)
static float accumulate(const float *p, int n)
void mergeL(BorderMode mode)
Top edge, from UV (1,1) to (0,1)
void mergeB(BorderMode mode)
PtexSeparableKernel & operator=(const PtexSeparableKernel &k)
bool adjustMainToSubface(int eid)
float makeSymmetric(float initialWeight)
static ApplyFn applyFunctions[40]
texel beyond border are assumed to be black
static ApplyConstFn applyConstFunctions[20]
void applyConst(float weight, float *dst, void *data, Ptex::DataType dt, int nChan)
void mergeR(BorderMode mode)
void set(Res resVal, int uVal, int vVal, int uwVal, int vwVal, const float *kuVal, const float *kvVal, int rotVal=0)
void adjustSubfaceToMain(int eid)
BorderMode
How to handle mesh border when filtering.
void(* ApplyFn)(PtexSeparableKernel &k, float *dst, void *data, int nChan, int nTxChan)
void mergeT(BorderMode mode)
void(* ApplyConstFn)(float weight, float *dst, void *data, int nChan)
Right edge, from UV (1,0) to (1,1)
Bottom edge, from UV (0,0) to (1,0)
void splitL(PtexSeparableKernel &k)
void splitB(PtexSeparableKernel &k)
void splitT(PtexSeparableKernel &k)
Left edge, from UV (0,1) to (0,0)
PtexSeparableKernel(const PtexSeparableKernel &k)
DataType
Type of data stored in texture file.
#define PTEX_NAMESPACE_END
Public API classes for reading, writing, caching, and filtering Ptex files.
void splitR(PtexSeparableKernel &k)