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);
    }
}
Beispiel #2
0
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);
    }
}
Beispiel #3
0
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];
    }
}