void PtexSeparableFilter::apply(PtexSeparableKernel& k, int faceid, const Ptex::FaceInfo& f) { assert(k.u >= 0 && k.u + k.uw <= k.res.u()); assert(k.v >= 0 && k.v + k.vw <= k.res.v()); if (k.uw <= 0 || k.vw <= 0) return; // downres kernel if needed while (k.res.u() > f.res.u()) k.downresU(); while (k.res.v() > f.res.v()) k.downresV(); // get face data, and apply PtexPtr<PtexFaceData> dh ( _tx->getData(faceid, k.res) ); if (!dh) return; if (dh->isConstant()) { k.applyConst(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan); } else if (dh->isTiled()) { Ptex::Res tileres = dh->tileRes(); PtexSeparableKernel kt; kt.res = tileres; int tileresu = tileres.u(); int tileresv = tileres.v(); int ntilesu = k.res.u() / tileresu; for (int v = k.v, vw = k.vw; vw > 0; vw -= kt.vw, v += kt.vw) { int tilev = v / tileresv; kt.v = v % tileresv; kt.vw = PtexUtils::min(vw, tileresv - kt.v); kt.kv = k.kv + v - k.v; for (int u = k.u, uw = k.uw; uw > 0; uw -= kt.uw, u += kt.uw) { int tileu = u / tileresu; kt.u = u % tileresu; kt.uw = PtexUtils::min(uw, tileresu - kt.u); kt.ku = k.ku + u - k.u; PtexPtr<PtexFaceData> th ( dh->getTile(tilev * ntilesu + tileu) ); if (th) { if (th->isConstant()) kt.applyConst(_result, (char*)th->getData()+_firstChanOffset, _dt, _nchan); else kt.apply(_result, (char*)th->getData()+_firstChanOffset, _dt, _nchan, _ntxchan); } } } } else { k.apply(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan, _ntxchan); } }
void PtexReader::getData(int faceid, void* buffer, int stride, Res res) { if (!_ok) return; // note - all locking is handled in called getData methods int resu = res.u(), resv = res.v(); int rowlen = _pixelsize * resu; if (stride == 0) stride = rowlen; PtexPtr<PtexFaceData> d ( getData(faceid, res) ); if (!d) return; if (d->isConstant()) { // fill dest buffer with pixel value PtexUtils::fill(d->getData(), buffer, stride, resu, resv, _pixelsize); } else if (d->isTiled()) { // loop over tiles Res tileres = d->tileRes(); int ntilesu = res.ntilesu(tileres); int ntilesv = res.ntilesv(tileres); int tileures = tileres.u(); int tilevres = tileres.v(); int tilerowlen = _pixelsize * tileures; int tile = 0; char* dsttilerow = (char*) buffer; for (int i = 0; i < ntilesv; i++) { char* dsttile = dsttilerow; for (int j = 0; j < ntilesu; j++) { PtexPtr<PtexFaceData> t ( d->getTile(tile++) ); if (!t) { i = ntilesv; break; } if (t->isConstant()) PtexUtils::fill(t->getData(), dsttile, stride, tileures, tilevres, _pixelsize); else PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride, tilevres, tilerowlen); dsttile += tilerowlen; } dsttilerow += stride * tilevres; } } else { PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen); } }
void PtexSeparableFilter::apply(PtexSeparableKernel& k, int faceid, const Ptex::FaceInfo& f) { assert(k.u >= 0 && k.u + k.uw <= k.res.u()); assert(k.v >= 0 && k.v + k.vw <= k.res.v()); if (k.uw <= 0 || k.vw <= 0) return; // downres kernel if needed while (k.res.u() > f.res.u()) k.downresU(); while (k.res.v() > f.res.v()) k.downresV(); // get face data, and apply PtexPtr<PtexFaceData> dh ( _tx->getData(faceid, k.res) ); if (!dh) return; if (dh->isConstant()) { k.applyConst(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan); return; } // allocate temporary result for tanvec mode (if needed) bool tanvecMode = (_efm == efm_tanvec) && (_nchan >= 2) && (k.rot > 0); float* result = tanvecMode ? (float*) alloca(sizeof(float)*_nchan) : _result; if (tanvecMode) memset(result, 0, sizeof(float)*_nchan); if (dh->isTiled()) { Ptex::Res tileres = dh->tileRes(); PtexSeparableKernel kt; kt.res = tileres; int tileresu = tileres.u(); int tileresv = tileres.v(); int ntilesu = k.res.u() / tileresu; for (int v = k.v, vw = k.vw; vw > 0; vw -= kt.vw, v += kt.vw) { int tilev = v / tileresv; kt.v = v % tileresv; kt.vw = PtexUtils::min(vw, tileresv - kt.v); kt.kv = k.kv + v - k.v; for (int u = k.u, uw = k.uw; uw > 0; uw -= kt.uw, u += kt.uw) { int tileu = u / tileresu; kt.u = u % tileresu; kt.uw = PtexUtils::min(uw, tileresu - kt.u); kt.ku = k.ku + u - k.u; PtexPtr<PtexFaceData> th ( dh->getTile(tilev * ntilesu + tileu) ); if (th) { if (th->isConstant()) kt.applyConst(result, (char*)th->getData()+_firstChanOffset, _dt, _nchan); else kt.apply(result, (char*)th->getData()+_firstChanOffset, _dt, _nchan, _ntxchan); } } } } else { k.apply(result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan, _ntxchan); } if (tanvecMode) { // rotate tangent-space vector data and update main result switch (k.rot) { case 0: // rot==0 included for completeness, but tanvecMode should be false in this case _result[0] += result[0]; _result[1] += result[1]; break; case 1: _result[0] -= result[1]; _result[1] += result[0]; break; case 2: _result[0] -= result[0]; _result[1] -= result[1]; break; case 3: _result[0] += result[1]; _result[1] -= result[0]; break; } for (int i = 2; i < _nchan; i++) _result[i] += result[i]; } }