Ptex: PtexReader.cpp Source File

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
57 PTEX_NAMESPACE_BEGIN
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
71PtexReader::PtexReader(bool premultiply, PtexInputHandler* io, PtexErrorHandler* err)
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
93PtexReader::~PtexReader()
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
104 void PtexReader::prune()
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();
111 _memUsed = _baseMemUsed;
112}
113
114
115 void PtexReader::purge()
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));
156 readBlock(&_header, HeaderSize);
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();
209 readConstData();
210 readLevelInfo();
211 readEditData();
212 _baseMemUsed = _memUsed;
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
227 bool PtexReader::tryClose()
228{
229 if (_fp) {
230 if (!readlock.trylock()) return false;
231 closeFP();
232 readlock.unlock();
233 }
234 return true;
235}
236
237
238 void PtexReader::closeFP()
239{
240 if (_fp) {
241 _io->close(_fp);
242 _fp = 0;
243 }
244 inflateEnd(&_zstream);
245}
246
247
248 bool PtexReader::reopenFP()
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
275 const Ptex::FaceInfo& PtexReader::getFaceInfo(int faceid)
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
285 void PtexReader::readFaceInfo()
286{
287 if (_faceinfo.empty()) {
288 // read compressed face info block
289 seek(_faceinfopos);
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);
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
306 void PtexReader::readLevelInfo()
307{
308 if (_levelinfo.empty()) {
309 // read level info block
310 seek(_levelinfopos);
311 _levelinfo.resize(_header.nlevels);
312 readBlock(&_levelinfo[0], LevelInfoSize*_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
327 void PtexReader::readConstData()
328{
329 if (!_constdata) {
330 // read compressed constant data block
331 seek(_constdatapos);
332 int size = _pixelsize * _header.nfaces;
333 _constdata = new uint8_t[size];
334 readZipBlock(_constdata, _header.constdatasize, size);
335 if (_premultiply && _header.hasAlpha())
336 PtexUtils::multalpha(_constdata, _header.nfaces, datatype(),
337 _header.nchannels, _header.alphachan);
338 increaseMemUsed(size);
339 }
340}
341
342
343 PtexMetaData* PtexReader::getMetaData()
344{
345 if (!_metadata) readMetaData();
346 return _metadata;
347}
348
349
350 PtexReader::MetaData::Entry*
351PtexReader::MetaData::getEntry(int index)
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
389 void PtexReader::readMetaData()
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)
403 readMetaDataBlock(newmeta, _metadatapos,
404 _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
405
406 // read large meta data headers
407 if (_extheader.lmdheadermemsize)
408 readLargeMetaDataHeaders(newmeta, _lmdheaderpos,
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
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
476 void PtexReader::readEditData()
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
510 void PtexReader::readEditFaceData()
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(),
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
541 void PtexReader::readEditMetaData()
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]);
617 readZipBlock(&newlevel->fdh[0], l.levelheadersize, FaceDataHeaderSize * l.nfaces);
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
643 void PtexReader::TiledFace::readTile(int tile, FaceData*& data)
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 {
665 ConstantFace* cf = new ConstantFace(_pixelsize);
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(),
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
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
775 PtexFaceData* PtexReader::getData(int faceid)
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
956 PtexReader::FaceData*
957PtexReader::PackedFace::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
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
974 PtexReader::FaceData* PtexReader::ConstantFace::reduce(PtexReader*, Res, PtexUtils::ReduceFn, size_t& newMemUsed)
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
979 ConstantFace* pf = new ConstantFace(_pixelsize);
980 newMemUsed = sizeof(ConstantFace) + _pixelsize;
981 memcpy(pf->_data, _data, _pixelsize);
982 return pf;
983}
984
985
986 PtexReader::FaceData*
987PtexReader::TiledFaceBase::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
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
1123 PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
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
1197 PTEX_NAMESPACE_END
Magic
const uint32_t Magic
Definition PtexIO.h:104
EditMetaDataHeaderSize
const int EditMetaDataHeaderSize
Definition PtexIO.h:110
FaceDataHeaderSize
const int FaceDataHeaderSize
Definition PtexIO.h:108
ExtHeaderSize
const int ExtHeaderSize
Definition PtexIO.h:106
EditFaceDataHeaderSize
const int EditFaceDataHeaderSize
Definition PtexIO.h:109
AllocaMax
const int AllocaMax
Definition PtexIO.h:116
HeaderSize
const int HeaderSize
Definition PtexIO.h:105
LevelInfoSize
const int LevelInfoSize
Definition PtexIO.h:107
BlockSize
const int BlockSize
Definition PtexIO.h:114
LittleEndian
bool LittleEndian()
Definition PtexIO.h:119
et_editfacedata
@ et_editfacedata
Definition PtexIO.h:92
et_editmetadata
@ et_editmetadata
Definition PtexIO.h:92
enc_diffzipped
@ enc_diffzipped
Definition PtexIO.h:81
enc_zipped
@ enc_zipped
Definition PtexIO.h:81
enc_constant
@ enc_constant
Definition PtexIO.h:81
enc_tiled
@ enc_tiled
Definition PtexIO.h:81
PtexPlatform.h
Platform-specific classes, functions, and includes.
FilePos
off_t FilePos
Definition PtexPlatform.h:101
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition PtexPlatform.h:286
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition PtexPlatform.h:280
PtexReader.h
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition PtexUtils.cpp:123
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
AutoLock
Automatically acquire and release lock within enclosing scope.
Definition PtexMutex.h:43
Mutex::trylock
bool trylock()
Definition PtexPlatform.h:144
Mutex::unlock
void unlock()
Definition PtexPlatform.h:145
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition Ptexture.h:658
PtexFaceData
Per-face texture data accessor.
Definition Ptexture.h:406
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
PtexHashMap::get
Value get(Key &key)
Definition PtexHashMap.h:203
PtexHashMap::clear
void clear()
Definition PtexHashMap.h:195
PtexHashMap::tryInsert
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition PtexHashMap.h:224
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition Ptexture.h:619
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexMetaData
Meta data accessor.
Definition Ptexture.h:328
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition Ptexture.h:1032
PtexPtr::get
T * get() const
Get pointer value.
Definition Ptexture.h:1048
PtexReader::ConstDataPtr
Definition PtexReader.h:345
PtexReader::ConstantFace
Definition PtexReader.h:401
PtexReader::ConstantFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:974
PtexReader::FaceData
Definition PtexReader.h:365
PtexReader::FaceData::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
PtexReader::Level
Definition PtexReader.h:520
PtexReader::Level::offsets
std::vector< FilePos > offsets
Definition PtexReader.h:523
PtexReader::Level::fdh
std::vector< FaceDataHeader > fdh
Definition PtexReader.h:522
PtexReader::Level::faces
std::vector< FaceData * > faces
Definition PtexReader.h:524
PtexReader::Level::memUsed
size_t memUsed()
Definition PtexReader.h:537
PtexReader::MetaData::LargeMetaData
Definition PtexReader.h:273
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition PtexReader.h:278
PtexReader::MetaData
Definition PtexReader.h:120
PtexReader::MetaData::selfDataSize
size_t selfDataSize()
Definition PtexReader.h:266
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition PtexReader.h:246
PtexReader::MetaData::_reader
PtexReader * _reader
Definition PtexReader.h:338
PtexReader::MetaData::addLmdEntry
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize, size_t &metaDataMemUsed)
Definition PtexReader.h:255
PtexReader::MetaData::getEntry
Entry * getEntry(int index)
Definition PtexReader.cpp:351
PtexReader::MetaData::_entries
std::vector< Entry * > _entries
Definition PtexReader.h:341
PtexReader::PackedFace
Definition PtexReader.h:377
PtexReader::PackedFace::data
void * data()
Definition PtexReader.h:382
PtexReader::PackedFace::_data
char * _data
Definition PtexReader.h:398
PtexReader::PackedFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:957
PtexReader::ReductionKey
Definition PtexReader.h:685
PtexReader::TiledFaceBase::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:987
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition PtexReader.h:464
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition PtexReader.cpp:1112
PtexReader::TiledFace
Definition PtexReader.h:470
PtexReader::TiledFace::_fdh
std::vector< FaceDataHeader > _fdh
Definition PtexReader.h:493
PtexReader::TiledFace::memUsed
size_t memUsed()
Definition PtexReader.h:486
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition PtexReader.cpp:643
PtexReader::TiledFace::_offsets
std::vector< FilePos > _offsets
Definition PtexReader.h:494
PtexReader::TiledReducedFace
Definition PtexReader.h:498
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition PtexReader.cpp:1123
PtexReader::TiledReducedFace::memUsed
size_t memUsed()
Definition PtexReader.h:512
PtexReader
Definition PtexReader.h:52
PtexReader::readLevelInfo
void readLevelInfo()
Definition PtexReader.cpp:306
PtexReader::_reductions
ReductionMap _reductions
Definition PtexReader.h:713
PtexReader::reopenFP
bool reopenFP()
Definition PtexReader.cpp:248
PtexReader::datatype
DataType datatype() const
Definition PtexReader.h:113
PtexReader::readEditFaceData
void readEditFaceData()
Definition PtexReader.cpp:510
PtexReader::_premultiply
bool _premultiply
Definition PtexReader.h:641
PtexReader::_constdatapos
FilePos _constdatapos
Definition PtexReader.h:651
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:422
PtexReader::readFaceInfo
void readFaceInfo()
Definition PtexReader.cpp:285
PtexReader::_path
std::string _path
Definition PtexReader.h:647
PtexReader::_constdata
uint8_t * _constdata
Definition PtexReader.h:659
PtexReader::_levelpos
std::vector< FilePos > _levelpos
Definition PtexReader.h:666
PtexReader::readEditData
void readEditData()
Definition PtexReader.cpp:476
PtexReader::getPixel
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
Definition PtexReader.cpp:901
PtexReader::_faceedits
std::vector< FaceEdit > _faceedits
Definition PtexReader.h:683
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition PtexReader.h:56
PtexReader::increaseMemUsed
void increaseMemUsed(size_t amount)
Definition PtexReader.h:71
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.h:580
PtexReader::purge
void purge()
Definition PtexReader.cpp:115
PtexReader::_editdatapos
FilePos _editdatapos
Definition PtexReader.h:657
PtexReader::tell
FilePos tell()
Definition PtexReader.h:557
PtexReader::getLevel
Level * getLevel(int levelid)
Definition PtexReader.h:572
PtexReader::errorData
FaceData * errorData(bool deleteOnRelease=false)
Definition PtexReader.h:600
PtexReader::~PtexReader
virtual ~PtexReader()
Definition PtexReader.cpp:93
PtexReader::_hasEdits
bool _hasEdits
Definition PtexReader.h:661
PtexReader::_needToOpen
bool _needToOpen
Definition PtexReader.h:643
PtexReader::computeOffsets
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition PtexReader.h:605
PtexReader::readConstData
void readConstData()
Definition PtexReader.cpp:327
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition PtexReader.cpp:343
PtexReader::needToOpen
bool needToOpen() const
Definition PtexReader.h:57
PtexReader::_extheader
ExtHeader _extheader
Definition PtexReader.h:649
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition PtexReader.h:653
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition PtexReader.cpp:719
PtexReader::_err
PtexErrorHandler * _err
Definition PtexReader.h:640
PtexReader::readEditMetaData
void readEditMetaData()
Definition PtexReader.cpp:541
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition PtexReader.h:650
PtexReader::_levelinfo
std::vector< LevelInfo > _levelinfo
Definition PtexReader.h:665
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition PtexReader.cpp:71
PtexReader::_zstream
z_stream_s _zstream
Definition PtexReader.h:716
PtexReader::_io
PtexInputHandler * _io
Definition PtexReader.h:639
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition PtexReader.cpp:275
PtexReader::_metadatapos
FilePos _metadatapos
Definition PtexReader.h:654
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:448
PtexReader::closeFP
void closeFP()
Definition PtexReader.cpp:238
PtexReader::_pixelsize
int _pixelsize
Definition PtexReader.h:658
PtexReader::_pendingPurge
bool _pendingPurge
Definition PtexReader.h:644
PtexReader::readlock
Mutex readlock
Definition PtexReader.h:637
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.cpp:635
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition PtexReader.h:652
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition PtexReader.h:655
PtexReader::nchannels
int nchannels() const
Definition PtexReader.h:114
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition PtexReader.h:656
PtexReader::prune
void prune()
Definition PtexReader.cpp:104
PtexReader::_rfaceids
std::vector< uint32_t > _rfaceids
Definition PtexReader.h:664
PtexReader::_metaedits
std::vector< MetaEdit > _metaedits
Definition PtexReader.h:675
PtexReader::_memUsed
volatile size_t _memUsed
Definition PtexReader.h:718
PtexReader::_header
Header _header
Definition PtexReader.h:648
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition PtexReader.cpp:649
PtexReader::seek
void seek(FilePos pos)
Definition PtexReader.h:558
PtexReader::readBlock
bool readBlock(void *data, int size, bool reportError=true)
Definition PtexReader.cpp:556
PtexReader::_metadata
MetaData * _metadata
Definition PtexReader.h:660
PtexReader::_levels
std::vector< Level * > _levels
Definition PtexReader.h:667
PtexReader::_baseMemUsed
size_t _baseMemUsed
Definition PtexReader.h:717
PtexReader::_faceinfo
std::vector< FaceInfo > _faceinfo
Definition PtexReader.h:663
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition PtexReader.h:645
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition PtexReader.cpp:571
PtexReader::readMetaData
void readMetaData()
Definition PtexReader.cpp:389
PtexReader::logOpen
void logOpen()
Definition PtexReader.h:72
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition PtexReader.cpp:603
PtexReader::_errorPixel
std::vector< char > _errorPixel
Definition PtexReader.h:714
PtexReader::getConstData
uint8_t * getConstData()
Definition PtexReader.h:579
PtexReader::_pos
FilePos _pos
Definition PtexReader.h:646
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition PtexReader.cpp:137
PtexReader::tryClose
bool tryClose()
Definition PtexReader.cpp:227
PtexReader::setError
void setError(const char *error)
Definition PtexReader.h:546
PtexReader::_ok
bool _ok
Definition PtexReader.h:642
PtexTexture
Interface for reading data from a ptex file.
Definition Ptexture.h:457
PtexTexture::path
virtual const char * path()=0
Path that file was opened with.
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition PtexReader.cpp:59
Ptex::String
Memory-managed string.
Definition Ptexture.h:296
PTEX_NAMESPACE_BEGIN
Definition PtexSeparableKernel.cpp:42
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition PtexUtils.cpp:630
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:333
PtexUtils::min
T min(T a, T b)
Definition PtexUtils.h:148
PtexUtils::max
T max(T a, T b)
Definition PtexUtils.h:151
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition PtexUtils.cpp:271
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:366
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition PtexUtils.cpp:422
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:406
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition PtexUtils.cpp:438
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition PtexUtils.h:185
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition PtexUtils.cpp:579
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:189
EditFaceDataHeader
Definition PtexIO.h:93
EditFaceDataHeader::faceid
uint32_t faceid
Definition PtexIO.h:94
EditFaceDataHeader::fdh
FaceDataHeader fdh
Definition PtexIO.h:96
EditFaceDataHeader::faceinfo
FaceInfo faceinfo
Definition PtexIO.h:95
EditMetaDataHeader
Definition PtexIO.h:98
EditMetaDataHeader::metadatazipsize
uint32_t metadatazipsize
Definition PtexIO.h:99
EditMetaDataHeader::metadatamemsize
uint32_t metadatamemsize
Definition PtexIO.h:100
ExtHeader
Definition PtexIO.h:64
ExtHeader::lmddatasize
uint64_t lmddatasize
Definition PtexIO.h:71
ExtHeader::editdatapos
uint64_t editdatapos
Definition PtexIO.h:73
ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition PtexIO.h:70
ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition PtexIO.h:69
ExtHeader::editdatasize
uint64_t editdatasize
Definition PtexIO.h:72
FaceDataHeader
Definition PtexIO.h:82
FaceDataHeader::encoding
Encoding encoding() const
Definition PtexIO.h:85
FaceDataHeader::blocksize
uint32_t blocksize() const
Definition PtexIO.h:84
Header
Definition PtexIO.h:44
Header::metadatamemsize
uint32_t metadatamemsize
Definition PtexIO.h:60
Header::faceinfosize
uint32_t faceinfosize
Definition PtexIO.h:54
Header::nlevels
uint16_t nlevels
Definition PtexIO.h:51
Header::nchannels
uint16_t nchannels
Definition PtexIO.h:50
Header::meshtype
uint32_t meshtype
Definition PtexIO.h:47
Header::constdatasize
uint32_t constdatasize
Definition PtexIO.h:55
Header::levelinfosize
uint32_t levelinfosize
Definition PtexIO.h:56
Header::extheadersize
uint32_t extheadersize
Definition PtexIO.h:53
Header::metadatazipsize
uint32_t metadatazipsize
Definition PtexIO.h:59
Header::pixelSize
int pixelSize() const
Definition PtexIO.h:61
Header::alphachan
int32_t alphachan
Definition PtexIO.h:49
Header::magic
uint32_t magic
Definition PtexIO.h:45
Header::nfaces
uint32_t nfaces
Definition PtexIO.h:52
Header::leveldatasize
uint64_t leveldatasize
Definition PtexIO.h:58
Header::version
uint32_t version
Definition PtexIO.h:46
Header::hasAlpha
bool hasAlpha() const
Definition PtexIO.h:62
LevelInfo
Definition PtexIO.h:75
LevelInfo::levelheadersize
uint32_t levelheadersize
Definition PtexIO.h:77
LevelInfo::nfaces
uint32_t nfaces
Definition PtexIO.h:78
PtexReader::FaceEdit
Definition PtexReader.h:678
PtexReader::FaceEdit::pos
FilePos pos
Definition PtexReader.h:679
PtexReader::FaceEdit::faceid
int faceid
Definition PtexReader.h:680
PtexReader::FaceEdit::fdh
FaceDataHeader fdh
Definition PtexReader.h:681
PtexReader::MetaData::Entry
Definition PtexReader.h:284
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition PtexReader.h:291
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition PtexReader.h:292
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition PtexReader.h:289
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition PtexReader.h:287
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition PtexReader.h:290
PtexReader::MetaData::Entry::data
char * data
Definition PtexReader.h:288
PtexReader::MetaEdit
Definition PtexReader.h:670
PtexReader::MetaEdit::zipsize
int zipsize
Definition PtexReader.h:672
PtexReader::MetaEdit::memsize
int memsize
Definition PtexReader.h:673
PtexReader::MetaEdit::pos
FilePos pos
Definition PtexReader.h:671
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition Ptexture.h:229
Ptex::Res
Pixel resolution of a given texture.
Definition Ptexture.h:159