PtexReader.cpp
Go to the documentation of this file.
/*
PTEX SOFTWARE
Copyright 2014 Disney Enterprises, Inc. All rights reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
Studios" or the names of its contributors may NOT be used to
endorse or promote products derived from this software without
specific prior written permission from Walt Disney Pictures.
Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include "PtexPlatform.h"
#include <iostream>
#include <sstream>
#include <stdio.h>
#include "Ptexture.h"
#include "PtexUtils.h"
#include "PtexReader.h"
namespace {
class TempErrorHandler : public PtexErrorHandler
{
std::string _error;
public:
virtual void reportError(const char* error) {
_error += error;
}
const std::string& getErrorString() const { return _error; }
};
}
PTEX_NAMESPACE_BEGIN
PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
{
PtexReader* reader = new PtexReader(premultiply, (PtexInputHandler*) 0, (PtexErrorHandler*) 0);
bool ok = reader->open(path, error);
if (!ok) {
reader->release();
return 0;
}
return reader;
}
PtexReader::PtexReader(bool premultiply, PtexInputHandler* io, PtexErrorHandler* err)
: _io(io ? io : &_defaultIo),
_err(err),
_premultiply(premultiply),
_ok(true),
_needToOpen(true),
_pendingPurge(false),
_fp(0),
_pos(0),
_pixelsize(0),
_constdata(0),
_metadata(0),
_hasEdits(false),
_baseMemUsed(sizeof(*this)),
_memUsed(_baseMemUsed),
_opens(0),
_blockReads(0)
{
memset(&_zstream, 0, sizeof(_zstream));
}
PtexReader::~PtexReader()
{
closeFP();
if (_constdata) delete [] _constdata;
if (_metadata) delete _metadata;
for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
if (*i) delete *i;
}
}
void PtexReader::prune()
{
if (_metadata) { delete _metadata; _metadata = 0; }
for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
if (*i) { delete *i; *i = 0; }
}
_reductions.clear();
_memUsed = _baseMemUsed;
}
void PtexReader::purge()
{
// free all dynamic data
prune();
if (_constdata) {delete [] _constdata; _constdata = 0; }
std::vector<FaceInfo>().swap(_faceinfo);
std::vector<uint32_t>().swap(_rfaceids);
std::vector<LevelInfo>().swap(_levelinfo);
std::vector<FilePos>().swap(_levelpos);
std::vector<Level*>().swap(_levels);
std::vector<MetaEdit>().swap(_metaedits);
std::vector<FaceEdit>().swap(_faceedits);
closeFP();
// reset initial state
_ok = true;
_needToOpen = true;
_pendingPurge = false;
_memUsed = _baseMemUsed = sizeof(*this);
}
bool PtexReader::open(const char* pathArg, Ptex::String& error)
{
AutoMutex locker(readlock);
if (!needToOpen()) return false;
if (!LittleEndian()) {
error = "Ptex library doesn't currently support big-endian cpu's";
return 0;
}
_path = pathArg;
_fp = _io->open(pathArg);
if (!_fp) {
std::string errstr = "Can't open ptex file: ";
errstr += pathArg; errstr += "\n"; errstr += _io->lastError();
error = errstr.c_str();
_ok = 0;
return 0;
}
memset(&_header, 0, sizeof(_header));
readBlock(&_header, HeaderSize);
if (_header.magic != Magic) {
std::string errstr = "Not a ptex file: "; errstr += pathArg;
error = errstr.c_str();
_ok = 0;
closeFP();
return 0;
}
if (_header.version != 1) {
std::stringstream s;
s << "Unsupported ptex file version ("<< _header.version << "): " << pathArg;
error = s.str();
_ok = 0;
closeFP();
return 0;
}
_pixelsize = _header.pixelSize();
_errorPixel.resize(_pixelsize);
// install temp error handler to capture error (to return in error param)
TempErrorHandler tempErr;
PtexErrorHandler* prevErr = _err;
_err = &tempErr;
// read extended header
memset(&_extheader, 0, sizeof(_extheader));
readBlock(&_extheader, PtexUtils::min(uint32_t(ExtHeaderSize), _header.extheadersize));
// compute offsets of various blocks
FilePos pos = HeaderSize + _header.extheadersize;
_faceinfopos = pos; pos += _header.faceinfosize;
_constdatapos = pos; pos += _header.constdatasize;
_levelinfopos = pos; pos += _header.levelinfosize;
_leveldatapos = pos; pos += _header.leveldatasize;
_metadatapos = pos; pos += _header.metadatazipsize;
pos += sizeof(uint64_t); // compatibility barrier
_lmdheaderpos = pos; pos += _extheader.lmdheaderzipsize;
_lmddatapos = pos; pos += _extheader.lmddatasize;
// edit data may not start immediately if additional sections have been added
// use value from extheader if present (and > pos)
_editdatapos = PtexUtils::max(FilePos(_extheader.editdatapos), pos);
// read basic file info
readFaceInfo();
readConstData();
readLevelInfo();
readEditData();
_baseMemUsed = _memUsed;
// restore error handler
_err = prevErr;
// an error occurred while reading the file
if (!_ok) {
error = tempErr.getErrorString();
closeFP();
return 0;
}
AtomicStore(&_needToOpen, false);
return true;
}
bool PtexReader::tryClose()
{
if (_fp) {
if (!readlock.trylock()) return false;
closeFP();
readlock.unlock();
}
return true;
}
void PtexReader::closeFP()
{
if (_fp) {
_io->close(_fp);
_fp = 0;
}
inflateEnd(&_zstream);
}
bool PtexReader::reopenFP()
{
if (_fp) return true;
// we assume this is called lazily in a scope where readlock is already held
_fp = _io->open(_path.c_str());
if (!_fp) {
setError("Can't reopen");
return false;
}
_pos = 0;
Header headerval;
ExtHeader extheaderval;
readBlock(&headerval, HeaderSize);
memset(&extheaderval, 0, sizeof(extheaderval));
readBlock(&extheaderval, PtexUtils::min(uint32_t(ExtHeaderSize), headerval.extheadersize));
if (0 != memcmp(&headerval, &_header, sizeof(headerval)) ||
0 != memcmp(&extheaderval, &_extheader, sizeof(extheaderval)))
{
setError("Header mismatch on reopen of");
return false;
}
logOpen();
return true;
}
const Ptex::FaceInfo& PtexReader::getFaceInfo(int faceid)
{
if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
return _faceinfo[faceid];
static Ptex::FaceInfo dummy;
return dummy;
}
void PtexReader::readFaceInfo()
{
if (_faceinfo.empty()) {
// read compressed face info block
seek(_faceinfopos);
int nfaces = _header.nfaces;
_faceinfo.resize(nfaces);
readZipBlock(&_faceinfo[0], _header.faceinfosize,
(int)(sizeof(FaceInfo)*nfaces));
// generate rfaceids
_rfaceids.resize(nfaces);
std::vector<uint32_t> faceids_r(nfaces);
PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
&_rfaceids[0], &faceids_r[0]);
increaseMemUsed(nfaces * (sizeof(_faceinfo[0]) + sizeof(_rfaceids[0])));
}
}
void PtexReader::readLevelInfo()
{
if (_levelinfo.empty()) {
// read level info block
seek(_levelinfopos);
_levelinfo.resize(_header.nlevels);
readBlock(&_levelinfo[0], LevelInfoSize*_header.nlevels);
// initialize related data
_levels.resize(_header.nlevels);
_levelpos.resize(_header.nlevels);
FilePos pos = _leveldatapos;
for (int i = 0; i < _header.nlevels; i++) {
_levelpos[i] = pos;
pos += _levelinfo[i].leveldatasize;
}
increaseMemUsed(_header.nlevels * sizeof(_levelinfo[0]) + sizeof(_levels[0]) + sizeof(_levelpos[0]));
}
}
void PtexReader::readConstData()
{
if (!_constdata) {
// read compressed constant data block
seek(_constdatapos);
int size = _pixelsize * _header.nfaces;
_constdata = new uint8_t[size];
readZipBlock(_constdata, _header.constdatasize, size);
if (_premultiply && _header.hasAlpha())
PtexUtils::multalpha(_constdata, _header.nfaces, datatype(),
_header.nchannels, _header.alphachan);
increaseMemUsed(size);
}
}
PtexMetaData* PtexReader::getMetaData()
{
if (!_metadata) readMetaData();
return _metadata;
}
PtexReader::MetaData::Entry*
PtexReader::MetaData::getEntry(int index)
{
if (index < 0 || index >= int(_entries.size())) {
return 0;
}
Entry* e = _entries[index];
if (!e->isLmd) {
// normal (small) meta data - just return directly
return e;
}
// large meta data - may not be read in yet
if (e->lmdData) {
// already in memory
return e;
}
else {
// not present, must read from file
// get read lock and make sure we still need to read
AutoMutex locker(_reader->readlock);
if (e->lmdData) {
return e;
}
// go ahead and read, keep local until finished
LargeMetaData* lmdData = new LargeMetaData(e->datasize);
e->data = (char*) lmdData->data();
_reader->increaseMemUsed(sizeof(LargeMetaData) + e->datasize);
_reader->seek(e->lmdPos);
_reader->readZipBlock(e->data, e->lmdZipSize, e->datasize);
// update entry
e->lmdData = lmdData;
return e;
}
}
void PtexReader::readMetaData()
{
// get read lock and make sure we still need to read
AutoMutex locker(readlock);
if (_metadata) {
return;
}
// allocate new meta data (keep local until fully initialized)
MetaData* newmeta = new MetaData(this);
size_t metaDataMemUsed = sizeof(MetaData);
// read primary meta data blocks
if (_header.metadatamemsize)
readMetaDataBlock(newmeta, _metadatapos,
_header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
// read large meta data headers
if (_extheader.lmdheadermemsize)
readLargeMetaDataHeaders(newmeta, _lmdheaderpos,
_extheader.lmdheaderzipsize, _extheader.lmdheadermemsize, metaDataMemUsed);
// read meta data edits
for (size_t i = 0, size = _metaedits.size(); i < size; i++)
readMetaDataBlock(newmeta, _metaedits[i].pos,
_metaedits[i].zipsize, _metaedits[i].memsize, metaDataMemUsed);
// store meta data
AtomicStore(&_metadata, newmeta);
increaseMemUsed(newmeta->selfDataSize() + metaDataMemUsed);
}
void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
{
seek(pos);
// read from file
bool useNew = memsize > AllocaMax;
char* buff = useNew ? new char[memsize] : (char*)alloca(memsize);
if (readZipBlock(buff, zipsize, memsize)) {
// unpack data entries
char* ptr = buff;
char* end = ptr + memsize;
while (ptr < end) {
uint8_t keysize = *ptr++;
char* key = (char*)ptr; ptr += keysize;
key[keysize-1] = '\0';
uint8_t datatypeval = *ptr++;
uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
ptr += sizeof(datasize);
char* data = ptr; ptr += datasize;
metadata->addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
}
}
if (useNew) delete [] buff;
}
void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
{
seek(pos);
// read from file
bool useNew = memsize > AllocaMax;
char* buff = useNew ? new char [memsize] : (char*)alloca(memsize);
if (readZipBlock(buff, zipsize, memsize)) {
pos += zipsize;
// unpack data entries
char* ptr = buff;
char* end = ptr + memsize;
while (ptr < end) {
uint8_t keysize = *ptr++;
char* key = (char*)ptr; ptr += keysize;
uint8_t datatypeval = *ptr++;
uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
ptr += sizeof(datasize);
uint32_t zipsizeval; memcpy(&zipsizeval, ptr, sizeof(zipsizeval));
ptr += sizeof(zipsizeval);
metadata->addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
pos += zipsizeval;
}
}
if (useNew) delete [] buff;
}
void PtexReader::readEditData()
{
// determine file range to scan for edits
FilePos pos = FilePos(_editdatapos), endpos;
if (_extheader.editdatapos > 0) {
// newer files record the edit data position and size in the extheader
// note: position will be non-zero even if size is zero
endpos = FilePos(pos + _extheader.editdatasize);
}
else {
// must have an older file, just read until EOF
endpos = FilePos((uint64_t)-1);
}
while (pos < endpos) {
seek(pos);
// read the edit data header
uint8_t edittype = et_editmetadata;
uint32_t editsize;
if (!readBlock(&edittype, sizeof(edittype), /*reporterror*/ false)) break;
if (!readBlock(&editsize, sizeof(editsize), /*reporterror*/ false)) break;
if (!editsize) break;
_hasEdits = true;
pos = tell() + editsize;
switch (edittype) {
case et_editfacedata: readEditFaceData(); break;
case et_editmetadata: readEditMetaData(); break;
}
}
increaseMemUsed(sizeof(_faceedits[0]) * _faceedits.capacity() +
sizeof(_metaedits[0]) * _metaedits.capacity());
}
void PtexReader::readEditFaceData()
{
// read header
EditFaceDataHeader efdh;
if (!readBlock(&efdh, EditFaceDataHeaderSize)) return;
// update face info
int faceid = efdh.faceid;
if (faceid < 0 || size_t(faceid) >= _header.nfaces) return;
FaceInfo& f = _faceinfo[faceid];
f = efdh.faceinfo;
f.flags |= FaceInfo::flag_hasedits;
// read const value now
uint8_t* constdata = _constdata + _pixelsize * faceid;
if (!readBlock(constdata, _pixelsize)) return;
if (_premultiply && _header.hasAlpha())
PtexUtils::multalpha(constdata, 1, datatype(),
_header.nchannels, _header.alphachan);
// update header info for remaining data
if (!f.isConstant()) {
_faceedits.push_back(FaceEdit());
FaceEdit& e = _faceedits.back();
e.pos = tell();
e.faceid = faceid;
e.fdh = efdh.fdh;
}
}
void PtexReader::readEditMetaData()
{
// read header
EditMetaDataHeader emdh;
if (!readBlock(&emdh, EditMetaDataHeaderSize)) return;
// record header info for later
_metaedits.push_back(MetaEdit());
MetaEdit& e = _metaedits.back();
e.pos = tell();
e.zipsize = emdh.metadatazipsize;
e.memsize = emdh.metadatamemsize;
}
bool PtexReader::readBlock(void* data, int size, bool reporterror)
{
assert(_fp && size >= 0);
if (!_fp || size < 0) return false;
int result = (int)_io->read(data, size, _fp);
if (result == size) {
_pos += size;
return true;
}
if (reporterror)
setError("PtexReader error: read failed (EOF)");
return false;
}
bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
{
if (zipsize < 0 || unzipsize < 0) return false;
if (!_zstream.state) {
inflateInit(&_zstream);
}
void* buff = alloca(BlockSize);
_zstream.next_out = (Bytef*) data;
_zstream.avail_out = unzipsize;
while (1) {
int size = (zipsize < BlockSize) ? zipsize : BlockSize;
zipsize -= size;
if (!readBlock(buff, size)) break;
_zstream.next_in = (Bytef*) buff;
_zstream.avail_in = size;
int zresult = inflate(&_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
if (zresult == Z_STREAM_END) break;
if (zresult != Z_OK) {
setError("PtexReader error: unzip failed, file corrupt");
inflateReset(&_zstream);
return 0;
}
}
int total = (int)_zstream.total_out;
inflateReset(&_zstream);
return total == unzipsize;
}
void PtexReader::readLevel(int levelid, Level*& level)
{
// get read lock and make sure we still need to read
AutoMutex locker(readlock);
if (level) {
return;
}
// go ahead and read the level
LevelInfo& l = _levelinfo[levelid];
// keep new level local until finished
Level* newlevel = new Level(l.nfaces);
seek(_levelpos[levelid]);
readZipBlock(&newlevel->fdh[0], l.levelheadersize, FaceDataHeaderSize * l.nfaces);
computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
// apply edits (if any) to level 0
if (levelid == 0) {
for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
FaceEdit& e = _faceedits[i];
newlevel->fdh[e.faceid] = e.fdh;
newlevel->offsets[e.faceid] = e.pos;
}
}
// don't assign to result until level data is fully initialized
AtomicStore(&level, newlevel);
increaseMemUsed(level->memUsed());
}
void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
{
FaceData*& face = level->faces[faceid];
FaceDataHeader fdh = level->fdh[faceid];
readFaceData(level->offsets[faceid], fdh, res, levelid, face);
}
void PtexReader::TiledFace::readTile(int tile, FaceData*& data)
{
_reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
}
void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
FaceData*& face)
{
AutoMutex locker(readlock);
if (face) {
return;
}
// keep new face local until fully initialized
FaceData* newface = 0;
size_t newMemUsed = 0;
seek(pos);
switch (fdh.encoding()) {
case enc_constant:
{
ConstantFace* cf = new ConstantFace(_pixelsize);
newface = cf;
newMemUsed = sizeof(ConstantFace) + _pixelsize;
readBlock(cf->data(), _pixelsize);
if (levelid==0 && _premultiply && _header.hasAlpha())
PtexUtils::multalpha(cf->data(), 1, datatype(),
_header.nchannels, _header.alphachan);
}
break;
case enc_tiled:
{
Res tileres;
readBlock(&tileres, sizeof(tileres));
uint32_t tileheadersize;
readBlock(&tileheadersize, sizeof(tileheadersize));
TiledFace* tf = new TiledFace(this, res, tileres, levelid);
newface = tf;
newMemUsed = tf->memUsed();
readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
}
break;
case enc_zipped:
case enc_diffzipped:
{
int uw = res.u(), vw = res.v();
int npixels = uw * vw;
int unpackedSize = _pixelsize * npixels;
PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
newface = pf;
newMemUsed = sizeof(PackedFace) + unpackedSize;
bool useNew = unpackedSize > AllocaMax;
char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
readZipBlock(tmp, fdh.blocksize(), unpackedSize);
if (fdh.encoding() == enc_diffzipped)
PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
pf->data(), uw * _pixelsize,
datatype(), _header.nchannels);
if (levelid==0 && _premultiply && _header.hasAlpha())
PtexUtils::multalpha(pf->data(), npixels, datatype(),
_header.nchannels, _header.alphachan);
if (useNew) delete [] tmp;
}
break;
}
if (!newface) newface = errorData();
AtomicStore(&face, newface);
increaseMemUsed(newMemUsed);
}
void PtexReader::getData(int faceid, void* buffer, int stride)
{
const FaceInfo& f = getFaceInfo(faceid);
getData(faceid, buffer, stride, f.res);
}
void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
{
if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
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->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->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);
}
}
PtexFaceData* PtexReader::getData(int faceid)
{
if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
return errorData(/*deleteOnRelease*/ true);
}
FaceInfo& fi = _faceinfo[faceid];
if (fi.isConstant() || fi.res == 0) {
return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
}
// get level zero (full) res face
Level* level = getLevel(0);
FaceData* face = getFace(0, level, faceid, fi.res);
return face;
}
PtexFaceData* PtexReader::getData(int faceid, Res res)
{
if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
return errorData(/*deleteOnRelease*/ true);
}
FaceInfo& fi = _faceinfo[faceid];
if (fi.isConstant() || res == 0) {
return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
}
// determine how many reduction levels are needed
int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
if (redu == 0 && redv == 0) {
// no reduction - get level zero (full) res face
Level* level = getLevel(0);
FaceData* face = getFace(0, level, faceid, res);
return face;
}
if (redu == redv && !fi.hasEdits()) {
// reduction is symmetric and non-negative
// and face has no edits => access data from reduction level (if present)
int levelid = redu;
if (size_t(levelid) < _levels.size()) {
Level* level = getLevel(levelid);
// get reduction face id
int rfaceid = _rfaceids[faceid];
// get the face data (if present)
FaceData* face = 0;
if (size_t(rfaceid) < level->faces.size()) {
face = getFace(levelid, level, rfaceid, res);
}
if (face) {
return face;
}
}
}
// dynamic reduction required - look in dynamic reduction cache
ReductionKey key(faceid, res);
FaceData* face = _reductions.get(key);
if (face) {
return face;
}
// not found, generate new reduction
FaceData *newface = 0;
size_t newMemUsed = 0;
if (res.ulog2 < 0 || res.vlog2 < 0) {
std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
newface = errorData();
}
else if (redu < 0 || redv < 0) {
std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
newface = errorData();
}
else if (_header.meshtype == mt_triangle)
{
if (redu != redv) {
std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
newface = errorData();
}
else {
PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
FaceData* src = static_cast< FaceData*>(psrc.get());
newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
}
}
else {
// determine which direction to blend
bool blendu;
if (redu == redv) {
// for symmetric face blends, alternate u and v blending
blendu = (res.ulog2 & 1);
}
else blendu = redu > redv;
if (blendu) {
// get next-higher u-res and reduce in u
PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
FaceData* src = static_cast< FaceData*>(psrc.get());
newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
}
else {
// get next-higher v-res and reduce in v
PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
FaceData* src = static_cast< FaceData*>(psrc.get());
newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
}
}
size_t tableNewMemUsed = 0;
face = _reductions.tryInsert(key, newface, tableNewMemUsed);
if (face != newface) {
delete newface;
}
else {
increaseMemUsed(newMemUsed + tableNewMemUsed);
}
return face;
}
void PtexReader::getPixel(int faceid, int u, int v,
float* result, int firstchan, int nchannelsArg)
{
memset(result, 0, sizeof(*result)*nchannelsArg);
// clip nchannels against actual number available
nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
if (nchannelsArg <= 0) return;
// get raw pixel data
PtexPtr<PtexFaceData> data ( getData(faceid) );
void* pixel = alloca(_pixelsize);
data->getPixel(u, v, pixel);
// adjust for firstchan offset
int datasize = DataSize(datatype());
if (firstchan)
pixel = (char*) pixel + datasize * firstchan;
// convert/copy to result as needed
if (datatype() == dt_float)
memcpy(result, pixel, datasize * nchannelsArg);
else
ConvertToFloat(result, pixel, datatype(), nchannelsArg);
}
void PtexReader::getPixel(int faceid, int u, int v,
float* result, int firstchan, int nchannelsArg,
Ptex::Res res)
{
memset(result, 0, nchannelsArg);
// clip nchannels against actual number available
nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
if (nchannelsArg <= 0) return;
// get raw pixel data
PtexPtr<PtexFaceData> data ( getData(faceid, res) );
void* pixel = alloca(_pixelsize);
data->getPixel(u, v, pixel);
// adjust for firstchan offset
int datasize = DataSize(datatype());
if (firstchan)
pixel = (char*) pixel + datasize * firstchan;
// convert/copy to result as needed
if (datatype() == dt_float)
memcpy(result, pixel, datasize * nchannelsArg);
else
ConvertToFloat(result, pixel, datatype(), nchannelsArg);
}
PtexReader::FaceData*
PtexReader::PackedFace::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
size_t& newMemUsed)
{
// allocate a new face and reduce image
DataType dt = r->datatype();
int nchan = r->nchannels();
int memsize = _pixelsize * newres.size();
PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
newMemUsed = sizeof(PackedFace) + memsize;
// reduce and copy into new face
reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
pf->_data, _pixelsize * newres.u(), dt, nchan);
return pf;
}
PtexReader::FaceData* PtexReader::ConstantFace::reduce(PtexReader*, Res, PtexUtils::ReduceFn, size_t& newMemUsed)
{
// must make a new constant face (even though it's identical to this one)
// because it will be owned by a different reduction level
// and will therefore have a different parent
ConstantFace* pf = new ConstantFace(_pixelsize);
newMemUsed = sizeof(ConstantFace) + _pixelsize;
memcpy(pf->_data, _data, _pixelsize);
return pf;
}
PtexReader::FaceData*
PtexReader::TiledFaceBase::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
size_t& newMemUsed)
{
/* 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* newface = 0;
// don't tile triangle reductions (too complicated)
Res newtileres;
bool isTriangle = r->_header.meshtype == mt_triangle;
if (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(_pixelsize);
memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
newMemUsed = sizeof(ConstantFace) + _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 = new char [_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
int memsize = _pixelsize * newres.size();
newface = new PackedFace(newres, _pixelsize, memsize);
newMemUsed = sizeof(PackedFace) + memsize;
// reduce and copy into new face
reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
delete [] tmp;
}
else {
// allocate a new packed face
int memsize = _pixelsize * newres.size();
newface = new PackedFace(newres, _pixelsize, memsize);
newMemUsed = sizeof(PackedFace) + memsize;
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
TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
newface = tf;
newMemUsed = tf->memUsed();
}
return newface;
}
void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
{
int tileu = ui >> _tileres.ulog2;
int tilev = vi >> _tileres.vlog2;
PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
tile->getPixel(ui - (tileu<<_tileres.ulog2),
vi - (tilev<<_tileres.vlog2), result);
}
PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
{
FaceData*& face = _tiles[tile];
if (face) {
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 ntilesval = nu*nv; // num parent tiles for this tile
PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
bool allConstant = true;
int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
for (int i = 0; i < ntilesval;) {
PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
allConstant = (allConstant && tileval->isConstant() &&
(i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
_pixelsize))));
i++;
ptile += (i%nu)? 1 : pntilesu - nu + 1;
}
FaceData* newface = 0;
size_t newMemUsed = 0;
if (allConstant) {
// allocate a new constant face
newface = new ConstantFace(_pixelsize);
newMemUsed = sizeof(ConstantFace) + _pixelsize;
memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
}
else {
// allocate a new packed face for the tile
int memsize = _pixelsize*_tileres.size();
newface = new PackedFace(_tileres, _pixelsize, memsize);
newMemUsed = sizeof(PackedFace) + memsize;
// 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*) newface->getData();
for (int i = 0; i < ntilesval;) {
PtexFaceData* tileval = tiles[i];
if (tileval->isConstant())
PtexUtils::fill(tileval->getData(), dst, dstride,
_tileres.u()/nu, _tileres.v()/nv,
_pixelsize);
else
_reducefn(tileval->getData(), sstride, ptileures, ptilevres,
dst, dstride, _dt, _nchan);
i++;
dst += (i%nu) ? dstepu : dstepv;
}
}
if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
delete newface;
}
else {
_reader->increaseMemUsed(newMemUsed);
}
return face;
}
PTEX_NAMESPACE_END
Magic
const uint32_t Magic
Definition PtexIO.h:104
EditMetaDataHeaderSize
const int EditMetaDataHeaderSize
Definition PtexIO.h:110
FaceDataHeaderSize
const int FaceDataHeaderSize
Definition PtexIO.h:108
ExtHeaderSize
const int ExtHeaderSize
Definition PtexIO.h:106
EditFaceDataHeaderSize
const int EditFaceDataHeaderSize
Definition PtexIO.h:109
AllocaMax
const int AllocaMax
Definition PtexIO.h:116
HeaderSize
const int HeaderSize
Definition PtexIO.h:105
LevelInfoSize
const int LevelInfoSize
Definition PtexIO.h:107
BlockSize
const int BlockSize
Definition PtexIO.h:114
LittleEndian
bool LittleEndian()
Definition PtexIO.h:119
et_editfacedata
@ et_editfacedata
Definition PtexIO.h:92
et_editmetadata
@ et_editmetadata
Definition PtexIO.h:92
enc_diffzipped
@ enc_diffzipped
Definition PtexIO.h:81
enc_zipped
@ enc_zipped
Definition PtexIO.h:81
enc_constant
@ enc_constant
Definition PtexIO.h:81
enc_tiled
@ enc_tiled
Definition PtexIO.h:81
PtexPlatform.h
Platform-specific classes, functions, and includes.
FilePos
off_t FilePos
Definition PtexPlatform.h:99
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition PtexPlatform.h:284
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition PtexPlatform.h:278
PtexReader.h
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition PtexUtils.cpp:123
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
AutoLock
Automatically acquire and release lock within enclosing scope.
Definition PtexMutex.h:43
Mutex::trylock
bool trylock()
Definition PtexPlatform.h:142
Mutex::unlock
void unlock()
Definition PtexPlatform.h:143
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition Ptexture.h:658
PtexErrorHandler::reportError
virtual void reportError(const char *error)=0
PtexFaceData
Per-face texture data accessor.
Definition Ptexture.h:406
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
PtexHashMap::get
Value get(Key &key)
Definition PtexHashMap.h:203
PtexHashMap::clear
void clear()
Definition PtexHashMap.h:195
PtexHashMap::tryInsert
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition PtexHashMap.h:224
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition Ptexture.h:619
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexMetaData
Meta data accessor.
Definition Ptexture.h:328
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition Ptexture.h:1032
PtexPtr::get
T * get() const
Get pointer value.
Definition Ptexture.h:1048
PtexReader::ConstDataPtr
Definition PtexReader.h:345
PtexReader::ConstantFace
Definition PtexReader.h:401
PtexReader::ConstantFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:966
PtexReader::FaceData
Definition PtexReader.h:365
PtexReader::FaceData::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
PtexReader::Level
Definition PtexReader.h:520
PtexReader::Level::offsets
std::vector< FilePos > offsets
Definition PtexReader.h:523
PtexReader::Level::fdh
std::vector< FaceDataHeader > fdh
Definition PtexReader.h:522
PtexReader::Level::faces
std::vector< FaceData * > faces
Definition PtexReader.h:524
PtexReader::Level::memUsed
size_t memUsed()
Definition PtexReader.h:537
PtexReader::MetaData::LargeMetaData
Definition PtexReader.h:273
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition PtexReader.h:278
PtexReader::MetaData
Definition PtexReader.h:120
PtexReader::MetaData::selfDataSize
size_t selfDataSize()
Definition PtexReader.h:266
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition PtexReader.h:246
PtexReader::MetaData::_reader
PtexReader * _reader
Definition PtexReader.h:338
PtexReader::MetaData::addLmdEntry
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize, size_t &metaDataMemUsed)
Definition PtexReader.h:255
PtexReader::MetaData::getEntry
Entry * getEntry(int index)
Definition PtexReader.cpp:343
PtexReader::MetaData::_entries
std::vector< Entry * > _entries
Definition PtexReader.h:341
PtexReader::PackedFace
Definition PtexReader.h:377
PtexReader::PackedFace::data
void * data()
Definition PtexReader.h:382
PtexReader::PackedFace::_data
char * _data
Definition PtexReader.h:398
PtexReader::PackedFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:949
PtexReader::ReductionKey
Definition PtexReader.h:685
PtexReader::TiledFaceBase::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:979
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition PtexReader.h:464
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition PtexReader.cpp:1104
PtexReader::TiledFace
Definition PtexReader.h:470
PtexReader::TiledFace::_fdh
std::vector< FaceDataHeader > _fdh
Definition PtexReader.h:493
PtexReader::TiledFace::memUsed
size_t memUsed()
Definition PtexReader.h:486
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition PtexReader.cpp:635
PtexReader::TiledFace::_offsets
std::vector< FilePos > _offsets
Definition PtexReader.h:494
PtexReader::TiledReducedFace
Definition PtexReader.h:498
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition PtexReader.cpp:1115
PtexReader::TiledReducedFace::memUsed
size_t memUsed()
Definition PtexReader.h:512
PtexReader
Definition PtexReader.h:52
PtexReader::readLevelInfo
void readLevelInfo()
Definition PtexReader.cpp:298
PtexReader::_reductions
ReductionMap _reductions
Definition PtexReader.h:713
PtexReader::reopenFP
bool reopenFP()
Definition PtexReader.cpp:240
PtexReader::datatype
DataType datatype() const
Definition PtexReader.h:113
PtexReader::readEditFaceData
void readEditFaceData()
Definition PtexReader.cpp:502
PtexReader::_premultiply
bool _premultiply
Definition PtexReader.h:641
PtexReader::_constdatapos
FilePos _constdatapos
Definition PtexReader.h:651
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:414
PtexReader::readFaceInfo
void readFaceInfo()
Definition PtexReader.cpp:277
PtexReader::_path
std::string _path
Definition PtexReader.h:647
PtexReader::_constdata
uint8_t * _constdata
Definition PtexReader.h:659
PtexReader::_levelpos
std::vector< FilePos > _levelpos
Definition PtexReader.h:666
PtexReader::readEditData
void readEditData()
Definition PtexReader.cpp:468
PtexReader::getPixel
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
Definition PtexReader.cpp:893
PtexReader::_faceedits
std::vector< FaceEdit > _faceedits
Definition PtexReader.h:683
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition PtexReader.h:56
PtexReader::increaseMemUsed
void increaseMemUsed(size_t amount)
Definition PtexReader.h:71
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.h:580
PtexReader::purge
void purge()
Definition PtexReader.cpp:115
PtexReader::_editdatapos
FilePos _editdatapos
Definition PtexReader.h:657
PtexReader::tell
FilePos tell()
Definition PtexReader.h:557
PtexReader::getLevel
Level * getLevel(int levelid)
Definition PtexReader.h:572
PtexReader::errorData
FaceData * errorData(bool deleteOnRelease=false)
Definition PtexReader.h:600
PtexReader::~PtexReader
virtual ~PtexReader()
Definition PtexReader.cpp:93
PtexReader::_hasEdits
bool _hasEdits
Definition PtexReader.h:661
PtexReader::_needToOpen
bool _needToOpen
Definition PtexReader.h:643
PtexReader::computeOffsets
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition PtexReader.h:605
PtexReader::readConstData
void readConstData()
Definition PtexReader.cpp:319
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition PtexReader.cpp:335
PtexReader::needToOpen
bool needToOpen() const
Definition PtexReader.h:57
PtexReader::_extheader
ExtHeader _extheader
Definition PtexReader.h:649
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition PtexReader.h:653
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition PtexReader.cpp:711
PtexReader::_err
PtexErrorHandler * _err
Definition PtexReader.h:640
PtexReader::readEditMetaData
void readEditMetaData()
Definition PtexReader.cpp:533
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition PtexReader.h:650
PtexReader::_levelinfo
std::vector< LevelInfo > _levelinfo
Definition PtexReader.h:665
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition PtexReader.cpp:71
PtexReader::_zstream
z_stream_s _zstream
Definition PtexReader.h:716
PtexReader::_io
PtexInputHandler * _io
Definition PtexReader.h:639
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition PtexReader.cpp:267
PtexReader::_metadatapos
FilePos _metadatapos
Definition PtexReader.h:654
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:440
PtexReader::closeFP
void closeFP()
Definition PtexReader.cpp:230
PtexReader::_pixelsize
int _pixelsize
Definition PtexReader.h:658
PtexReader::_pendingPurge
bool _pendingPurge
Definition PtexReader.h:644
PtexReader::readlock
Mutex readlock
Definition PtexReader.h:637
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.cpp:627
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition PtexReader.h:652
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition PtexReader.h:655
PtexReader::nchannels
int nchannels() const
Definition PtexReader.h:114
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition PtexReader.h:656
PtexReader::prune
void prune()
Definition PtexReader.cpp:104
PtexReader::_rfaceids
std::vector< uint32_t > _rfaceids
Definition PtexReader.h:664
PtexReader::_metaedits
std::vector< MetaEdit > _metaedits
Definition PtexReader.h:675
PtexReader::_memUsed
volatile size_t _memUsed
Definition PtexReader.h:718
PtexReader::_header
Header _header
Definition PtexReader.h:648
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition PtexReader.cpp:641
PtexReader::seek
void seek(FilePos pos)
Definition PtexReader.h:558
PtexReader::readBlock
bool readBlock(void *data, int size, bool reportError=true)
Definition PtexReader.cpp:548
PtexReader::_metadata
MetaData * _metadata
Definition PtexReader.h:660
PtexReader::_levels
std::vector< Level * > _levels
Definition PtexReader.h:667
PtexReader::_baseMemUsed
size_t _baseMemUsed
Definition PtexReader.h:717
PtexReader::_faceinfo
std::vector< FaceInfo > _faceinfo
Definition PtexReader.h:663
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition PtexReader.h:645
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition PtexReader.cpp:563
PtexReader::readMetaData
void readMetaData()
Definition PtexReader.cpp:381
PtexReader::logOpen
void logOpen()
Definition PtexReader.h:72
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition PtexReader.cpp:595
PtexReader::_errorPixel
std::vector< char > _errorPixel
Definition PtexReader.h:714
PtexReader::getConstData
uint8_t * getConstData()
Definition PtexReader.h:579
PtexReader::_pos
FilePos _pos
Definition PtexReader.h:646
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition PtexReader.cpp:137
PtexReader::tryClose
bool tryClose()
Definition PtexReader.cpp:219
PtexReader::setError
void setError(const char *error)
Definition PtexReader.h:546
PtexReader::_ok
bool _ok
Definition PtexReader.h:642
PtexTexture
Interface for reading data from a ptex file.
Definition Ptexture.h:457
PtexTexture::path
virtual const char * path()=0
Path that file was opened with.
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition PtexReader.cpp:59
Ptex::String
Memory-managed string.
Definition Ptexture.h:296
Ptex::String::c_str
const char * c_str() const
Definition Ptexture.h:304
PTEX_NAMESPACE_BEGIN
Definition PtexSeparableKernel.cpp:42
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition PtexUtils.cpp:630
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:333
PtexUtils::min
T min(T a, T b)
Definition PtexUtils.h:148
PtexUtils::max
T max(T a, T b)
Definition PtexUtils.h:151
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition PtexUtils.cpp:271
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:366
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition PtexUtils.cpp:422
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:406
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition PtexUtils.cpp:438
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition PtexUtils.h:185
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition PtexUtils.cpp:579
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:189
EditFaceDataHeader
Definition PtexIO.h:93
EditFaceDataHeader::faceid
uint32_t faceid
Definition PtexIO.h:94
EditFaceDataHeader::fdh
FaceDataHeader fdh
Definition PtexIO.h:96
EditFaceDataHeader::faceinfo
FaceInfo faceinfo
Definition PtexIO.h:95
EditMetaDataHeader
Definition PtexIO.h:98
EditMetaDataHeader::metadatazipsize
uint32_t metadatazipsize
Definition PtexIO.h:99
EditMetaDataHeader::metadatamemsize
uint32_t metadatamemsize
Definition PtexIO.h:100
ExtHeader
Definition PtexIO.h:64
ExtHeader::lmddatasize
uint64_t lmddatasize
Definition PtexIO.h:71
ExtHeader::editdatapos
uint64_t editdatapos
Definition PtexIO.h:73
ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition PtexIO.h:70
ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition PtexIO.h:69
ExtHeader::editdatasize
uint64_t editdatasize
Definition PtexIO.h:72
FaceDataHeader
Definition PtexIO.h:82
FaceDataHeader::encoding
Encoding encoding() const
Definition PtexIO.h:85
FaceDataHeader::blocksize
uint32_t blocksize() const
Definition PtexIO.h:84
Header
Definition PtexIO.h:44
Header::metadatamemsize
uint32_t metadatamemsize
Definition PtexIO.h:60
Header::faceinfosize
uint32_t faceinfosize
Definition PtexIO.h:54
Header::nlevels
uint16_t nlevels
Definition PtexIO.h:51
Header::nchannels
uint16_t nchannels
Definition PtexIO.h:50
Header::meshtype
uint32_t meshtype
Definition PtexIO.h:47
Header::constdatasize
uint32_t constdatasize
Definition PtexIO.h:55
Header::levelinfosize
uint32_t levelinfosize
Definition PtexIO.h:56
Header::extheadersize
uint32_t extheadersize
Definition PtexIO.h:53
Header::metadatazipsize
uint32_t metadatazipsize
Definition PtexIO.h:59
Header::pixelSize
int pixelSize() const
Definition PtexIO.h:61
Header::alphachan
int32_t alphachan
Definition PtexIO.h:49
Header::magic
uint32_t magic
Definition PtexIO.h:45
Header::nfaces
uint32_t nfaces
Definition PtexIO.h:52
Header::leveldatasize
uint64_t leveldatasize
Definition PtexIO.h:58
Header::version
uint32_t version
Definition PtexIO.h:46
Header::hasAlpha
bool hasAlpha() const
Definition PtexIO.h:62
LevelInfo
Definition PtexIO.h:75
LevelInfo::levelheadersize
uint32_t levelheadersize
Definition PtexIO.h:77
LevelInfo::nfaces
uint32_t nfaces
Definition PtexIO.h:78
PtexReader::FaceEdit
Definition PtexReader.h:678
PtexReader::FaceEdit::pos
FilePos pos
Definition PtexReader.h:679
PtexReader::FaceEdit::faceid
int faceid
Definition PtexReader.h:680
PtexReader::FaceEdit::fdh
FaceDataHeader fdh
Definition PtexReader.h:681
PtexReader::MetaData::Entry
Definition PtexReader.h:284
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition PtexReader.h:291
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition PtexReader.h:292
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition PtexReader.h:289
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition PtexReader.h:287
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition PtexReader.h:290
PtexReader::MetaData::Entry::data
char * data
Definition PtexReader.h:288
PtexReader::MetaEdit
Definition PtexReader.h:670
PtexReader::MetaEdit::zipsize
int zipsize
Definition PtexReader.h:672
PtexReader::MetaEdit::memsize
int memsize
Definition PtexReader.h:673
PtexReader::MetaEdit::pos
FilePos pos
Definition PtexReader.h:671
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition Ptexture.h:229
Ptex::Res
Pixel resolution of a given texture.
Definition Ptexture.h:159