//--------------------------------------------------------------------- std::vector<OgreMeshDeserializer::VertexElement> OgreMeshDeserializer::readGeometryVertexDeclaration() { std::vector<OgreMeshDeserializer::VertexElement> elements; // Find optional geometry streams if (!m_stream.eof()) { unsigned short streamID = readChunk(m_stream); while (!m_stream.eof() && (streamID == M_GEOMETRY_VERTEX_ELEMENT)) { switch (streamID) { case M_GEOMETRY_VERTEX_ELEMENT: elements.push_back(readGeometryVertexElement()); break; default: break; } // Get next m_stream if (!m_stream.eof()) { streamID = readChunk(m_stream); } } if (!m_stream.eof()) { // Backpedal back to start of non-submesh m_stream backpedalChunkHeader(m_stream); } } return elements; }
void OgreMeshDeserializer::readGeometry() { std::vector<char> vertexBuffer; std::vector<OgreMeshDeserializer::VertexElement> elements; unsigned int vertexCount = 0; readInts(m_stream, &vertexCount, 1); // Find optional geometry streams if (!m_stream.eof()) { unsigned short streamID = readChunk(m_stream); while (!m_stream.eof() && (streamID == M_GEOMETRY_VERTEX_DECLARATION || streamID == M_GEOMETRY_VERTEX_BUFFER)) { switch (streamID) { case M_GEOMETRY_VERTEX_DECLARATION: elements = readGeometryVertexDeclaration(); break; case M_GEOMETRY_VERTEX_BUFFER: vertexBuffer = readGeometryVertexBuffer(vertexCount); break; default: skipChunk(m_stream); } // Get next stream if (!m_stream.eof()) { streamID = readChunk(m_stream); } } if (!elements.empty()) { for (auto& element : elements) { if (element.vSemantic == VertexElementSemantic::VES_POSITION) { size_t vertexSize = vertexBuffer.size() / vertexCount; for (size_t i = 0; i < vertexCount; ++i) { char* vertexStart = vertexBuffer.data() + (i * vertexSize); char* positionStart = vertexStart + element.offset; if (element.vType == VertexElementType::VET_FLOAT3) { float* positions = reinterpret_cast<float*>(positionStart); m_vertices.push_back(*positions); positions++; m_vertices.push_back(*positions); positions++; m_vertices.push_back(*positions); } } } } } if (!m_stream.eof()) { // Backpedal back to start of non-submesh stream backpedalChunkHeader(m_stream); } } }
void LodConfigSerializer::readLodConfig() { pushInnerChunk(mStream); while(!mStream->eof()) { unsigned short streamID = readChunk(mStream); switch(streamID) { case LCCID_BASIC_INFO: readLodBasicInfo(); break; case LCCID_LOD_LEVELS: readLodLevels(); break; case LCCID_ADVANCED_INFO: readLodAdvancedInfo(); break; case LCCID_PROFILE: readLodProfile(); break; default: // Backpedal back to start of stream backpedalChunkHeader(mStream); popInnerChunk(mStream); return; } } popInnerChunk(mStream); }
void LodConfigSerializer::importLodConfig(Ogre::LodConfig* config, DataStreamPtr& stream) { mStream = stream; mLodConfig = config; // Determine endianness (must be the first thing we do!) determineEndianness(mStream); // Check header readFileHeader(mStream); pushInnerChunk(mStream); while (!mStream->eof()) { unsigned short streamID = readChunk(mStream); switch (streamID) { case LCCID_LOD_CONFIG: readLodConfig(); break; default: backpedalChunkHeader(mStream); popInnerChunk(mStream); return; } } popInnerChunk(mStream); }
//--------------------------------------------------------------------- void SkeletonSerializer::readAnimation(DataStreamPtr& stream, Skeleton* pSkel) { // char* name : Name of the animation String name; name = readString(stream); // float length : Length of the animation in seconds float len; readFloats(stream, &len, 1); Animation *pAnim = pSkel->createAnimation(name, len); // Read all tracks if (!stream->eof()) { pushInnerChunk(stream); unsigned short streamID = readChunk(stream); // Optional base info is possible if (streamID == SKELETON_ANIMATION_BASEINFO) { // char baseAnimationName String baseAnimName = readString(stream); // float baseKeyFrameTime float baseKeyTime; readFloats(stream, &baseKeyTime, 1); pAnim->setUseBaseKeyFrame(true, baseKeyTime, baseAnimName); if (!stream->eof()) { // Get next stream streamID = readChunk(stream); } } while(streamID == SKELETON_ANIMATION_TRACK && !stream->eof()) { readAnimationTrack(stream, pAnim, pSkel); if (!stream->eof()) { // Get next stream streamID = readChunk(stream); } } if (!stream->eof()) { // Backpedal back to start of this stream if we've found a non-track backpedalChunkHeader(stream); } popInnerChunk(stream); } }
//--------------------------------------------------------------------- void OgreMeshDeserializer::readMesh() { //First value is whether it's skeletally animated m_stream.seekg(sizeof(bool), std::ios_base::cur); // Find all substreams if (!m_stream.eof()) { unsigned short streamID = readChunk(m_stream); while (!m_stream.eof() && (streamID == M_GEOMETRY || streamID == M_SUBMESH || streamID == M_MESH_SKELETON_LINK || streamID == M_MESH_BONE_ASSIGNMENT || streamID == M_MESH_LOD_LEVEL || streamID == M_MESH_BOUNDS || streamID == M_SUBMESH_NAME_TABLE || streamID == M_EDGE_LISTS || streamID == M_POSES || streamID == M_ANIMATIONS || streamID == M_TABLE_EXTREMES)) { switch (streamID) { case M_GEOMETRY: readGeometry(); break; case M_SUBMESH: readSubMesh(); break; case M_MESH_BOUNDS: readBoundsInfo(); break; default: skipChunk(m_stream); } if (!m_stream.eof()) { streamID = readChunk(m_stream); } } if (!m_stream.eof()) { // Backpedal back to start of m_stream backpedalChunkHeader(m_stream); } } }
//--------------------------------------------------------------------- void SkeletonSerializer::readAnimationTrack(DataStreamPtr& stream, Animation* anim, Skeleton* pSkel) { // unsigned short boneIndex : Index of bone to apply to unsigned short boneHandle; readShorts(stream, &boneHandle, 1); // Find bone Bone *targetBone = pSkel->getBone(boneHandle); // Create track NodeAnimationTrack* pTrack = anim->createNodeTrack(boneHandle, targetBone); // Keep looking for nested keyframes if (!stream->eof()) { pushInnerChunk(stream); unsigned short streamID = readChunk(stream); while(streamID == SKELETON_ANIMATION_TRACK_KEYFRAME && !stream->eof()) { readKeyFrame(stream, pTrack, pSkel); if (!stream->eof()) { // Get next stream streamID = readChunk(stream); } } if (!stream->eof()) { // Backpedal back to start of this stream if we've found a non-keyframe backpedalChunkHeader(stream); } popInnerChunk(stream); } }
//--------------------------------------------------------------------- void OgreMeshDeserializer::readSubMesh() { unsigned short streamID; std::string materialName = readString(m_stream); bool useSharedVertices; readBools(m_stream, &useSharedVertices, 1); size_t offset = 0; if (!useSharedVertices) { offset = m_vertices.size() / 3; } unsigned int indexCount = 0; readInts(m_stream, &indexCount, 1); bool idx32bit; readBools(m_stream, &idx32bit, 1); if (indexCount > 0) { if (idx32bit) { std::vector<std::uint32_t> indices; indices.resize(indexCount); readInts(m_stream, indices.data(), indexCount); for (auto& index : indices) { m_indices.emplace_back(index + offset); } } else // 16-bit { std::vector<std::uint16_t> indices; indices.resize(indexCount); readShorts(m_stream, indices.data(), indexCount); for (auto& index : indices) { m_indices.emplace_back(index + offset); } } } { // M_GEOMETRY m_stream (Optional: present only if useSharedVertices = false) if (!useSharedVertices) { streamID = readChunk(m_stream); if (streamID != M_GEOMETRY) { std::runtime_error("Missing geometry data in mesh file"); } readGeometry(); } // Find all bone assignments, submesh operation, and texture aliases (if present) if (!m_stream.eof()) { streamID = readChunk(m_stream); while (!m_stream.eof() && (streamID == M_SUBMESH_BONE_ASSIGNMENT || streamID == M_SUBMESH_OPERATION || streamID == M_SUBMESH_TEXTURE_ALIAS)) { skipChunk(m_stream); if (!m_stream.eof()) { streamID = readChunk(m_stream); } } if (!m_stream.eof()) { // Backpedal back to start of m_stream backpedalChunkHeader(m_stream); } } } }