48 int faceid,
float u,
float v,
49 float uw1,
float vw1,
float uw2,
float vw2,
50 float width,
float blur)
53 if (!
_tx || nChannels <= 0)
return;
54 if (faceid < 0 || faceid >=
_tx->
numFaces())
return;
62 if (f.isNeighborhoodConstant()) {
69 float uw = std::abs(uw1) + std::abs(uw2), vw = std::abs(vw1) + std::abs(vw2);
72 bool return_black =
false;
75 case m_clamp: u = std::clamp(u, 0.0f, 1.0f);
break;
77 case m_black:
if (u <= -1.0f || u >= 2.0f) return_black =
true;
break;
81 case m_clamp: v = std::clamp(v, 0.0f, 1.0f);
break;
83 case m_black:
if (v <= -1.0f || v >= 2.0f) return_black =
true;
break;
87 memset(result, 0,
sizeof(
float)*
_nchan);
95 uw = uw * width + blur * 2.0f;
96 vw = vw * width + blur * 2.0f;
98 Ptex::Res((int8_t)(f.res.ulog2+1),(int8_t)(f.res.vlog2+1)));
101 k.
res.ulog2--; k.
res.vlog2--;
104 uw = uw * width + blur;
105 vw = vw * width + blur;
111 assert(k.
uw > 0 && k.
vw > 0);
125 for (
int i = 0; i <
_nchan; i++) result[i] =
float(
_result[i] * scale);
135 bool splitR = (k.
u+k.
uw > k.
res.u()), splitL = (k.
u < 0);
136 bool splitT = (k.
v+k.
vw > k.
res.v()), splitB = (k.
v < 0);
147 if (splitR || splitL || splitT || splitB) {
217 int rot = eid - aeid + 2;
221 if (fIsSubface != afIsSubface) {
228 int neid = (aeid + 3) % 4;
232 rot += neid - aeid + 2;
242 bool primary = (af->
adjface(aeid) == faceid);
250 else apply(k, afid, *af);
258 int afid = faceid, aeid = eid;
259 const FaceInfo* af = &f;
262 const int MaxValence = 10;
263 int cfaceId[MaxValence];
264 int cedgeId[MaxValence];
265 const FaceInfo* cface[MaxValence];
268 for (
int i = 0; i < MaxValence; i++) {
271 afid = af->adjface(aeid);
272 aeid = (af->adjedge(aeid) + 1) % 4;
278 if (afid < 0 || (afid == faceid && aeid == eid)) {
291 if (prevIsSubface && !isSubface && af->adjface((aeid+3)%4) == prevFace)
295 bool primary = (i==1);
297 k.
rotate(eid - aeid + 3 - primary);
301 prevIsSubface = isSubface;
304 if (numCorners == 1) {
308 else if (numCorners > 1) {
312 float initialWeight = k.
weight();
314 for (
int i = 1; i <= numCorners; i++) {
319 _weight += newWeight * (float)numCorners - initialWeight;
333 if (fIsSubface != cfIsSubface) {
341 else apply(k, cfid, cf);
347 assert(k.
u >= 0 && k.
u + k.
uw <= k.
res.u());
348 assert(k.
v >= 0 && k.
v + k.
vw <= k.
res.v());
350 if (k.
uw <= 0 || k.
vw <= 0)
return;
369 if (dh->isConstant()) {
376 float* result = tanvecMode ? (
float*) alloca(
sizeof(
float)*
_nchan) :
_result;
377 if (tanvecMode) memset(result, 0,
sizeof(
float)*
_nchan);
383 int tileresu = tileres.
u();
384 int tileresv = tileres.
v();
385 int ntilesu = k.
res.u() / tileresu;
386 for (
int v = k.
v, vw = k.
vw; vw > 0; vw -= kt.
vw, v += kt.
vw) {
387 int tilev = v / tileresv;
389 kt.
vw = std::min(vw, tileresv - kt.
v);
390 kt.
kv = k.
kv + v - k.
v;
391 for (
int u = k.
u, uw = k.
uw; uw > 0; uw -= kt.
uw, u += kt.
uw) {
392 int tileu = u / tileresu;
394 kt.
uw = std::min(uw, tileresu - kt.
u);
395 kt.
ku = k.
ku + u - k.
u;
398 if (th->isConstant())
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
void splitAndApply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
void apply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
bool isConstant() const
Determine if face is constant (by checking a flag).
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
void applyConst(float *dst, void *data, DataType dt, int nChan)
bool noedgeblend
Disable cross-face filtering. Useful for debugging or rendering on polys.
void mergeL(BorderMode mode)
texel access is clamped to border
Top edge, from UV (1,1) to (0,1)
virtual void * getConstantData(int faceid)=0
Access the constant (or average) data value for a given face.
void mergeB(BorderMode mode)
bool adjustMainToSubface(int eid)
float makeSymmetric(float initialWeight)
int v() const
V resolution in texels.
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)
Apply filter to a ptex data file.
texel beyond border are assumed to be black
Values are vectors in tangent space; rotate values.
int u() const
U resolution in texels.
int8_t vlog2
log base 2 of v resolution, in texels
void mergeR(BorderMode mode)
virtual void getData(int faceid, void *buffer, int stride)=0
Access texture data for a face at highest-resolution.
bool isSubface() const
Determine if face is a subface (by checking a flag).
void adjustSubfaceToMain(int eid)
virtual int numFaces()=0
Number of faces stored in file.
void mergeT(BorderMode mode)
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Right edge, from UV (1,0) to (1,1)
Bottom edge, from UV (0,0) to (1,0)
virtual void buildKernel(PtexSeparableKernel &k, float u, float v, float uw, float vw, Res faceRes)=0
void splitL(PtexSeparableKernel &k)
Smart-pointer for acquiring and releasing API objects.
void applyToCornerFace(PtexSeparableKernel &k, const Ptex::FaceInfo &f, int eid, int cfaceid, const Ptex::FaceInfo &cf, int ceid)
void splitB(PtexSeparableKernel &k)
int8_t ulog2
log base 2 of u resolution, in texels
texel access wraps to other side of face
void splitT(PtexSeparableKernel &k)
Pixel resolution of a given texture.
Left edge, from UV (0,1) to (0,0)
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Res res
Resolution of face.
Information about a face, as stored in the Ptex file header.
void applyAcrossEdge(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
void applyToCorner(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
float OneValue(DataType dt)
Look up value of given data type that corresponds to the normalized value of 1.0. ...
#define PTEX_NAMESPACE_END
void splitR(PtexSeparableKernel &k)
void ConvertToFloat(float *dst, const void *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from the given data type to float.