Ptex
PtexReader.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2014 Disney Enterprises, Inc. All rights reserved
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in
14  the documentation and/or other materials provided with the
15  distribution.
16 
17  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18  Studios" or the names of its contributors may NOT be used to
19  endorse or promote products derived from this software without
20  specific prior written permission from Walt Disney Pictures.
21 
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
35 
36 #include "PtexPlatform.h"
37 #include <iostream>
38 #include <sstream>
39 #include <stdio.h>
40 
41 #include "Ptexture.h"
42 #include "PtexUtils.h"
43 #include "PtexReader.h"
44 
45 namespace {
46  class TempErrorHandler : public PtexErrorHandler
47  {
48  std::string _error;
49  public:
50  virtual void reportError(const char* error) {
51  _error += error;
52  }
53  const std::string& getErrorString() const { return _error; }
54  };
55 }
56 
58 
59 PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
60 {
61  PtexReader* reader = new PtexReader(premultiply, (PtexInputHandler*) 0, (PtexErrorHandler*) 0);
62  bool ok = reader->open(path, error);
63  if (!ok) {
64  reader->release();
65  return 0;
66  }
67  return reader;
68 }
69 
70 
72  : _io(io ? io : &_defaultIo),
73  _err(err),
74  _premultiply(premultiply),
75  _ok(true),
76  _needToOpen(true),
77  _pendingPurge(false),
78  _fp(0),
79  _pos(0),
80  _pixelsize(0),
81  _constdata(0),
82  _metadata(0),
83  _hasEdits(false),
84  _baseMemUsed(sizeof(*this)),
85  _memUsed(_baseMemUsed),
86  _opens(0),
87  _blockReads(0)
88 {
89  memset(&_zstream, 0, sizeof(_zstream));
90 }
91 
92 
94 {
95  closeFP();
96  if (_constdata) delete [] _constdata;
97  if (_metadata) delete _metadata;
98 
99  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
100  if (*i) delete *i;
101  }
102 }
103 
105 {
106  if (_metadata) { delete _metadata; _metadata = 0; }
107  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
108  if (*i) { delete *i; *i = 0; }
109  }
110  _reductions.clear();
112 }
113 
114 
116 {
117  // free all dynamic data
118  prune();
119  if (_constdata) {delete [] _constdata; _constdata = 0; }
120  std::vector<FaceInfo>().swap(_faceinfo);
121  std::vector<uint32_t>().swap(_rfaceids);
122  std::vector<LevelInfo>().swap(_levelinfo);
123  std::vector<FilePos>().swap(_levelpos);
124  std::vector<Level*>().swap(_levels);
125  std::vector<MetaEdit>().swap(_metaedits);
126  std::vector<FaceEdit>().swap(_faceedits);
127  closeFP();
128 
129  // reset initial state
130  _ok = true;
131  _needToOpen = true;
132  _pendingPurge = false;
133  _memUsed = _baseMemUsed = sizeof(*this);
134 }
135 
136 
137 bool PtexReader::open(const char* pathArg, Ptex::String& error)
138 {
139  AutoMutex locker(readlock);
140  if (!needToOpen()) return false;
141 
142  if (!LittleEndian()) {
143  error = "Ptex library doesn't currently support big-endian cpu's";
144  return 0;
145  }
146  _path = pathArg;
147  _fp = _io->open(pathArg);
148  if (!_fp) {
149  std::string errstr = "Can't open ptex file: ";
150  errstr += pathArg; errstr += "\n"; errstr += _io->lastError();
151  error = errstr.c_str();
152  _ok = 0;
153  return 0;
154  }
155  memset(&_header, 0, sizeof(_header));
157  if (_header.magic != Magic) {
158  std::string errstr = "Not a ptex file: "; errstr += pathArg;
159  error = errstr.c_str();
160  _ok = 0;
161  closeFP();
162  return 0;
163  }
164  if (_header.version != 1) {
165  std::stringstream s;
166  s << "Unsupported ptex file version ("<< _header.version << "): " << pathArg;
167  error = s.str();
168  _ok = 0;
169  closeFP();
170  return 0;
171  }
173  std::stringstream s;
174  s << "Invalid mesh type (" << _header.meshtype << "): " << pathArg;
175  error = s.str();
176  _ok = 0;
177  closeFP();
178  return 0;
179  }
181  _errorPixel.resize(_pixelsize);
182 
183  // install temp error handler to capture error (to return in error param)
184  TempErrorHandler tempErr;
185  PtexErrorHandler* prevErr = _err;
186  _err = &tempErr;
187 
188  // read extended header
189  memset(&_extheader, 0, sizeof(_extheader));
191 
192  // compute offsets of various blocks
194  _faceinfopos = pos; pos += _header.faceinfosize;
195  _constdatapos = pos; pos += _header.constdatasize;
196  _levelinfopos = pos; pos += _header.levelinfosize;
197  _leveldatapos = pos; pos += _header.leveldatasize;
198  _metadatapos = pos; pos += _header.metadatazipsize;
199  pos += sizeof(uint64_t); // compatibility barrier
201  _lmddatapos = pos; pos += _extheader.lmddatasize;
202 
203  // edit data may not start immediately if additional sections have been added
204  // use value from extheader if present (and > pos)
206 
207  // read basic file info
208  readFaceInfo();
209  readConstData();
210  readLevelInfo();
211  readEditData();
213 
214  // restore error handler
215  _err = prevErr;
216 
217  // an error occurred while reading the file
218  if (!_ok) {
219  error = tempErr.getErrorString();
220  closeFP();
221  return 0;
222  }
223  AtomicStore(&_needToOpen, false);
224  return true;
225 }
226 
228 {
229  if (_fp) {
230  if (!readlock.trylock()) return false;
231  closeFP();
232  readlock.unlock();
233  }
234  return true;
235 }
236 
237 
239 {
240  if (_fp) {
241  _io->close(_fp);
242  _fp = 0;
243  }
244  inflateEnd(&_zstream);
245 }
246 
247 
249 {
250  if (_fp) return true;
251 
252  // we assume this is called lazily in a scope where readlock is already held
253  _fp = _io->open(_path.c_str());
254  if (!_fp) {
255  setError("Can't reopen");
256  return false;
257  }
258  _pos = 0;
259  Header headerval;
260  ExtHeader extheaderval;
261  readBlock(&headerval, HeaderSize);
262  memset(&extheaderval, 0, sizeof(extheaderval));
263  readBlock(&extheaderval, PtexUtils::min(uint32_t(ExtHeaderSize), headerval.extheadersize));
264  if (0 != memcmp(&headerval, &_header, sizeof(headerval)) ||
265  0 != memcmp(&extheaderval, &_extheader, sizeof(extheaderval)))
266  {
267  setError("Header mismatch on reopen of");
268  return false;
269  }
270  logOpen();
271  return true;
272 }
273 
274 
276 {
277  if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
278  return _faceinfo[faceid];
279 
280  static Ptex::FaceInfo dummy;
281  return dummy;
282 }
283 
284 
286 {
287  if (_faceinfo.empty()) {
288  // read compressed face info block
290  int nfaces = _header.nfaces;
291  _faceinfo.resize(nfaces);
293  (int)(sizeof(FaceInfo)*nfaces));
294 
295  // generate rfaceids
296  _rfaceids.resize(nfaces);
297  std::vector<uint32_t> faceids_r(nfaces);
298  PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
299  &_rfaceids[0], &faceids_r[0]);
300  increaseMemUsed(nfaces * (sizeof(_faceinfo[0]) + sizeof(_rfaceids[0])));
301  }
302 }
303 
304 
305 
307 {
308  if (_levelinfo.empty()) {
309  // read level info block
311  _levelinfo.resize(_header.nlevels);
313 
314  // initialize related data
315  _levels.resize(_header.nlevels);
316  _levelpos.resize(_header.nlevels);
317  FilePos pos = _leveldatapos;
318  for (int i = 0; i < _header.nlevels; i++) {
319  _levelpos[i] = pos;
320  pos += _levelinfo[i].leveldatasize;
321  }
322  increaseMemUsed(_header.nlevels * sizeof(_levelinfo[0]) + sizeof(_levels[0]) + sizeof(_levelpos[0]));
323  }
324 }
325 
326 
328 {
329  if (!_constdata) {
330  // read compressed constant data block
332  int size = _pixelsize * _header.nfaces;
333  _constdata = new uint8_t[size];
335  if (_premultiply && _header.hasAlpha())
338  increaseMemUsed(size);
339  }
340 }
341 
342 
344 {
345  if (!_metadata) readMetaData();
346  return _metadata;
347 }
348 
349 
352 {
353  if (index < 0 || index >= int(_entries.size())) {
354  return 0;
355  }
356 
357  Entry* e = _entries[index];
358  if (!e->isLmd) {
359  // normal (small) meta data - just return directly
360  return e;
361  }
362 
363  // large meta data - may not be read in yet
364  if (e->lmdData) {
365  // already in memory
366  return e;
367  }
368  else {
369  // not present, must read from file
370 
371  // get read lock and make sure we still need to read
372  AutoMutex locker(_reader->readlock);
373  if (e->lmdData) {
374  return e;
375  }
376  // go ahead and read, keep local until finished
377  LargeMetaData* lmdData = new LargeMetaData(e->datasize);
378  e->data = (char*) lmdData->data();
380  _reader->seek(e->lmdPos);
382  // update entry
383  e->lmdData = lmdData;
384  return e;
385  }
386 }
387 
388 
390 {
391  // get read lock and make sure we still need to read
392  AutoMutex locker(readlock);
393  if (_metadata) {
394  return;
395  }
396 
397  // allocate new meta data (keep local until fully initialized)
398  MetaData* newmeta = new MetaData(this);
399  size_t metaDataMemUsed = sizeof(MetaData);
400 
401  // read primary meta data blocks
404  _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
405 
406  // read large meta data headers
410 
411  // read meta data edits
412  for (size_t i = 0, size = _metaedits.size(); i < size; i++)
413  readMetaDataBlock(newmeta, _metaedits[i].pos,
414  _metaedits[i].zipsize, _metaedits[i].memsize, metaDataMemUsed);
415 
416  // store meta data
417  AtomicStore(&_metadata, newmeta);
418  increaseMemUsed(newmeta->selfDataSize() + metaDataMemUsed);
419 }
420 
421 
422 void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
423 {
424  seek(pos);
425  // read from file
426  bool useNew = memsize > AllocaMax;
427  char* buff = useNew ? new char[memsize] : (char*)alloca(memsize);
428 
429  if (readZipBlock(buff, zipsize, memsize)) {
430  // unpack data entries
431  char* ptr = buff;
432  char* end = ptr + memsize;
433  while (ptr < end) {
434  uint8_t keysize = *ptr++;
435  char* key = (char*)ptr; ptr += keysize;
436  key[keysize-1] = '\0';
437  uint8_t datatypeval = *ptr++;
438  uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
439  ptr += sizeof(datasize);
440  char* data = ptr; ptr += datasize;
441  metadata->addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
442  }
443  }
444  if (useNew) delete [] buff;
445 }
446 
447 
448 void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
449 {
450  seek(pos);
451  // read from file
452  bool useNew = memsize > AllocaMax;
453  char* buff = useNew ? new char [memsize] : (char*)alloca(memsize);
454 
455  if (readZipBlock(buff, zipsize, memsize)) {
456  pos += zipsize;
457 
458  // unpack data entries
459  char* ptr = buff;
460  char* end = ptr + memsize;
461  while (ptr < end) {
462  uint8_t keysize = *ptr++;
463  char* key = (char*)ptr; ptr += keysize;
464  uint8_t datatypeval = *ptr++;
465  uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
466  ptr += sizeof(datasize);
467  uint32_t zipsizeval; memcpy(&zipsizeval, ptr, sizeof(zipsizeval));
468  ptr += sizeof(zipsizeval);
469  metadata->addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
470  pos += zipsizeval;
471  }
472  }
473  if (useNew) delete [] buff;
474 }
475 
477 {
478  // determine file range to scan for edits
479  FilePos pos = FilePos(_editdatapos), endpos;
480  if (_extheader.editdatapos > 0) {
481  // newer files record the edit data position and size in the extheader
482  // note: position will be non-zero even if size is zero
483  endpos = FilePos(pos + _extheader.editdatasize);
484  }
485  else {
486  // must have an older file, just read until EOF
487  endpos = FilePos((uint64_t)-1);
488  }
489 
490  while (pos < endpos) {
491  seek(pos);
492  // read the edit data header
493  uint8_t edittype = et_editmetadata;
494  uint32_t editsize;
495  if (!readBlock(&edittype, sizeof(edittype), /*reporterror*/ false)) break;
496  if (!readBlock(&editsize, sizeof(editsize), /*reporterror*/ false)) break;
497  if (!editsize) break;
498  _hasEdits = true;
499  pos = tell() + editsize;
500  switch (edittype) {
501  case et_editfacedata: readEditFaceData(); break;
502  case et_editmetadata: readEditMetaData(); break;
503  }
504  }
505  increaseMemUsed(sizeof(_faceedits[0]) * _faceedits.capacity() +
506  sizeof(_metaedits[0]) * _metaedits.capacity());
507 }
508 
509 
511 {
512  // read header
513  EditFaceDataHeader efdh;
514  if (!readBlock(&efdh, EditFaceDataHeaderSize)) return;
515 
516  // update face info
517  int faceid = efdh.faceid;
518  if (faceid < 0 || size_t(faceid) >= _header.nfaces) return;
519  FaceInfo& f = _faceinfo[faceid];
520  f = efdh.faceinfo;
521  f.flags |= FaceInfo::flag_hasedits;
522 
523  // read const value now
524  uint8_t* constdata = _constdata + _pixelsize * faceid;
525  if (!readBlock(constdata, _pixelsize)) return;
526  if (_premultiply && _header.hasAlpha())
527  PtexUtils::multalpha(constdata, 1, datatype(),
529 
530  // update header info for remaining data
531  if (!f.isConstant()) {
532  _faceedits.push_back(FaceEdit());
533  FaceEdit& e = _faceedits.back();
534  e.pos = tell();
535  e.faceid = faceid;
536  e.fdh = efdh.fdh;
537  }
538 }
539 
540 
542 {
543  // read header
544  EditMetaDataHeader emdh;
545  if (!readBlock(&emdh, EditMetaDataHeaderSize)) return;
546 
547  // record header info for later
548  _metaedits.push_back(MetaEdit());
549  MetaEdit& e = _metaedits.back();
550  e.pos = tell();
551  e.zipsize = emdh.metadatazipsize;
552  e.memsize = emdh.metadatamemsize;
553 }
554 
555 
556 bool PtexReader::readBlock(void* data, int size, bool reporterror)
557 {
558  assert(_fp && size >= 0);
559  if (!_fp || size < 0) return false;
560  int result = (int)_io->read(data, size, _fp);
561  if (result == size) {
562  _pos += size;
563  return true;
564  }
565  if (reporterror)
566  setError("PtexReader error: read failed (EOF)");
567  return false;
568 }
569 
570 
571 bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
572 {
573  if (zipsize < 0 || unzipsize < 0) return false;
574  if (!_zstream.state) {
575  inflateInit(&_zstream);
576  }
577 
578  void* buff = alloca(BlockSize);
579  _zstream.next_out = (Bytef*) data;
580  _zstream.avail_out = unzipsize;
581 
582  while (1) {
583  int size = (zipsize < BlockSize) ? zipsize : BlockSize;
584  zipsize -= size;
585  if (!readBlock(buff, size)) break;
586  _zstream.next_in = (Bytef*) buff;
587  _zstream.avail_in = size;
588  int zresult = inflate(&_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
589  if (zresult == Z_STREAM_END) break;
590  if (zresult != Z_OK) {
591  setError("PtexReader error: unzip failed, file corrupt");
592  inflateReset(&_zstream);
593  return 0;
594  }
595  }
596 
597  int total = (int)_zstream.total_out;
598  inflateReset(&_zstream);
599  return total == unzipsize;
600 }
601 
602 
603 void PtexReader::readLevel(int levelid, Level*& level)
604 {
605  // get read lock and make sure we still need to read
606  AutoMutex locker(readlock);
607  if (level) {
608  return;
609  }
610 
611  // go ahead and read the level
612  LevelInfo& l = _levelinfo[levelid];
613 
614  // keep new level local until finished
615  Level* newlevel = new Level(l.nfaces);
616  seek(_levelpos[levelid]);
618  computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
619 
620  // apply edits (if any) to level 0
621  if (levelid == 0) {
622  for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
623  FaceEdit& e = _faceedits[i];
624  newlevel->fdh[e.faceid] = e.fdh;
625  newlevel->offsets[e.faceid] = e.pos;
626  }
627  }
628 
629  // don't assign to result until level data is fully initialized
630  AtomicStore(&level, newlevel);
631  increaseMemUsed(level->memUsed());
632 }
633 
634 
635 void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
636 {
637  FaceData*& face = level->faces[faceid];
638  FaceDataHeader fdh = level->fdh[faceid];
639  readFaceData(level->offsets[faceid], fdh, res, levelid, face);
640 }
641 
642 
644 {
645  _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
646 }
647 
648 
649 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
650  FaceData*& face)
651 {
652  AutoMutex locker(readlock);
653  if (face) {
654  return;
655  }
656 
657  // keep new face local until fully initialized
658  FaceData* newface = 0;
659  size_t newMemUsed = 0;
660 
661  seek(pos);
662  switch (fdh.encoding()) {
663  case enc_constant:
664  {
666  newface = cf;
667  newMemUsed = sizeof(ConstantFace) + _pixelsize;
668  readBlock(cf->data(), _pixelsize);
669  if (levelid==0 && _premultiply && _header.hasAlpha())
670  PtexUtils::multalpha(cf->data(), 1, datatype(),
672  }
673  break;
674  case enc_tiled:
675  {
676  Res tileres;
677  readBlock(&tileres, sizeof(tileres));
678  uint32_t tileheadersize;
679  readBlock(&tileheadersize, sizeof(tileheadersize));
680  TiledFace* tf = new TiledFace(this, res, tileres, levelid);
681  newface = tf;
682  newMemUsed = tf->memUsed();
683  readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
684  computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
685  }
686  break;
687  case enc_zipped:
688  case enc_diffzipped:
689  {
690  int uw = res.u(), vw = res.v();
691  int npixels = uw * vw;
692  int unpackedSize = _pixelsize * npixels;
693  PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
694  newface = pf;
695  newMemUsed = sizeof(PackedFace) + unpackedSize;
696  bool useNew = unpackedSize > AllocaMax;
697  char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
698  readZipBlock(tmp, fdh.blocksize(), unpackedSize);
699  if (fdh.encoding() == enc_diffzipped)
700  PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
701  PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
702  pf->data(), uw * _pixelsize,
704  if (levelid==0 && _premultiply && _header.hasAlpha())
705  PtexUtils::multalpha(pf->data(), npixels, datatype(),
707  if (useNew) delete [] tmp;
708  }
709  break;
710  }
711 
712  if (!newface) newface = errorData();
713 
714  AtomicStore(&face, newface);
715  increaseMemUsed(newMemUsed);
716 }
717 
718 
719 void PtexReader::getData(int faceid, void* buffer, int stride)
720 {
721  const FaceInfo& f = getFaceInfo(faceid);
722  getData(faceid, buffer, stride, f.res);
723 }
724 
725 
726 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
727 {
728  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
729  PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
730  return;
731  }
732 
733  // note - all locking is handled in called getData methods
734  int resu = res.u(), resv = res.v();
735  int rowlen = _pixelsize * resu;
736  if (stride == 0) stride = rowlen;
737 
738  PtexPtr<PtexFaceData> d ( getData(faceid, res) );
739  if (d->isConstant()) {
740  // fill dest buffer with pixel value
741  PtexUtils::fill(d->getData(), buffer, stride,
742  resu, resv, _pixelsize);
743  }
744  else if (d->isTiled()) {
745  // loop over tiles
746  Res tileres = d->tileRes();
747  int ntilesu = res.ntilesu(tileres);
748  int ntilesv = res.ntilesv(tileres);
749  int tileures = tileres.u();
750  int tilevres = tileres.v();
751  int tilerowlen = _pixelsize * tileures;
752  int tile = 0;
753  char* dsttilerow = (char*) buffer;
754  for (int i = 0; i < ntilesv; i++) {
755  char* dsttile = dsttilerow;
756  for (int j = 0; j < ntilesu; j++) {
757  PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
758  if (t->isConstant())
759  PtexUtils::fill(t->getData(), dsttile, stride,
760  tileures, tilevres, _pixelsize);
761  else
762  PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
763  tilevres, tilerowlen);
764  dsttile += tilerowlen;
765  }
766  dsttilerow += stride * tilevres;
767  }
768  }
769  else {
770  PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
771  }
772 }
773 
774 
776 {
777  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
778  return errorData(/*deleteOnRelease*/ true);
779  }
780 
781  FaceInfo& fi = _faceinfo[faceid];
782  if (fi.isConstant() || fi.res == 0) {
783  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
784  }
785 
786  // get level zero (full) res face
787  Level* level = getLevel(0);
788  FaceData* face = getFace(0, level, faceid, fi.res);
789  return face;
790 }
791 
792 
793 PtexFaceData* PtexReader::getData(int faceid, Res res)
794 {
795  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
796  return errorData(/*deleteOnRelease*/ true);
797  }
798 
799  FaceInfo& fi = _faceinfo[faceid];
800  if (fi.isConstant() || res == 0) {
801  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
802  }
803 
804  // determine how many reduction levels are needed
805  int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
806 
807  if (redu == 0 && redv == 0) {
808  // no reduction - get level zero (full) res face
809  Level* level = getLevel(0);
810  FaceData* face = getFace(0, level, faceid, res);
811  return face;
812  }
813 
814  if (redu == redv && !fi.hasEdits()) {
815  // reduction is symmetric and non-negative
816  // and face has no edits => access data from reduction level (if present)
817  int levelid = redu;
818  if (size_t(levelid) < _levels.size()) {
819  Level* level = getLevel(levelid);
820 
821  // get reduction face id
822  int rfaceid = _rfaceids[faceid];
823 
824  // get the face data (if present)
825  FaceData* face = 0;
826  if (size_t(rfaceid) < level->faces.size()) {
827  face = getFace(levelid, level, rfaceid, res);
828  }
829  if (face) {
830  return face;
831  }
832  }
833  }
834 
835  // dynamic reduction required - look in dynamic reduction cache
836  ReductionKey key(faceid, res);
837  FaceData* face = _reductions.get(key);
838  if (face) {
839  return face;
840  }
841 
842  // not found, generate new reduction
843  FaceData *newface = 0;
844  size_t newMemUsed = 0;
845 
846  if (res.ulog2 < 0 || res.vlog2 < 0) {
847  std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
848  newface = errorData();
849  }
850  else if (redu < 0 || redv < 0) {
851  std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
852  newface = errorData();
853  }
854  else if (_header.meshtype == mt_triangle)
855  {
856  if (redu != redv) {
857  std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
858  newface = errorData();
859  }
860  else {
861  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
862  FaceData* src = static_cast<FaceData*>(psrc.get());
863  newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
864  }
865  }
866  else {
867  // determine which direction to blend
868  bool blendu;
869  if (redu == redv) {
870  // for symmetric face blends, alternate u and v blending
871  blendu = (res.ulog2 & 1);
872  }
873  else blendu = redu > redv;
874 
875  if (blendu) {
876  // get next-higher u-res and reduce in u
877  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
878  FaceData* src = static_cast<FaceData*>(psrc.get());
879  newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
880  }
881  else {
882  // get next-higher v-res and reduce in v
883  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
884  FaceData* src = static_cast<FaceData*>(psrc.get());
885  newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
886  }
887  }
888 
889  size_t tableNewMemUsed = 0;
890  face = _reductions.tryInsert(key, newface, tableNewMemUsed);
891  if (face != newface) {
892  delete newface;
893  }
894  else {
895  increaseMemUsed(newMemUsed + tableNewMemUsed);
896  }
897  return face;
898 }
899 
900 
901 void PtexReader::getPixel(int faceid, int u, int v,
902  float* result, int firstchan, int nchannelsArg)
903 {
904  memset(result, 0, sizeof(*result)*nchannelsArg);
905 
906  // clip nchannels against actual number available
907  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
908  if (nchannelsArg <= 0) return;
909 
910  // get raw pixel data
911  PtexPtr<PtexFaceData> data ( getData(faceid) );
912  void* pixel = alloca(_pixelsize);
913  data->getPixel(u, v, pixel);
914 
915  // adjust for firstchan offset
916  int datasize = DataSize(datatype());
917  if (firstchan)
918  pixel = (char*) pixel + datasize * firstchan;
919 
920  // convert/copy to result as needed
921  if (datatype() == dt_float)
922  memcpy(result, pixel, datasize * nchannelsArg);
923  else
924  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
925 }
926 
927 
928 void PtexReader::getPixel(int faceid, int u, int v,
929  float* result, int firstchan, int nchannelsArg,
930  Ptex::Res res)
931 {
932  memset(result, 0, nchannelsArg);
933 
934  // clip nchannels against actual number available
935  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
936  if (nchannelsArg <= 0) return;
937 
938  // get raw pixel data
939  PtexPtr<PtexFaceData> data ( getData(faceid, res) );
940  void* pixel = alloca(_pixelsize);
941  data->getPixel(u, v, pixel);
942 
943  // adjust for firstchan offset
944  int datasize = DataSize(datatype());
945  if (firstchan)
946  pixel = (char*) pixel + datasize * firstchan;
947 
948  // convert/copy to result as needed
949  if (datatype() == dt_float)
950  memcpy(result, pixel, datasize * nchannelsArg);
951  else
952  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
953 }
954 
955 
958  size_t& newMemUsed)
959 {
960  // allocate a new face and reduce image
961  DataType dt = r->datatype();
962  int nchan = r->nchannels();
963  int memsize = _pixelsize * newres.size();
964  PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
965  newMemUsed = sizeof(PackedFace) + memsize;
966  // reduce and copy into new face
967  reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
968  pf->_data, _pixelsize * newres.u(), dt, nchan);
969  return pf;
970 }
971 
972 
973 
975 {
976  // must make a new constant face (even though it's identical to this one)
977  // because it will be owned by a different reduction level
978  // and will therefore have a different parent
980  newMemUsed = sizeof(ConstantFace) + _pixelsize;
981  memcpy(pf->_data, _data, _pixelsize);
982  return pf;
983 }
984 
985 
988  size_t& newMemUsed)
989 {
990  /* Tiled reductions should generally only be anisotropic (just u
991  or v, not both) since isotropic reductions are precomputed and
992  stored on disk. (This function should still work for isotropic
993  reductions though.)
994 
995  In the anisotropic case, the number of tiles should be kept the
996  same along the direction not being reduced in order to preserve
997  the laziness of the file access. In contrast, if reductions
998  were not tiled, then any reduction would read all the tiles and
999  defeat the purpose of tiling.
1000  */
1001 
1002  // keep new face local until fully initialized
1003  FaceData* newface = 0;
1004 
1005  // don't tile triangle reductions (too complicated)
1006  Res newtileres;
1007  bool isTriangle = r->_header.meshtype == mt_triangle;
1008  if (isTriangle) {
1009  newtileres = newres;
1010  }
1011  else {
1012  // propagate the tile res to the reduction
1013  newtileres = _tileres;
1014  // but make sure tile isn't larger than the new face!
1015  if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1016  if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1017  }
1018 
1019 
1020  // determine how many tiles we will have on the reduction
1021  int newntiles = newres.ntiles(newtileres);
1022 
1023  if (newntiles == 1) {
1024  // no need to keep tiling, reduce tiles into a single face
1025  // first, get all tiles and check if they are constant (with the same value)
1026  PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1027  bool allConstant = true;
1028  for (int i = 0; i < _ntiles; i++) {
1029  PtexFaceData* tile = tiles[i] = getTile(i);
1030  allConstant = (allConstant && tile->isConstant() &&
1031  (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1032  _pixelsize))));
1033  }
1034  if (allConstant) {
1035  // allocate a new constant face
1036  newface = new ConstantFace(_pixelsize);
1037  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1038  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1039  }
1040  else if (isTriangle) {
1041  // reassemble all tiles into temporary contiguous image
1042  // (triangle reduction doesn't work on tiles)
1043  int tileures = _tileres.u();
1044  int tilevres = _tileres.v();
1045  int sstride = _pixelsize * tileures;
1046  int dstride = sstride * _ntilesu;
1047  int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1048 
1049  char* tmp = new char [_ntiles * _tileres.size() * _pixelsize];
1050  char* tmpptr = tmp;
1051  for (int i = 0; i < _ntiles;) {
1052  PtexFaceData* tile = tiles[i];
1053  if (tile->isConstant())
1054  PtexUtils::fill(tile->getData(), tmpptr, dstride,
1055  tileures, tilevres, _pixelsize);
1056  else
1057  PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1058  i++;
1059  tmpptr += (i%_ntilesu) ? sstride : dstepv;
1060  }
1061 
1062  // allocate a new packed face
1063  int memsize = _pixelsize * newres.size();
1064  newface = new PackedFace(newres, _pixelsize, memsize);
1065  newMemUsed = sizeof(PackedFace) + memsize;
1066  // reduce and copy into new face
1067  reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1068  newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1069 
1070  delete [] tmp;
1071  }
1072  else {
1073  // allocate a new packed face
1074  int memsize = _pixelsize * newres.size();
1075  newface = new PackedFace(newres, _pixelsize, memsize);
1076  newMemUsed = sizeof(PackedFace) + memsize;
1077 
1078  int tileures = _tileres.u();
1079  int tilevres = _tileres.v();
1080  int sstride = _pixelsize * tileures;
1081  int dstride = _pixelsize * newres.u();
1082  int dstepu = dstride/_ntilesu;
1083  int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1084 
1085  char* dst = (char*) newface->getData();
1086  for (int i = 0; i < _ntiles;) {
1087  PtexFaceData* tile = tiles[i];
1088  if (tile->isConstant())
1089  PtexUtils::fill(tile->getData(), dst, dstride,
1090  newres.u()/_ntilesu, newres.v()/_ntilesv,
1091  _pixelsize);
1092  else
1093  reducefn(tile->getData(), sstride, tileures, tilevres,
1094  dst, dstride, _dt, _nchan);
1095  i++;
1096  dst += (i%_ntilesu) ? dstepu : dstepv;
1097  }
1098  }
1099  // release the tiles
1100  for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1101  }
1102  else {
1103  // otherwise, tile the reduced face
1104  TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
1105  newface = tf;
1106  newMemUsed = tf->memUsed();
1107  }
1108  return newface;
1109 }
1110 
1111 
1112 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1113 {
1114  int tileu = ui >> _tileres.ulog2;
1115  int tilev = vi >> _tileres.vlog2;
1116  PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1117  tile->getPixel(ui - (tileu<<_tileres.ulog2),
1118  vi - (tilev<<_tileres.vlog2), result);
1119 }
1120 
1121 
1122 
1124 {
1125  FaceData*& face = _tiles[tile];
1126  if (face) {
1127  return face;
1128  }
1129 
1130  // first, get all parent tiles for this tile
1131  // and check if they are constant (with the same value)
1132  int pntilesu = _parentface->ntilesu();
1133  int pntilesv = _parentface->ntilesv();
1134  int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1135  int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1136 
1137  int ntilesval = nu*nv; // num parent tiles for this tile
1138  PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
1139  bool allConstant = true;
1140  int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1141  for (int i = 0; i < ntilesval;) {
1142  PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
1143  allConstant = (allConstant && tileval->isConstant() &&
1144  (i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
1145  _pixelsize))));
1146  i++;
1147  ptile += (i%nu)? 1 : pntilesu - nu + 1;
1148  }
1149 
1150  FaceData* newface = 0;
1151  size_t newMemUsed = 0;
1152  if (allConstant) {
1153  // allocate a new constant face
1154  newface = new ConstantFace(_pixelsize);
1155  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1156  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1157  }
1158  else {
1159  // allocate a new packed face for the tile
1160  int memsize = _pixelsize*_tileres.size();
1161  newface = new PackedFace(_tileres, _pixelsize, memsize);
1162  newMemUsed = sizeof(PackedFace) + memsize;
1163 
1164  // generate reduction from parent tiles
1165  int ptileures = _parentface->tileres().u();
1166  int ptilevres = _parentface->tileres().v();
1167  int sstride = ptileures * _pixelsize;
1168  int dstride = _tileres.u() * _pixelsize;
1169  int dstepu = dstride/nu;
1170  int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1171 
1172  char* dst = (char*) newface->getData();
1173  for (int i = 0; i < ntilesval;) {
1174  PtexFaceData* tileval = tiles[i];
1175  if (tileval->isConstant())
1176  PtexUtils::fill(tileval->getData(), dst, dstride,
1177  _tileres.u()/nu, _tileres.v()/nv,
1178  _pixelsize);
1179  else
1180  _reducefn(tileval->getData(), sstride, ptileures, ptilevres,
1181  dst, dstride, _dt, _nchan);
1182  i++;
1183  dst += (i%nu) ? dstepu : dstepv;
1184  }
1185  }
1186 
1187  if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
1188  delete newface;
1189  }
1190  else {
1191  _reader->increaseMemUsed(newMemUsed);
1192  }
1193 
1194  return face;
1195 }
1196 
const uint32_t Magic
Definition: PtexIO.h:104
const int EditMetaDataHeaderSize
Definition: PtexIO.h:110
const int FaceDataHeaderSize
Definition: PtexIO.h:108
const int ExtHeaderSize
Definition: PtexIO.h:106
const int EditFaceDataHeaderSize
Definition: PtexIO.h:109
const int AllocaMax
Definition: PtexIO.h:116
const int HeaderSize
Definition: PtexIO.h:105
const int LevelInfoSize
Definition: PtexIO.h:107
const int BlockSize
Definition: PtexIO.h:114
bool LittleEndian()
Definition: PtexIO.h:119
@ et_editfacedata
Definition: PtexIO.h:92
@ et_editmetadata
Definition: PtexIO.h:92
@ enc_diffzipped
Definition: PtexIO.h:81
@ enc_zipped
Definition: PtexIO.h:81
@ enc_constant
Definition: PtexIO.h:81
@ enc_tiled
Definition: PtexIO.h:81
Platform-specific classes, functions, and includes.
off_t FilePos
Definition: PtexPlatform.h:101
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:286
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:280
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:123
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
Public API classes for reading, writing, caching, and filtering Ptex files.
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:43
bool trylock()
Definition: PtexPlatform.h:144
void unlock()
Definition: PtexPlatform.h:145
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:658
virtual void reportError(const char *error)=0
Per-face texture data accessor.
Definition: Ptexture.h:406
virtual void * getData()=0
Access the data from this data block.
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
virtual bool isConstant()=0
True if this data block is constant.
Value get(Key &key)
Definition: PtexHashMap.h:203
void clear()
Definition: PtexHashMap.h:195
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition: PtexHashMap.h:224
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:619
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
virtual const char * lastError()=0
Return the last error message encountered.
virtual Handle open(const char *path)=0
Open a file in read mode.
virtual bool close(Handle handle)=0
Close a file.
Meta data accessor.
Definition: Ptexture.h:328
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1032
T * get() const
Get pointer value.
Definition: Ptexture.h:1048
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:974
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
std::vector< FilePos > offsets
Definition: PtexReader.h:523
std::vector< FaceDataHeader > fdh
Definition: PtexReader.h:522
std::vector< FaceData * > faces
Definition: PtexReader.h:524
size_t memUsed()
Definition: PtexReader.h:537
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 * _reader
Definition: PtexReader.h:338
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
Entry * getEntry(int index)
Definition: PtexReader.cpp:351
std::vector< Entry * > _entries
Definition: PtexReader.h:341
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:957
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:987
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
std::vector< FaceDataHeader > _fdh
Definition: PtexReader.h:493
void readTile(int tile, FaceData *&data)
Definition: PtexReader.cpp:643
std::vector< FilePos > _offsets
Definition: PtexReader.h:494
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
void readLevelInfo()
Definition: PtexReader.cpp:306
ReductionMap _reductions
Definition: PtexReader.h:713
bool reopenFP()
Definition: PtexReader.cpp:248
DataType datatype() const
Definition: PtexReader.h:113
void readEditFaceData()
Definition: PtexReader.cpp:510
bool _premultiply
Definition: PtexReader.h:641
FilePos _constdatapos
Definition: PtexReader.h:651
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:422
uint8_t * getConstData()
Definition: PtexReader.h:579
void readFaceInfo()
Definition: PtexReader.cpp:285
std::string _path
Definition: PtexReader.h:647
uint8_t * _constdata
Definition: PtexReader.h:659
std::vector< FilePos > _levelpos
Definition: PtexReader.h:666
void readEditData()
Definition: PtexReader.cpp:476
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:901
std::vector< FaceEdit > _faceedits
Definition: PtexReader.h:683
FaceData * errorData(bool deleteOnRelease=false)
Definition: PtexReader.h:600
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexReader.h:56
void increaseMemUsed(size_t amount)
Definition: PtexReader.h:71
void purge()
Definition: PtexReader.cpp:115
FilePos _editdatapos
Definition: PtexReader.h:657
FilePos tell()
Definition: PtexReader.h:557
virtual ~PtexReader()
Definition: PtexReader.cpp:93
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.h:580
bool _hasEdits
Definition: PtexReader.h:661
bool _needToOpen
Definition: PtexReader.h:643
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition: PtexReader.h:605
void readConstData()
Definition: PtexReader.cpp:327
virtual PtexMetaData * getMetaData()
Access meta data.
Definition: PtexReader.cpp:343
bool needToOpen() const
Definition: PtexReader.h:57
ExtHeader _extheader
Definition: PtexReader.h:649
FilePos _leveldatapos
Definition: PtexReader.h:653
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition: PtexReader.cpp:719
PtexErrorHandler * _err
Definition: PtexReader.h:640
void readEditMetaData()
Definition: PtexReader.cpp:541
FilePos _faceinfopos
Definition: PtexReader.h:650
std::vector< LevelInfo > _levelinfo
Definition: PtexReader.h:665
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexReader.cpp:71
z_stream_s _zstream
Definition: PtexReader.h:716
PtexInputHandler * _io
Definition: PtexReader.h:639
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition: PtexReader.cpp:275
FilePos _metadatapos
Definition: PtexReader.h:654
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:448
void closeFP()
Definition: PtexReader.cpp:238
int _pixelsize
Definition: PtexReader.h:658
bool _pendingPurge
Definition: PtexReader.h:644
Mutex readlock
Definition: PtexReader.h:637
Level * getLevel(int levelid)
Definition: PtexReader.h:572
void readFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.cpp:635
FilePos _levelinfopos
Definition: PtexReader.h:652
FilePos _lmdheaderpos
Definition: PtexReader.h:655
int nchannels() const
Definition: PtexReader.h:114
FilePos _lmddatapos
Definition: PtexReader.h:656
void prune()
Definition: PtexReader.cpp:104
std::vector< uint32_t > _rfaceids
Definition: PtexReader.h:664
std::vector< MetaEdit > _metaedits
Definition: PtexReader.h:675
volatile size_t _memUsed
Definition: PtexReader.h:718
Header _header
Definition: PtexReader.h:648
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition: PtexReader.cpp:649
void seek(FilePos pos)
Definition: PtexReader.h:558
bool readBlock(void *data, int size, bool reportError=true)
Definition: PtexReader.cpp:556
MetaData * _metadata
Definition: PtexReader.h:660
std::vector< Level * > _levels
Definition: PtexReader.h:667
size_t _baseMemUsed
Definition: PtexReader.h:717
std::vector< FaceInfo > _faceinfo
Definition: PtexReader.h:663
PtexInputHandler::Handle _fp
Definition: PtexReader.h:645
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition: PtexReader.cpp:571
void readMetaData()
Definition: PtexReader.cpp:389
void logOpen()
Definition: PtexReader.h:72
void readLevel(int levelid, Level *&level)
Definition: PtexReader.cpp:603
std::vector< char > _errorPixel
Definition: PtexReader.h:714
FilePos _pos
Definition: PtexReader.h:646
bool open(const char *path, Ptex::String &error)
Definition: PtexReader.cpp:137
bool tryClose()
Definition: PtexReader.cpp:227
void setError(const char *error)
Definition: PtexReader.h:546
Interface for reading data from a ptex file.
Definition: Ptexture.h:457
virtual const char * path()=0
Path that file was opened with.
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition: PtexReader.cpp:59
Memory-managed string.
Definition: Ptexture.h:296
const char * c_str() const
Definition: Ptexture.h:304
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:630
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:333
T min(T a, T b)
Definition: PtexUtils.h:148
T max(T a, T b)
Definition: PtexUtils.h:151
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:271
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:366
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:422
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:406
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:438
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.h:185
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:579
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:189
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:130
DataType
Type of data stored in texture file.
Definition: Ptexture.h:72
@ dt_float
Single-precision (32-bit) floating point.
Definition: Ptexture.h:76
@ mt_triangle
Mesh is triangle-based.
Definition: Ptexture.h:67
@ mt_quad
Mesh is quad-based.
Definition: Ptexture.h:68
uint32_t faceid
Definition: PtexIO.h:94
FaceDataHeader fdh
Definition: PtexIO.h:96
FaceInfo faceinfo
Definition: PtexIO.h:95
uint32_t metadatazipsize
Definition: PtexIO.h:99
uint32_t metadatamemsize
Definition: PtexIO.h:100
uint64_t lmddatasize
Definition: PtexIO.h:71
uint64_t editdatapos
Definition: PtexIO.h:73
uint32_t lmdheadermemsize
Definition: PtexIO.h:70
uint32_t lmdheaderzipsize
Definition: PtexIO.h:69
uint64_t editdatasize
Definition: PtexIO.h:72
Encoding encoding() const
Definition: PtexIO.h:85
uint32_t blocksize() const
Definition: PtexIO.h:84
Definition: PtexIO.h:44
uint32_t metadatamemsize
Definition: PtexIO.h:60
uint32_t faceinfosize
Definition: PtexIO.h:54
uint16_t nlevels
Definition: PtexIO.h:51
uint16_t nchannels
Definition: PtexIO.h:50
uint32_t meshtype
Definition: PtexIO.h:47
uint32_t constdatasize
Definition: PtexIO.h:55
uint32_t levelinfosize
Definition: PtexIO.h:56
uint32_t extheadersize
Definition: PtexIO.h:53
uint32_t metadatazipsize
Definition: PtexIO.h:59
int pixelSize() const
Definition: PtexIO.h:61
int32_t alphachan
Definition: PtexIO.h:49
uint32_t magic
Definition: PtexIO.h:45
uint32_t nfaces
Definition: PtexIO.h:52
uint64_t leveldatasize
Definition: PtexIO.h:58
uint32_t version
Definition: PtexIO.h:46
bool hasAlpha() const
Definition: PtexIO.h:62
uint32_t levelheadersize
Definition: PtexIO.h:77
uint32_t nfaces
Definition: PtexIO.h:78
FaceDataHeader fdh
Definition: PtexReader.h:681
LargeMetaData * lmdData
Definition: PtexReader.h:290
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:229
Pixel resolution of a given texture.
Definition: Ptexture.h:159