Example #1
0
bool Animation::Load(Deserializer& source)
{
    PROFILE(LoadAnimation);
    
    unsigned memoryUse = sizeof(Animation);
    
    // Check ID
    if (source.ReadFileID() != "UANI")
    {
        LOGERROR(source.GetName() + " is not a valid animation file");
        return false;
    }
    
    // Read name and length
    animationName_ = source.ReadString();
    animationNameHash_ = animationName_;
    length_ = source.ReadFloat();
    tracks_.Clear();
    
    unsigned tracks = source.ReadUInt();
    tracks_.Resize(tracks);
    memoryUse += tracks * sizeof(AnimationTrack);
    
    // Read tracks
    for (unsigned i = 0; i < tracks; ++i)
    {
        AnimationTrack& newTrack = tracks_[i];
        newTrack.name_ = source.ReadString();
        newTrack.nameHash_ = newTrack.name_;
        newTrack.channelMask_ = source.ReadUByte();
        
        unsigned keyFrames = source.ReadUInt();
        newTrack.keyFrames_.Resize(keyFrames);
        memoryUse += keyFrames * sizeof(AnimationKeyFrame);
        
        // Read keyframes of the track
        for (unsigned j = 0; j < keyFrames; ++j)
        {
            AnimationKeyFrame& newKeyFrame = newTrack.keyFrames_[j];
            newKeyFrame.time_ = source.ReadFloat();
            if (newTrack.channelMask_ & CHANNEL_POSITION)
                newKeyFrame.position_ = source.ReadVector3();
            if (newTrack.channelMask_ & CHANNEL_ROTATION)
                newKeyFrame.rotation_ = source.ReadQuaternion();
            if (newTrack.channelMask_ & CHANNEL_SCALE)
                newKeyFrame.scale_ = source.ReadVector3();
        }
    }
    
    // Optionally read triggers from an XML file
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    String xmlName = ReplaceExtension(GetName(), ".xml");
    
    if (cache->Exists(xmlName))
    {
        XMLFile* file = cache->GetResource<XMLFile>(xmlName);
        if (file)
        {
            XMLElement rootElem = file->GetRoot();
            XMLElement triggerElem = rootElem.GetChild("trigger");
            while (triggerElem)
            {
                if (triggerElem.HasAttribute("normalizedtime"))
                    AddTrigger(triggerElem.GetFloat("normalizedtime"), true, triggerElem.GetVariant());
                else if (triggerElem.HasAttribute("time"))
                    AddTrigger(triggerElem.GetFloat("time"), false, triggerElem.GetVariant());
                
                triggerElem = triggerElem.GetNext("trigger");
            }
            
            memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint);
        }
    }
    
    SetMemoryUse(memoryUse);
    return true;
}
Example #2
0
bool Model::BeginLoad(Deserializer& source)
{
    // Check ID

    String id = source.ReadFileID();
    bool umdl = false;
    if (id == "UMDL") // we only support UMDL for some current legacy mdl's (ToonTown)
        umdl = true;

    if (!umdl && id != "AMDL")
    {
        LOGERROR(source.GetName() + " is not a valid model file");
        return false;
    }

    geometries_.Clear();
    geometryBoneMappings_.Clear();
    geometryCenters_.Clear();
    morphs_.Clear();
    vertexBuffers_.Clear();
    indexBuffers_.Clear();

    unsigned memoryUse = sizeof(Model);
    bool async = GetAsyncLoadState() == ASYNC_LOADING;

    // Read vertex buffers
    unsigned numVertexBuffers = source.ReadUInt();
    vertexBuffers_.Reserve(numVertexBuffers);
    morphRangeStarts_.Resize(numVertexBuffers);
    morphRangeCounts_.Resize(numVertexBuffers);
    loadVBData_.Resize(numVertexBuffers);
    for (unsigned i = 0; i < numVertexBuffers; ++i)
    {
        unsigned vertexCount = source.ReadUInt();
        unsigned elementMask = source.ReadUInt();
        morphRangeStarts_[i] = source.ReadUInt();
        morphRangeCounts_[i] = source.ReadUInt();

        SharedPtr<VertexBuffer> buffer(new VertexBuffer(context_));
        unsigned vertexSize = VertexBuffer::GetVertexSize(elementMask);

        // Prepare vertex buffer data to be uploaded during EndLoad()
        if (async)
        {
            loadVBData_[i].vertexCount_ = vertexCount;
            loadVBData_[i].elementMask_ = elementMask;
            loadVBData_[i].dataSize_ = vertexCount * vertexSize;
            loadVBData_[i].data_ = new unsigned char[loadVBData_[i].dataSize_];
            source.Read(loadVBData_[i].data_.Get(), loadVBData_[i].dataSize_);
        }
        else
        {
            // If not async loading, use locking to avoid extra allocation & copy
            loadVBData_[i].data_.Reset(); // Make sure no previous data
            buffer->SetShadowed(true);
            buffer->SetSize(vertexCount, elementMask);
            void* dest = buffer->Lock(0, vertexCount);
            source.Read(dest, vertexCount * vertexSize);
            buffer->Unlock();
        }

        memoryUse += sizeof(VertexBuffer) + vertexCount * vertexSize;
        vertexBuffers_.Push(buffer);
    }

    // Read index buffers
    unsigned numIndexBuffers = source.ReadUInt();
    indexBuffers_.Reserve(numIndexBuffers);
    loadIBData_.Resize(numIndexBuffers);
    for (unsigned i = 0; i < numIndexBuffers; ++i)
    {
        unsigned indexCount = source.ReadUInt();
        unsigned indexSize = source.ReadUInt();

        SharedPtr<IndexBuffer> buffer(new IndexBuffer(context_));

        // Prepare index buffer data to be uploaded during EndLoad()
        if (async)
        {
            loadIBData_[i].indexCount_ = indexCount;
            loadIBData_[i].indexSize_ = indexSize;
            loadIBData_[i].dataSize_ = indexCount * indexSize;
            loadIBData_[i].data_ = new unsigned char[loadIBData_[i].dataSize_];
            source.Read(loadIBData_[i].data_.Get(), loadIBData_[i].dataSize_);
        }
        else
        {
            // If not async loading, use locking to avoid extra allocation & copy
            loadIBData_[i].data_.Reset(); // Make sure no previous data
            buffer->SetShadowed(true);
            buffer->SetSize(indexCount, indexSize > sizeof(unsigned short));
            void* dest = buffer->Lock(0, indexCount);
            source.Read(dest, indexCount * indexSize);
            buffer->Unlock();
        }

        memoryUse += sizeof(IndexBuffer) + indexCount * indexSize;
        indexBuffers_.Push(buffer);
    }

    // Read geometries
    unsigned numGeometries = source.ReadUInt();
    geometries_.Reserve(numGeometries);
    geometryBoneMappings_.Reserve(numGeometries);
    geometryCenters_.Reserve(numGeometries);
    loadGeometries_.Resize(numGeometries);
    for (unsigned i = 0; i < numGeometries; ++i)
    {
        // Read bone mappings
        unsigned boneMappingCount = source.ReadUInt();
        PODVector<unsigned> boneMapping(boneMappingCount);
        for (unsigned j = 0; j < boneMappingCount; ++j)
            boneMapping[j] = source.ReadUInt();
        geometryBoneMappings_.Push(boneMapping);

        unsigned numLodLevels = source.ReadUInt();
        Vector<SharedPtr<Geometry> > geometryLodLevels;
        geometryLodLevels.Reserve(numLodLevels);
        loadGeometries_[i].Resize(numLodLevels);

        for (unsigned j = 0; j < numLodLevels; ++j)
        {
            float distance = source.ReadFloat();
            PrimitiveType type = (PrimitiveType)source.ReadUInt();

            unsigned vbRef = source.ReadUInt();
            unsigned ibRef = source.ReadUInt();
            unsigned indexStart = source.ReadUInt();
            unsigned indexCount = source.ReadUInt();

            if (vbRef >= vertexBuffers_.Size())
            {
                LOGERROR("Vertex buffer index out of bounds");
                loadVBData_.Clear();
                loadIBData_.Clear();
                loadGeometries_.Clear();
                return false;
            }
            if (ibRef >= indexBuffers_.Size())
            {
                LOGERROR("Index buffer index out of bounds");
                loadVBData_.Clear();
                loadIBData_.Clear();
                loadGeometries_.Clear();
                return false;
            }

            SharedPtr<Geometry> geometry(new Geometry(context_));
            geometry->SetLodDistance(distance);

            // Prepare geometry to be defined during EndLoad()
            loadGeometries_[i][j].type_ = type;
            loadGeometries_[i][j].vbRef_ = vbRef;
            loadGeometries_[i][j].ibRef_ = ibRef;
            loadGeometries_[i][j].indexStart_ = indexStart;
            loadGeometries_[i][j].indexCount_ = indexCount;

            geometryLodLevels.Push(geometry);
            memoryUse += sizeof(Geometry);
        }

        geometries_.Push(geometryLodLevels);
    }

    // Read morphs
    unsigned numMorphs = source.ReadUInt();
    morphs_.Reserve(numMorphs);
    for (unsigned i = 0; i < numMorphs; ++i)
    {
        ModelMorph newMorph;

        newMorph.name_ = source.ReadString();
        newMorph.nameHash_ = newMorph.name_;
        newMorph.weight_ = 0.0f;
        unsigned numBuffers = source.ReadUInt();

        for (unsigned j = 0; j < numBuffers; ++j)
        {
            VertexBufferMorph newBuffer;
            unsigned bufferIndex = source.ReadUInt();

            newBuffer.elementMask_ = source.ReadUInt();
            newBuffer.vertexCount_ = source.ReadUInt();

            // Base size: size of each vertex index
            unsigned vertexSize = sizeof(unsigned);
            // Add size of individual elements
            if (newBuffer.elementMask_ & MASK_POSITION)
                vertexSize += sizeof(Vector3);
            if (newBuffer.elementMask_ & MASK_NORMAL)
                vertexSize += sizeof(Vector3);
            if (newBuffer.elementMask_ & MASK_TANGENT)
                vertexSize += sizeof(Vector3);
            newBuffer.dataSize_ = newBuffer.vertexCount_ * vertexSize;
            newBuffer.morphData_ = new unsigned char[newBuffer.dataSize_];

            source.Read(&newBuffer.morphData_[0], newBuffer.vertexCount_ * vertexSize);

            newMorph.buffers_[bufferIndex] = newBuffer;
            memoryUse += sizeof(VertexBufferMorph) + newBuffer.vertexCount_ * vertexSize;
        }

        morphs_.Push(newMorph);
        memoryUse += sizeof(ModelMorph);
    }

    // Read skeleton
    skeleton_.Load(source);
    memoryUse += skeleton_.GetNumBones() * sizeof(Bone);

    // Read bounding box
    boundingBox_ = source.ReadBoundingBox();

    // Read geometry centers
    for (unsigned i = 0; i < geometries_.Size() && !source.IsEof(); ++i)
        geometryCenters_.Push(source.ReadVector3());
    while (geometryCenters_.Size() < geometries_.Size())
        geometryCenters_.Push(Vector3::ZERO);
    memoryUse += sizeof(Vector3) * geometries_.Size();

    if (umdl)
    {
        SetMemoryUse(memoryUse);
        return true;
    }

    // MODEL_VERSION
    unsigned version = source.ReadUInt();

    ResourceRefList animList = source.ReadResourceRefList();

    animationsResources_.Clear();

    ResourceCache* cache = GetSubsystem<ResourceCache>();
    for (unsigned i = 0; i < animList.names_.Size(); ++i)
    {
        AddAnimationResource(cache->GetResource<Animation>(animList.names_[i]));
    }

    SetMemoryUse(memoryUse);
    return true;
}
Example #3
0
bool Model::Load(Deserializer& source)
{
    PROFILE(LoadModel);
    
    // Check ID
    if (source.ReadFileID() != "UMDL")
    {
        LOGERROR(source.GetName() + " is not a valid model file");
        return false;
    }
    
    geometries_.Clear();
    geometryBoneMappings_.Clear();
    geometryCenters_.Clear();
    morphs_.Clear();
    vertexBuffers_.Clear();
    indexBuffers_.Clear();
    
    unsigned memoryUse = sizeof(Model);
    
    // Read vertex buffers
    unsigned numVertexBuffers = source.ReadUInt();
    vertexBuffers_.Reserve(numVertexBuffers);
    morphRangeStarts_.Resize(numVertexBuffers);
    morphRangeCounts_.Resize(numVertexBuffers);
    for (unsigned i = 0; i < numVertexBuffers; ++i)
    {
        unsigned vertexCount = source.ReadUInt();
        unsigned elementMask = source.ReadUInt();
        morphRangeStarts_[i] = source.ReadUInt();
        morphRangeCounts_[i] = source.ReadUInt();
        
        SharedPtr<VertexBuffer> buffer(new VertexBuffer(context_));
        buffer->SetShadowed(true);
        buffer->SetSize(vertexCount, elementMask);
        
        void* dest = buffer->Lock(0, vertexCount);
        unsigned vertexSize = buffer->GetVertexSize();
        source.Read(dest, vertexCount * vertexSize);
        buffer->Unlock();
        
        memoryUse += sizeof(VertexBuffer) + vertexCount * vertexSize;
        vertexBuffers_.Push(buffer);
    }

    // Read index buffers
    unsigned numIndexBuffers = source.ReadUInt();
    indexBuffers_.Reserve(numIndexBuffers);
    for (unsigned i = 0; i < numIndexBuffers; ++i)
    {
        unsigned indexCount = source.ReadUInt();
        unsigned indexSize = source.ReadUInt();
        
        SharedPtr<IndexBuffer> buffer(new IndexBuffer(context_));
        buffer->SetShadowed(true);
        buffer->SetSize(indexCount, indexSize > sizeof(unsigned short));
        
        void* dest = buffer->Lock(0, indexCount);
        source.Read(dest, indexCount * indexSize);
        buffer->Unlock();
        
        memoryUse += sizeof(IndexBuffer) + indexCount * indexSize;
        indexBuffers_.Push(buffer);
    }
    
    // Read geometries
    unsigned numGeometries = source.ReadUInt();
    geometries_.Reserve(numGeometries);
    geometryBoneMappings_.Reserve(numGeometries);
    geometryCenters_.Reserve(numGeometries);
    for (unsigned i = 0; i < numGeometries; ++i)
    {
        // Read bone mappings
        unsigned boneMappingCount = source.ReadUInt();
        PODVector<unsigned> boneMapping(boneMappingCount);
        for (unsigned j = 0; j < boneMappingCount; ++j)
            boneMapping[j] = source.ReadUInt();
        geometryBoneMappings_.Push(boneMapping);
        
        unsigned numLodLevels = source.ReadUInt();
        Vector<SharedPtr<Geometry> > geometryLodLevels;
        geometryLodLevels.Reserve(numLodLevels);
        
        for (unsigned j = 0; j < numLodLevels; ++j)
        {
            float distance = source.ReadFloat();
            PrimitiveType type = (PrimitiveType)source.ReadUInt();
            
            unsigned vertexBufferRef = source.ReadUInt();
            unsigned indexBufferRef = source.ReadUInt();
            unsigned indexStart = source.ReadUInt();
            unsigned indexCount = source.ReadUInt();
            
            if (vertexBufferRef >= vertexBuffers_.Size())
            {
                LOGERROR("Vertex buffer index out of bounds");
                return false;
            }
            if (indexBufferRef >= indexBuffers_.Size())
            {
                LOGERROR("Index buffer index out of bounds");
                return false;
            }
            
            SharedPtr<Geometry> geometry(new Geometry(context_));
            geometry->SetVertexBuffer(0, vertexBuffers_[vertexBufferRef]);
            geometry->SetIndexBuffer(indexBuffers_[indexBufferRef]);
            geometry->SetDrawRange(type, indexStart, indexCount);
            geometry->SetLodDistance(distance);
            
            geometryLodLevels.Push(geometry);
            memoryUse += sizeof(Geometry);
        }
        
        geometries_.Push(geometryLodLevels);
    }
    
    // Read morphs
    unsigned numMorphs = source.ReadUInt();
    morphs_.Reserve(numMorphs);
    for (unsigned i = 0; i < numMorphs; ++i)
    {
        ModelMorph newMorph;
        
        newMorph.name_ = source.ReadString();
        newMorph.nameHash_ = newMorph.name_;
        newMorph.weight_ = 0.0f;
        unsigned nubuffers_ = source.ReadUInt();
        
        for (unsigned j = 0; j < nubuffers_; ++j)
        {
            VertexBufferMorph newBuffer;
            unsigned bufferIndex = source.ReadUInt();
            
            newBuffer.elementMask_ = source.ReadUInt();
            newBuffer.vertexCount_ = source.ReadUInt();
            
            // Base size: size of each vertex index
            unsigned vertexSize = sizeof(unsigned);
            // Add size of individual elements
            if (newBuffer.elementMask_ & MASK_POSITION)
                vertexSize += sizeof(Vector3);
            if (newBuffer.elementMask_ & MASK_NORMAL)
                vertexSize += sizeof(Vector3);
            if (newBuffer.elementMask_ & MASK_TANGENT)
                vertexSize += sizeof(Vector3);
            newBuffer.morphData_ = new unsigned char[newBuffer.vertexCount_ * vertexSize];
            
            source.Read(&newBuffer.morphData_[0], newBuffer.vertexCount_ * vertexSize);
            
            newMorph.buffers_[bufferIndex] = newBuffer;
            memoryUse += sizeof(VertexBufferMorph) + newBuffer.vertexCount_ * vertexSize;
        }
        
        morphs_.Push(newMorph);
        memoryUse += sizeof(ModelMorph);
    }
    
    // Read skeleton
    skeleton_.Load(source);
    memoryUse += skeleton_.GetNumBones() * sizeof(Bone);
    
    // Read bounding box
    boundingBox_ = source.ReadBoundingBox();
    
    // Read geometry centers
    for (unsigned i = 0; i < geometries_.Size() && !source.IsEof(); ++i)
        geometryCenters_.Push(source.ReadVector3());
    while (geometryCenters_.Size() < geometries_.Size())
        geometryCenters_.Push(Vector3::ZERO);
    memoryUse += sizeof(Vector3) * geometries_.Size();
    
    SetMemoryUse(memoryUse);
    return true;
}
Example #4
0
    bool ModelDefinition::Deserialize(Deserializer &deserializer)
    {
        // Clear everything.
        this->ClearMeshes();
        this->ClearBones();
        this->ClearAnimations(true);        // <-- 'true' = clear animation segments, too.
        this->ClearConvexHulls();


        // We keep looping until we hit the null or unknown chunk.
        Serialization::ChunkHeader header;
        while (deserializer.Peek(&header, sizeof(header)) == sizeof(header))
        {
            bool finished = false;

            switch (header.id)
            {
            case Serialization::ChunkID_Model_Bones:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t boneCount;
                        deserializer.Read(boneCount);

                        for (uint32_t iBone = 0; iBone < boneCount; ++iBone)
                        {
                            // Name.
                            String name;
                            deserializer.ReadString(name);

                            // Local transform.
                            glm::vec3 position;
                            glm::quat rotation;
                            glm::vec3 scale;

                            deserializer.Read(position);
                            deserializer.Read(rotation);
                            deserializer.Read(scale);

                            // 4x4 offset matrix.
                            glm::mat4 offsetMatrix;
                            deserializer.Read(offsetMatrix);


                            auto bone = new Bone;
                            bone->SetName(name.c_str());
                            bone->SetPosition(position);
                            bone->SetRotation(rotation);
                            bone->SetScale(scale);
                            bone->SetOffsetMatrix(offsetMatrix);
                            this->AddBone(bone);


                            // We need to create a channel for this bone. We then need to map that channel to a bone.
                            auto &channel = m_animation.CreateChannel();
                            this->animationChannelBones.Add(bone, &channel);
                        }


                        // Parents.
                        auto boneParentIndices = static_cast<uint32_t*>(malloc(boneCount * sizeof(uint32_t)));
                        deserializer.Read(boneParentIndices, boneCount * sizeof(uint32_t));

                        for (uint32_t iBone = 0; iBone < boneCount; ++iBone)
                        {
                            uint32_t parentIndex = boneParentIndices[iBone];

                            if (parentIndex != static_cast<uint32_t>(-1))
                            {
                                m_bones[parentIndex]->AttachChild(*m_bones[iBone]);
                            }
                        }

                        free(boneParentIndices);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_Meshes:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t meshCount;
                        deserializer.Read(meshCount);

                        for (uint32_t iMesh = 0; iMesh < meshCount; ++iMesh)
                        {
                            ModelDefinition::Mesh newMesh(m_context);

                            // Name.
                            deserializer.ReadString(newMesh.name);


                            // Material
                            String materialName;
                            deserializer.ReadString(materialName);

                            newMesh.material = m_context.GetMaterialLibrary().Create(materialName.c_str());



                            // Geometry
                            VertexFormat vertexFormat;
                            vertexFormat.Deserialize(deserializer);
                            newMesh.geometry = Renderer::CreateVertexArray(VertexArrayUsage_Static, vertexFormat);
                            
                            // Vertices.
                            uint32_t vertexCount;
                            deserializer.Read(vertexCount);

                            if (vertexCount > 0)
                            {
                                newMesh.geometry->SetVertexData(nullptr, static_cast<size_t>(vertexCount));
                                auto vertexData = newMesh.geometry->MapVertexData();
                                {
                                    deserializer.Read(vertexData, vertexCount * vertexFormat.GetSizeInBytes());
                                }
                                newMesh.geometry->UnmapVertexData();
                            }

                            // Indices.
                            uint32_t indexCount;
                            deserializer.Read(indexCount);

                            if (indexCount > 0)
                            {
                                newMesh.geometry->SetIndexData(nullptr, static_cast<size_t>(indexCount));
                                auto indexData = newMesh.geometry->MapIndexData();
                                {
                                    deserializer.Read(indexData, indexCount * sizeof(uint32_t));
                                }
                                newMesh.geometry->UnmapIndexData();
                            }



                            // Skinning Vertex Attributes
                            uint32_t skinningVertexAttributeCount;
                            deserializer.Read(skinningVertexAttributeCount);

                            if (skinningVertexAttributeCount > 0)
                            {
                                newMesh.skinningVertexAttributes = new SkinningVertexAttribute[skinningVertexAttributeCount];

                                auto counts = static_cast<uint16_t*>(malloc(skinningVertexAttributeCount * sizeof(uint16_t)));
                                deserializer.Read(counts, skinningVertexAttributeCount * sizeof(uint16_t));

                                uint32_t totalBoneWeights;
                                deserializer.Read(totalBoneWeights);

                                auto boneWeights = static_cast<BoneWeightPair*>(malloc(totalBoneWeights * sizeof(BoneWeightPair)));
                                deserializer.Read(boneWeights, totalBoneWeights * sizeof(BoneWeightPair));


                                auto currentBoneWeight = boneWeights;
                                for (uint32_t iVertex = 0; iVertex < skinningVertexAttributeCount; ++iVertex)
                                {
                                    auto count = counts[iVertex];

                                    // Here we allocate the buffer for the bones. We trick the vector here by modifying attributes directly.
                                    newMesh.skinningVertexAttributes[iVertex].bones.Reserve(count);
                                    newMesh.skinningVertexAttributes[iVertex].bones.count = count;

                                    for (uint16_t iBone = 0; iBone < count; ++iBone)
                                    {
                                        newMesh.skinningVertexAttributes[iVertex].bones[iBone] = *currentBoneWeight++;
                                    }
                                }

                                free(counts);
                                free(boneWeights);
                            }


                            // Uniforms.
                            newMesh.defaultUniforms.Deserialize(deserializer);


                            // Finally, add the mesh.
                            this->AddMesh(newMesh);
                        }
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_Animation:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t keyFrameCount;
                        deserializer.Read(keyFrameCount);

                        for (size_t iKeyFrame = 0; iKeyFrame < keyFrameCount; ++iKeyFrame)
                        {
                            float time;
                            deserializer.Read(time);

                            size_t keyFrameIndex = m_animation.AppendKeyFrame(static_cast<double>(time));


                            // With the key frame added, we now need to iterate over each channel in the key frame.
                            uint32_t channelCount;
                            deserializer.Read(channelCount);

                            for (uint32_t iChannel = 0; iChannel < channelCount; ++iChannel)
                            {
                                uint32_t boneIndex;
                                deserializer.Read(boneIndex);

                                auto bone = m_bones[boneIndex];
                                assert(bone != nullptr);
                                {
                                    auto iChannelBone = this->animationChannelBones.Find(bone);
                                    assert(iChannelBone != nullptr);
                                    {
                                        auto channel = iChannelBone->value;

                                        glm::vec3 position;
                                        glm::quat rotation;
                                        glm::vec3 scale;
                                        
                                        deserializer.Read(position);
                                        deserializer.Read(rotation);
                                        deserializer.Read(scale);

                                        auto key = new TransformAnimationKey(position, rotation, scale);
                                        channel->SetKey(keyFrameIndex, key);


                                        // We need to cache the key.
                                        this->animationKeyCache.PushBack(key);
                                    }
                                }
                            }
                        }

                        deserializer.Read(this->animationAABBPadding);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_AnimationSegments:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t animationSegmentCount;
                        deserializer.Read(animationSegmentCount);
                        
                        for (uint32_t iSegment = 0; iSegment < animationSegmentCount; ++iSegment)
                        {
                            String name;
                            uint32_t startKeyFrame;
                            uint32_t endKeyFrame;

                            deserializer.ReadString(name);
                            deserializer.Read(startKeyFrame);
                            deserializer.Read(endKeyFrame);

                            m_animation.AddNamedSegment(name.c_str(), static_cast<size_t>(startKeyFrame), static_cast<size_t>(endKeyFrame));
                        }
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_AnimationSequences:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_ConvexHulls:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t convexHullCount;
                        deserializer.Read(convexHullCount);

                        uint32_t* vertexCounts = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t)));
                        uint32_t* indexCounts  = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t)));

                        deserializer.Read(vertexCounts, convexHullCount * sizeof(uint32_t));
                        deserializer.Read(indexCounts,  convexHullCount * sizeof(uint32_t));


                        uint32_t totalVertexCount;
                        deserializer.Read(totalVertexCount);

                        uint32_t totalIndexCount;
                        deserializer.Read(totalIndexCount);


                        auto vertices = static_cast<float*   >(malloc(totalVertexCount * sizeof(float)));
                        auto indices  = static_cast<uint32_t*>(malloc(totalIndexCount  * sizeof(uint32_t)));

                        deserializer.Read(vertices, totalVertexCount * sizeof(float));
                        deserializer.Read(indices,  totalIndexCount  * sizeof(uint32_t));


                        auto currentVertices = vertices;
                        auto currentIndices  = indices;

                        for (uint32_t iConvexHull = 0; iConvexHull < convexHullCount; ++iConvexHull)
                        {
                            size_t vertexCount = static_cast<size_t>(vertexCounts[iConvexHull]);
                            size_t indexCount  = static_cast<size_t>(indexCounts[iConvexHull]);

                            m_convexHulls.PushBack(new ConvexHull(currentVertices, vertexCount, currentIndices, indexCount));

                            // Now we need to move our pointers forward.
                            currentVertices += vertexCount * 3;
                            currentIndices  += indexCount;
                        }


                        // Build Settings.
                        deserializer.Read(this->convexHullBuildSettings);


                        free(vertexCounts);
                        free(indexCounts);
                        free(vertices);
                        free(indices);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Null:
                {
                    deserializer.Seek(sizeof(header));

                    finished = true;
                    break;
                }

            default:
                {
                    // Unknown chunk = Error.
                    finished = true;
                    return false;
                }
            }


            if (finished)
            {
                break;
            }
        }


        // If we get here, we were successful.
        return true;
    }
Example #5
0
bool Animation::BeginLoad(Deserializer& source)
{
    unsigned memoryUse = sizeof(Animation);

    // Check ID
    if (source.ReadFileID() != "UANI")
    {
        URHO3D_LOGERROR(source.GetName() + " is not a valid animation file");
        return false;
    }

    // Read name and length
    animationName_ = source.ReadString();
    animationNameHash_ = animationName_;
    length_ = source.ReadFloat();
    tracks_.Clear();

    unsigned tracks = source.ReadUInt();
    memoryUse += tracks * sizeof(AnimationTrack);

    // Read tracks
    for (unsigned i = 0; i < tracks; ++i)
    {
        AnimationTrack* newTrack = CreateTrack(source.ReadString());
        newTrack->channelMask_ = source.ReadUByte();

        unsigned keyFrames = source.ReadUInt();
        newTrack->keyFrames_.Resize(keyFrames);
        memoryUse += keyFrames * sizeof(AnimationKeyFrame);

        // Read keyframes of the track
        for (unsigned j = 0; j < keyFrames; ++j)
        {
            AnimationKeyFrame& newKeyFrame = newTrack->keyFrames_[j];
            newKeyFrame.time_ = source.ReadFloat();
            if (newTrack->channelMask_ & CHANNEL_POSITION)
                newKeyFrame.position_ = source.ReadVector3();
            if (newTrack->channelMask_ & CHANNEL_ROTATION)
                newKeyFrame.rotation_ = source.ReadQuaternion();
            if (newTrack->channelMask_ & CHANNEL_SCALE)
                newKeyFrame.scale_ = source.ReadVector3();
        }
    }

    // Optionally read triggers from an XML file
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    String xmlName = ReplaceExtension(GetName(), ".xml");

    SharedPtr<XMLFile> file(cache->GetTempResource<XMLFile>(xmlName, false));
    if (file)
    {
        XMLElement rootElem = file->GetRoot();
        XMLElement triggerElem = rootElem.GetChild("trigger");
        while (triggerElem)
        {
            if (triggerElem.HasAttribute("normalizedtime"))
                AddTrigger(triggerElem.GetFloat("normalizedtime"), true, triggerElem.GetVariant());
            else if (triggerElem.HasAttribute("time"))
                AddTrigger(triggerElem.GetFloat("time"), false, triggerElem.GetVariant());

            triggerElem = triggerElem.GetNext("trigger");
        }

        memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint);
        SetMemoryUse(memoryUse);
        return true;
    }

    // Optionally read triggers from a JSON file
    String jsonName = ReplaceExtension(GetName(), ".json");

    SharedPtr<JSONFile> jsonFile(cache->GetTempResource<JSONFile>(jsonName, false));
    if (jsonFile)
    {
        const JSONValue& rootVal = jsonFile->GetRoot();
        JSONArray triggerArray = rootVal.Get("triggers").GetArray();

        for (unsigned i = 0; i < triggerArray.Size(); i++)
        {
            const JSONValue& triggerValue = triggerArray.At(i);
            JSONValue normalizedTimeValue = triggerValue.Get("normalizedTime");
            if (!normalizedTimeValue.IsNull())
                AddTrigger(normalizedTimeValue.GetFloat(), true, triggerValue.GetVariant());
            else
            {
                JSONValue timeVal = triggerValue.Get("time");
                if (!timeVal.IsNull())
                    AddTrigger(timeVal.GetFloat(), false, triggerValue.GetVariant());
            }
        }

        memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint);
        SetMemoryUse(memoryUse);
        return true;
    }

    SetMemoryUse(memoryUse);
    return true;
}
Example #6
0
    void ModelComponent::Deserialize(Deserializer &deserializer)
    {
        uint32_t whatChanged = 0;
        this->LockOnChanged();


        Serialization::ChunkHeader header;
        deserializer.Read(header);

        assert(header.id == Serialization::ChunkID_ModelComponent_Main);
        {
            size_t deserializerStart = deserializer.Tell();
            
            switch (header.version)
            {
            case 1:
                {
                    // Flags are first.
                    uint32_t newFlags;
                    deserializer.Read(newFlags);

                    if (newFlags != this->flags)
                    {
                        this->flags = newFlags;
                        whatChanged |= ChangeFlag_Flags;
                    }


                    // Next is a boolean indicating whether or not a model is defined here.
                    bool hasModel;
                    deserializer.Read(hasModel);

                    // We will only have additional data at this point if we have actually have a model defined.
                    if (hasModel)
                    {
                        auto oldModel = this->model;


                        String modelPath;
                        deserializer.ReadString(modelPath);

                        if (!modelPath.IsEmpty())
                        {
                            this->SetModel(modelPath.c_str());
                            
                            // If we failed to set the model (most likely due to the file not existing) we need to skip this chunk and return.
                            if (this->model == nullptr)
                            {
                                const size_t bytesReadSoFar = deserializer.Tell() - deserializerStart;
                                
                                deserializer.Seek(header.sizeInBytes - bytesReadSoFar);
                                return;
                            }
                        }
                        else
                        {
                            if (this->GetContext() != NULL) {
                                ModelDefinition nullDefinition(*this->GetContext());
                                this->SetModel(new Model(nullDefinition), true);
                            }
                        }


                        assert(this->model != nullptr);
                        {
                            this->model->Deserialize(deserializer);
                        }


                        if (this->model != oldModel)
                        {
                            whatChanged |= ChangeFlag_Model;
                        }
                    }


                    break;
                }

            default:
                {
                    if (this->GetContext() != NULL) {
                        this->GetContext()->Logf("Error deserializing ModelComponent. Main chunk has an unsupported version (%d).", header.version);
                    }

                    break;
                }
            }
        }


        this->UnlockOnChanged();
        if (whatChanged != 0)
        {
            this->OnChanged(whatChanged);
        }
    }