Factorized funtions to read the eof offset dictionary of serialized trimeshes
parent
e82a60e136
commit
2715f87613
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue