Ptex
PtexReader.cpp
Go to the documentation of this file.
1/*
2PTEX SOFTWARE
3Copyright 2014 Disney Enterprises, Inc. All rights reserved
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
22Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33OF 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
45namespace {
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
59PtexTexture* 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)),
86 _opens(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
137bool 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 }
172 if (!(_header.meshtype == mt_triangle || _header.meshtype == mt_quad)) {
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 }
180 _pixelsize = _header.pixelSize();
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));
190 readBlock(&_extheader, PtexUtils::min(uint32_t(ExtHeaderSize), _header.extheadersize));
191
192 // compute offsets of various blocks
193 FilePos pos = HeaderSize + _header.extheadersize;
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
200 _lmdheaderpos = pos; pos += _extheader.lmdheaderzipsize;
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)
205 _editdatapos = PtexUtils::max(FilePos(_extheader.editdatapos), pos);
206
207 // read basic file info
208 readFaceInfo();
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);
292 readZipBlock(&_faceinfo[0], _header.faceinfosize,
293 (int)(sizeof(FaceInfo)*nfaces));
294
295 // generate rfaceids
296 _rfaceids.resize(nfaces);
297 std::vector<uint32_t> faceids_r(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);
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];
334 readZipBlock(_constdata, _header.constdatasize, size);
335 if (_premultiply && _header.hasAlpha())
337 _header.nchannels, _header.alphachan);
338 increaseMemUsed(size);
339 }
340}
341
342
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();
379 _reader->increaseMemUsed(sizeof(LargeMetaData) + e->datasize);
380 _reader->seek(e->lmdPos);
381 _reader->readZipBlock(e->data, e->lmdZipSize, e->datasize);
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
402 if (_header.metadatamemsize)
404 _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
405
406 // read large meta data headers
407 if (_extheader.lmdheadermemsize)
409 _extheader.lmdheaderzipsize, _extheader.lmdheadermemsize, metaDataMemUsed);
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
422void 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
448void 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
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(),
528 _header.nchannels, _header.alphachan);
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
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
556bool 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
571bool 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
603void 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
635void 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
649void 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())
671 _header.nchannels, _header.alphachan);
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,
703 datatype(), _header.nchannels);
704 if (levelid==0 && _premultiply && _header.hasAlpha())
705 PtexUtils::multalpha(pf->data(), npixels, datatype(),
706 _header.nchannels, _header.alphachan);
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
719void 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
726void 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
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
901void 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
928void 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
1112void 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
AutoLock< Mutex > AutoMutex
Definition PtexMutex.h:51
Platform-specific classes, functions, and includes.
off_t FilePos
PTEX_INLINE void AtomicStore(T volatile *target, T value)
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Public API classes for reading, writing, caching, and filtering Ptex files.
Custom handler interface redirecting Ptex error messages.
Definition Ptexture.h:658
Per-face texture data accessor.
Definition Ptexture.h:406
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
virtual bool isConstant()=0
True if this data block is constant.
virtual void * getData()=0
Access the data from this data block.
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition Ptexture.h:619
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
ConstantFace(int pixelsize)
Definition PtexReader.h:403
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
FaceData(Res resArg)
Definition PtexReader.h:367
std::vector< FilePos > offsets
Definition PtexReader.h:523
std::vector< FaceDataHeader > fdh
Definition PtexReader.h:522
std::vector< FaceData * > faces
Definition PtexReader.h:524
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)
std::vector< Entry * > _entries
Definition PtexReader.h:341
PackedFace(Res resArg, int pixelsize, int size)
Definition PtexReader.h:379
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
std::vector< FaceData * > _tiles
Definition PtexReader.h:466
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
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)
std::vector< FilePos > _offsets
Definition PtexReader.h:494
TiledFaceBase * _parentface
Definition PtexReader.h:515
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
PtexUtils::ReduceFn * _reducefn
Definition PtexReader.h:516
void readLevelInfo()
ReductionMap _reductions
Definition PtexReader.h:713
bool reopenFP()
DataType datatype() const
Definition PtexReader.h:113
void readEditFaceData()
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)
void readFaceInfo()
std::string _path
Definition PtexReader.h:647
uint8_t * _constdata
Definition PtexReader.h:659
std::vector< FilePos > _levelpos
Definition PtexReader.h:666
void readEditData()
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
std::vector< FaceEdit > _faceedits
Definition PtexReader.h:683
volatile size_t _opens
Definition PtexReader.h:719
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
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.h:580
FilePos _editdatapos
Definition PtexReader.h:657
FilePos tell()
Definition PtexReader.h:557
Level * getLevel(int levelid)
Definition PtexReader.h:572
FaceData * errorData(bool deleteOnRelease=false)
Definition PtexReader.h:600
virtual ~PtexReader()
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()
virtual PtexMetaData * getMetaData()
Access meta data.
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.
PtexErrorHandler * _err
Definition PtexReader.h:640
void readEditMetaData()
FilePos _faceinfopos
Definition PtexReader.h:650
std::vector< LevelInfo > _levelinfo
Definition PtexReader.h:665
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
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.
FilePos _metadatapos
Definition PtexReader.h:654
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
void closeFP()
bool _pendingPurge
Definition PtexReader.h:644
Mutex readlock
Definition PtexReader.h:637
void readFace(int levelid, Level *level, int faceid, Res res)
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
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
DefaultInputHandler _defaultIo
Definition PtexReader.h:638
volatile size_t _blockReads
Definition PtexReader.h:720
Header _header
Definition PtexReader.h:648
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
void seek(FilePos pos)
Definition PtexReader.h:558
bool readBlock(void *data, int size, bool reportError=true)
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)
void readMetaData()
void logOpen()
Definition PtexReader.h:72
void readLevel(int levelid, Level *&level)
std::vector< char > _errorPixel
Definition PtexReader.h:714
uint8_t * getConstData()
Definition PtexReader.h:579
FilePos _pos
Definition PtexReader.h:646
bool open(const char *path, Ptex::String &error)
bool tryClose()
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.
Memory-managed string.
Definition Ptexture.h:296
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
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)
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
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)
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
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
Encoding encoding() const
Definition PtexIO.h:85
uint32_t blocksize() const
Definition PtexIO.h:84
uint32_t meshtype
Definition PtexIO.h:47
uint32_t extheadersize
Definition PtexIO.h:53
uint32_t levelheadersize
Definition PtexIO.h:77
uint32_t nfaces
Definition PtexIO.h:78
FaceDataHeader fdh
Definition PtexReader.h:681
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