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;
59 const FaceInfo& f =
_tx->getFaceInfo(faceid);
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;
76 case m_periodic: u = u-std::floor(u);
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;
82 case m_periodic: v = v-std::floor(v);
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);
124 float scale = 1.0f / (
_weight * OneValue(
_dt));
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) {
160 if (f.
adjface(e_bottom) >= 0) {
181 if (f.
adjface(e_bottom) >= 0) {
199 if (f.
adjface(e_bottom) >= 0) {
217 int rot = eid - aeid + 2;
221 if (fIsSubface != afIsSubface) {
228 int neid = (aeid + 3) % 4;
231 af = &
_tx->getFaceInfo(afid);
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)) {
284 af = &
_tx->getFaceInfo(afid);
290 bool isSubface = af->isSubface();
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()) {
375 bool tanvecMode = (
_efm == efm_tanvec) && (
_nchan >= 2) && (k.
rot > 0);
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())
#define PTEX_NAMESPACE_END
Smart-pointer for acquiring and releasing API objects.
void splitAndApply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
void applyToCornerFace(PtexSeparableKernel &k, const Ptex::FaceInfo &f, int eid, int cfaceid, const Ptex::FaceInfo &cf, int ceid)
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.
void apply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
void applyAcrossEdge(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
void applyToCorner(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
virtual void buildKernel(PtexSeparableKernel &k, float u, float v, float uw, float vw, Res faceRes)=0
void mergeT(BorderMode mode)
void mergeB(BorderMode mode)
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
float makeSymmetric(float initialWeight)
void splitT(PtexSeparableKernel &k)
void adjustSubfaceToMain(int eid)
void splitB(PtexSeparableKernel &k)
void splitL(PtexSeparableKernel &k)
void mergeR(BorderMode mode)
void applyConst(float *dst, void *data, DataType dt, int nChan)
bool adjustMainToSubface(int eid)
void mergeL(BorderMode mode)
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.
Information about a face, as stored in the Ptex file header.
bool isSubface() const
Determine if face is a subface (by checking a flag).
Res res
Resolution of face.
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
bool isConstant() const
Determine if face is constant (by checking a flag).
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
Pixel resolution of a given texture.
int8_t ulog2
log base 2 of u resolution, in texels
int v() const
V resolution in texels.
int u() const
U resolution in texels.
int8_t vlog2
log base 2 of v resolution, in texels