Factorized funtions to read the eof offset dictionary of serialized trimeshes

metadata
Edgar Velazquez-Armendariz 2013-01-22 22:25:39 -05:00
parent e82a60e136
commit 2715f87613
2 changed files with 88 additions and 23 deletions

View File

@ -310,6 +310,23 @@ protected:
/// Load a Mitsuba compressed triangle mesh substream
void loadCompressed(Stream *stream, int idx = 0);
/**
* \brief Read the idx-th entry from the offset diccionary at the end of
* the stream, which has to be open already, given the file version tag.
* This function modifies the position of the stream.
*/
size_t readOffset(ref<Stream>& stream, short version, int idx) const;
/**
* \brief Read the entirety of the end-of-file offset dictionary from the
* already open stream, replacing the contents of the input vector.
* If the file is not large enough the function returns -1
* and does not modify the vector.
* This function modifies the position of the stream.
*/
int readOffsetDictionary(ref<Stream>& stream, short version,
std::vector<size_t>& outOffsets) const;
/// Prepare internal tables for sampling uniformly wrt. area
void prepareSamplingTable();
protected:

View File

@ -171,7 +171,6 @@ static void readHelper(Stream *stream, bool fileDoublePrecision,
}
}
void TriMesh::loadCompressed(Stream *_stream, int index) {
ref<Stream> stream = _stream;
@ -194,28 +193,9 @@ void TriMesh::loadCompressed(Stream *_stream, int index) {
Log(EError, "Encountered an incompatible file version!");
if (index != 0) {
size_t streamSize = stream->getSize();
/* Determine the position of the requested substream. This
is stored at the end of the file */
stream->seek(streamSize - sizeof(uint32_t));
uint32_t count = stream->readUInt();
if (index < 0 || index > (int) count) {
Log(EError, "Unable to unserialize mesh, "
"shape index is out of range! (requested %i out of 0..%i)",
index, count-1);
}
// Seek to the correct position
if (version == MTS_FILEFORMAT_VERSION_V4) {
stream->seek(stream->getSize() - sizeof(uint64_t) * (count-index) - sizeof(uint32_t));
stream->seek(stream->readSize());
} else {
stream->seek(stream->getSize() - sizeof(uint32_t) * (count-index + 1));
stream->seek(stream->readUInt());
}
stream->skip(sizeof(short) * 2);
const size_t offset = readOffset(stream, version, index);
stream->seek(offset);
stream->skip(sizeof(short) * 2); // Skip the header
}
stream = new ZStream(stream);
@ -282,6 +262,74 @@ void TriMesh::loadCompressed(Stream *_stream, int index) {
m_flipNormals = false;
}
size_t TriMesh::readOffset(ref<Stream>& stream, short version, int idx) const {
const size_t streamSize = stream->getSize();
/* Determine the position of the requested substream. This is stored
at the end of the file */
stream->seek(streamSize - sizeof(uint32_t));
uint32_t count = stream->readUInt();
if (idx < 0 || idx > (int) count) {
Log(EError, "Unable to unserialize mesh, "
"shape index is out of range! (requested %i out of 0..%i)",
idx, count-1);
}
// Seek to the correct position
if (version == MTS_FILEFORMAT_VERSION_V4) {
stream->seek(stream->getSize() - sizeof(uint64_t) * (count-idx) - sizeof(uint32_t));
return stream->readSize();
} else {
Assert(version == MTS_FILEFORMAT_VERSION_V3);
stream->seek(stream->getSize() - sizeof(uint32_t) * (count-idx + 1));
return stream->readUInt();
}
}
int TriMesh::readOffsetDictionary(ref<Stream>& stream, short version,
std::vector<size_t>& outOffsets) const {
const size_t streamSize = stream->getSize();
stream->seek(streamSize - sizeof(uint32_t));
const uint32_t count = stream->readUInt();
// Check if the stream is large enough to contain that number of meshes
const size_t minSize = sizeof(uint32_t) + count *
( 2*sizeof(uint16_t) // Header
+ sizeof(uint32_t) // Flags
+ sizeof(char) // Name
+ 2*sizeof(uint64_t) // Number of vertices and triangles
+ 3*sizeof(float) // One vertex
+ 3*sizeof(uint32_t)); // One triange
if (streamSize >= minSize) {
outOffsets.resize(count);
if (version == MTS_FILEFORMAT_VERSION_V4) {
stream->seek(stream->getSize() - sizeof(uint64_t) * count - sizeof(uint32_t));
if (typeid(size_t) == typeid(uint64_t)) {
stream->readArray(&outOffsets[0], count);
} else {
for (size_t i = 0; i < count; ++i) {
outOffsets[i] = static_cast<size_t>(stream->readSize());
}
}
} else {
stream->seek(stream->getSize() - sizeof(uint32_t) * (count + 1));
Assert(version == MTS_FILEFORMAT_VERSION_V3);
if (typeid(size_t) == typeid(uint32_t)) {
stream->readArray(&outOffsets[0], count);
} else {
for (size_t i = 0; i < count; ++i) {
outOffsets[i] = stream->readUInt();
}
}
}
return count;
} else {
Log(EDebug, "The serialized mesh does not contain a valid dictionary");
return -1;
}
}
TriMesh::~TriMesh() {
if (m_positions)
delete[] m_positions;