#ifndef PtexMitchellFilter_h
#define PtexMitchellFilter_h
#include <vector>
#include "Ptexture.h"
#include "PtexFilterContext.h"
#include "PtexFilterKernel.h"
class PtexMitchellFilter : public PtexFilter, public Ptex
{
public:
PtexMitchellFilter(PtexTexture* tx, float sharpness)
: _tx(tx)
{
setSharpness(sharpness);
}
virtual void release() { delete this; }
virtual void eval(float* result, int firstchan, int nchannels,
int faceid,
float u,
float v,
float uw1, float vw1, float uw2, float vw2,
float width,
float blur);
protected:
struct Face {
bool valid;
bool blend;
int rotate;
operator bool() { return valid; }
Face() : valid(0), blend(0) {}
void set(int faceid, Res resval, int rotateval=0)
{
blend = 0;
valid = 1;
id = faceid;
res = resval;
rotate = rotateval&3;
if (rotateval&1) res.swapuv();
}
void clampres(Res resval)
{
if (res.ulog2 > resval.ulog2) res.ulog2 = resval.ulog2;
else if (res.ulog2 < resval.ulog2) blend = 1;
if (res.vlog2 > resval.vlog2) res.vlog2 = resval.vlog2;
else if (res.vlog2 < resval.vlog2) blend = 1;
}
void clear() { valid=0; blend=0; }
};
void setSharpness(float sharpness);
void getNeighborhood(
const FaceInfo&
f);
void computeWeights(
double* kernel,
double x1,
double step,
int size)
{
const double*
c = _filter;
for (
int i = 0; i <
size; i++) {
x = fabs(x1 + i*step);
if (x < 1) m = (c[0]*x + c[1])*x*x + c[2];
else if (x < 2) m = ((c[3]*x + c[4])*x + c[5])*x + c[6];
else m = 0;
kernel[i] = m;
}
}
void evalFaces(Res
res,
double weight,
float uw,
float vw);
void evalFaces(Res res, double weight)
{
evalFaces(res, weight, 1.0f/res.u(), 1.0f/res.v());
}
void evalLargeDu(float du, float weight);
void evalLargeDuFace(
int faceid,
int level,
float weight);
PtexTexture* _tx;
PtexFilterContext _ctx;
bool _isConstant;
bool _interior;
double _ublend, _vblend;
Face _face, _uface, _vface;
Face _cface;
std::vector<Face> _cfaces;
float _sharpness;
double _filter[7];
};
#endif