Пример #1
0
int main(int /*argc*/, char** /*argv*/)
{
    Ptex::String error;
    PtexPtr<PtexCache> c(PtexCache::create());
    c->setSearchPath("foo/bar:.");
    PtexPtr<PtexTexture> r(c->get("test.ptx", error));

    if (!r) {
	std::cerr << error.c_str() << std::endl;
	return 1;
    }
    std::cout << "meshType: " << Ptex::MeshTypeName(r->meshType()) << std::endl;
    std::cout << "dataType: " << Ptex::DataTypeName(r->dataType()) << std::endl;
    std::cout << "numChannels: " << r->numChannels() << std::endl;
    std::cout << "alphaChannel: ";
    if (r->alphaChannel() == -1) std::cout << "(none)" << std::endl;
    else std::cout << r->alphaChannel() << std::endl;
    std::cout << "numFaces: " << r->numFaces() << std::endl;

    PtexMetaData* meta = r->getMetaData();
    std::cout << "numMetaKeys: " << meta->numKeys() << std::endl;
    if (meta->numKeys()) DumpMetaData(meta);
    meta->release();

    int nfaces = r->numFaces();
    for (int i = 0; i < nfaces; i++) {
	const Ptex::FaceInfo& f = r->getFaceInfo(i);
	std::cout << "face " << i << ":\n"
		  << "  res: " << int(f.res.ulog2) << ' ' << int(f.res.vlog2) << "\n"
		  << "  adjface: " 
		  << f.adjfaces[0] << ' '
		  << f.adjfaces[1] << ' '
		  << f.adjfaces[2] << ' '
		  << f.adjfaces[3] << "\n"
		  << "  adjedge: " 
		  << f.adjedge(0) << ' '
		  << f.adjedge(1) << ' '
		  << f.adjedge(2) << ' '
		  << f.adjedge(3) << "\n"
		  << "  flags: " << int(f.flags) << "\n";

	Ptex::Res res = f.res;
	while (res.ulog2 > 0 || res.vlog2 > 0) {
	    PtexFaceData* dh = r->getData(i, res);
	    if (!dh) break;
	    DumpData(r->dataType(), r->numChannels(), dh, "  ");
	    bool isconst = dh->isConstant();
	    dh->release();
	    if (isconst) break;
	    if (res.ulog2) res.ulog2--;
	    if (res.vlog2) res.vlog2--;
	}
	PtexFaceData* dh = r->getData(i, Ptex::Res(0,0));
	DumpData(r->dataType(), r->numChannels(), dh, "  ");
	dh->release();
    }

    return 0;
}
Пример #2
0
void DumpData(Ptex::DataType dt, int nchan, PtexFaceData* dh, std::string prefix)
{
    void* dpixel = malloc(Ptex::DataSize(dt)*nchan);
    float* pixel = (float*) malloc(sizeof(float)*nchan);
    uint8_t* cpixel = (uint8_t*) malloc(sizeof(uint8_t)*nchan);
    Ptex::Res res = dh->res();
    printf("%sdata (%d x %d)", prefix.c_str(), res.u(), res.v());
    if (dh->isTiled()) {
	Ptex::Res tileres = dh->tileRes();
	printf(", tiled (%d x %d):\n", tileres.u(), tileres.v());
	int n = res.ntiles(tileres);
	for (int i = 0; i < n; i++) {
	    PtexFaceData* t = dh->getTile(i);
	    std::cout << prefix << "  tile " << i;
	    if (!t) {
		std::cout << " NULL!" << std::endl;
	    } else {
		DumpData(dt, nchan, t, prefix + "  ");
		t->release();
	    }
	}
    } else {
	int ures, vres;
	if (dh->isConstant()) { ures = vres = 1; std::cout << ", const: "; }
	else { ures = res.u(); vres = res.v(); std::cout << ":\n"; }
	
	int vimax = vres;// if (vimax > 16) vimax = 16;
	for (int vi = 0; vi < vimax; vi++) {
	    if (vi == 8 && vres > 16) { vi = vres-8; std::cout << prefix << "  ..." << std::endl; }
	    std::cout << prefix << "  ";
	    int uimax = ures;// if (uimax > 16) uimax = 16;
	    for (int ui = 0; ui < uimax; ui++) {
		if (ui == 8 && ures > 16) { ui = ures-8; std::cout << "... "; }
		dh->getPixel(ui, vi, dpixel);
		Ptex::ConvertToFloat(pixel, dpixel, dt, nchan);
		Ptex::ConvertFromFloat(cpixel, pixel, Ptex::dt_uint8, nchan);
		for (int c=0; c < nchan; c++) {
		    printf("%02x", cpixel[c]);
		}
		printf(" ");
	    }
	    if (uimax != ures) printf(" ...");
	    printf("\n");
	}
	if (vimax != vres) std::cout << prefix << "  ..." << std::endl;
    }
    free(cpixel);
    free(pixel);
    free(dpixel);
}
Пример #3
0
PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
{
    _cache->cachelock.lock();
    FaceData*& face = _tiles[tile];
    if (face) {
        face->ref();
        _cache->cachelock.unlock();
        return face;
    }

    // first, get all parent tiles for this tile
    // and check if they are constant (with the same value)
    int pntilesu = _parentface->ntilesu();
    int pntilesv = _parentface->ntilesv();
    int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
    int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir

    int ntiles = nu*nv; // num parent tiles for this tile
    PtexFaceData** tiles = (PtexFaceData**) alloca(ntiles * sizeof(PtexFaceData*));
    bool allConstant = true;
    int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
    for (int i = 0; i < ntiles;) {
        // temporarily release cache lock while we get parent tile
        _cache->cachelock.unlock();
        PtexFaceData* tile = tiles[i] = _parentface->getTile(ptile);
        _cache->cachelock.lock();
        allConstant = (allConstant && tile->isConstant() &&
                       (i==0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
                                             _pixelsize))));
        i++;
        ptile += i%nu? 1 : pntilesu - nu + 1;
    }

    // make sure another thread didn't make the tile while we were checking
    if (face) {
        face->ref();
        _cache->cachelock.unlock();
        // release the tiles
        for (int i = 0; i < ntiles; i++) tiles[i]->release();
        return face;
    }

    if (allConstant) {
        // allocate a new constant face
        face = new ConstantFace((void**)&face, _cache, _pixelsize);
        memcpy(face->getData(), tiles[0]->getData(), _pixelsize);
    }
    else {
        // allocate a new packed face for the tile
        face = new PackedFace((void**)&face, _cache, _tileres,
                              _pixelsize, _pixelsize*_tileres.size());

        // generate reduction from parent tiles
        int ptileures = _parentface->tileres().u();
        int ptilevres = _parentface->tileres().v();
        int sstride = ptileures * _pixelsize;
        int dstride = _tileres.u() * _pixelsize;
        int dstepu = dstride/nu;
        int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);

        char* dst = (char*) face->getData();
        for (int i = 0; i < ntiles;) {
            PtexFaceData* tile = tiles[i];
            if (tile->isConstant())
                PtexUtils::fill(tile->getData(), dst, dstride,
                                _tileres.u()/nu, _tileres.v()/nv,
                                _pixelsize);
            else
                _reducefn(tile->getData(), sstride, ptileures, ptilevres,
                          dst, dstride, _dt, _nchan);
            i++;
            dst += i%nu ? dstepu : dstepv;
        }
    }

    _cache->cachelock.unlock();

    // release the tiles
    for (int i = 0; i < ntiles; i++) tiles[i]->release();
    return face;
}
Пример #4
0
void PtexReader::TiledFaceBase::reduce(FaceData*& face, PtexReader* r,
                                       Res newres, PtexUtils::ReduceFn reducefn)
{
    // get reduce lock and make sure we still need to reduce
    AutoMutex rlocker(r->reducelock);
    if (face) {
        // another thread must have generated it while we were waiting
        AutoLockCache clocker(_cache->cachelock);
        // make sure it's still there now that we have the lock
        if (face) {
            face->ref();
            return;
        }
    }

    /* Tiled reductions should generally only be anisotropic (just u
       or v, not both) since isotropic reductions are precomputed and
       stored on disk.  (This function should still work for isotropic
       reductions though.)

       In the anisotropic case, the number of tiles should be kept the
       same along the direction not being reduced in order to preserve
       the laziness of the file access.  In contrast, if reductions
       were not tiled, then any reduction would read all the tiles and
       defeat the purpose of tiling.
    */

    // keep new face local until fully initialized
    FaceData* volatile newface = 0;

    // don't tile if either dimension is 1 (rare, would complicate blendFaces too much)
    // also, don't tile triangle reductions (too complicated)
    Res newtileres;
    bool isTriangle = r->_header.meshtype == mt_triangle;
    if (newres.ulog2 == 1 || newres.vlog2 == 1 || isTriangle) {
        newtileres = newres;
    }
    else {
        // propagate the tile res to the reduction
        newtileres = _tileres;
        // but make sure tile isn't larger than the new face!
        if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
        if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
    }


    // determine how many tiles we will have on the reduction
    int newntiles = newres.ntiles(newtileres);

    if (newntiles == 1) {
        // no need to keep tiling, reduce tiles into a single face
        // first, get all tiles and check if they are constant (with the same value)
        PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
        bool allConstant = true;
        for (int i = 0; i < _ntiles; i++) {
            PtexFaceData* tile = tiles[i] = getTile(i);
            allConstant = (allConstant && tile->isConstant() &&
                           (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
                                                   _pixelsize))));
        }
        if (allConstant) {
            // allocate a new constant face
            newface = new ConstantFace((void**)&face, _cache, _pixelsize);
            memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
        }
        else if (isTriangle) {
            // reassemble all tiles into temporary contiguous image
            // (triangle reduction doesn't work on tiles)
            int tileures = _tileres.u();
            int tilevres = _tileres.v();
            int sstride = _pixelsize * tileures;
            int dstride = sstride * _ntilesu;
            int dstepv = dstride * tilevres - sstride*(_ntilesu-1);

            char* tmp = (char*) malloc(_ntiles * _tileres.size() * _pixelsize);
            char* tmpptr = tmp;
            for (int i = 0; i < _ntiles;) {
                PtexFaceData* tile = tiles[i];
                if (tile->isConstant())
                    PtexUtils::fill(tile->getData(), tmpptr, dstride,
                                    tileures, tilevres, _pixelsize);
                else
                    PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
                i++;
                tmpptr += i%_ntilesu ? sstride : dstepv;
            }

            // allocate a new packed face
            newface = new PackedFace((void**)&face, _cache, newres,
                                     _pixelsize, _pixelsize * newres.size());
            // reduce and copy into new face
            reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
                     newface->getData(), _pixelsize * newres.u(), _dt, _nchan);

            free(tmp);
        }
        else {
            // allocate a new packed face
            newface = new PackedFace((void**)&face, _cache, newres,
                                     _pixelsize, _pixelsize*newres.size());

            int tileures = _tileres.u();
            int tilevres = _tileres.v();
            int sstride = _pixelsize * tileures;
            int dstride = _pixelsize * newres.u();
            int dstepu = dstride/_ntilesu;
            int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);

            char* dst = (char*) newface->getData();
            for (int i = 0; i < _ntiles;) {
                PtexFaceData* tile = tiles[i];
                if (tile->isConstant())
                    PtexUtils::fill(tile->getData(), dst, dstride,
                                    newres.u()/_ntilesu, newres.v()/_ntilesv,
                                    _pixelsize);
                else
                    reducefn(tile->getData(), sstride, tileures, tilevres,
                             dst, dstride, _dt, _nchan);
                i++;
                dst += i%_ntilesu ? dstepu : dstepv;
            }
        }
        // release the tiles
        for (int i = 0; i < _ntiles; i++) tiles[i]->release();
    }
    else {
        // otherwise, tile the reduced face
        newface = new TiledReducedFace((void**)&face, _cache, newres, newtileres,
                                       _dt, _nchan, this, reducefn);
    }
    AutoLockCache clocker(_cache->cachelock);
    face = newface;

    // clean up unused data
    _cache->purgeData();
}