<commit_before>/*
 *  Copyright 2019-2021 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#pragma once

/// \file
/// Implementation of the Diligent::ShaderResourceBindingBase template class

#include <array>
#include <functional>

#include "PrivateConstants.h"
#include "ShaderResourceBinding.h"
#include "ObjectBase.hpp"
#include "GraphicsTypes.h"
#include "Constants.h"
#include "RefCntAutoPtr.hpp"
#include "GraphicsAccessories.hpp"
#include "ShaderResourceCacheCommon.hpp"
#include "FixedLinearAllocator.hpp"
#include "EngineMemory.h"

namespace Diligent
{

/// Template class implementing base functionality of the shader resource binding

/// \tparam EngineImplTraits - Engine implementation type traits.
template <typename EngineImplTraits>
class ShaderResourceBindingBase : public ObjectBase<typename EngineImplTraits::ShaderResourceBindingInterface>
{
public:
    // Base interface this class inherits (IShaderResourceBindingD3D12, IShaderResourceBindingVk, etc.)
    using BaseInterface = typename EngineImplTraits::ShaderResourceBindingInterface;

    // The type of the pipeline resource signature implementation (PipelineResourceSignatureD3D12Impl, PipelineResourceSignatureVkImpl, etc.).
    using ResourceSignatureType = typename EngineImplTraits::PipelineResourceSignatureImplType;

    // The type of the shader resource cache implementation (ShaderResourceCacheD3D12Impl, ShaderResourceCacheVkImpl, etc.)
    using ShaderResourceCacheImplType = typename EngineImplTraits::ShaderResourceCacheImplType;

    // The type of the shader resource variable manager (ShaderVariableManagerD3D12Impl, ShaderVariableManagerVkImpl, etc.)
    using ShaderVariableManagerImplType = typename EngineImplTraits::ShaderVariableManagerImplType;

    using TObjectBase = ObjectBase<BaseInterface>;

    /// \param pRefCounters - Reference counters object that controls the lifetime of this SRB.
    /// \param pPRS         - Pipeline resource signature that this SRB belongs to.
    ShaderResourceBindingBase(IReferenceCounters* pRefCounters, ResourceSignatureType* pPRS) :
        TObjectBase{pRefCounters},
        m_pPRS{pPRS},
        m_ShaderResourceCache{ResourceCacheContentType::SRB}
    {
        m_ActiveShaderStageIndex.fill(-1);

        const auto NumShaders   = GetNumShaders();
        const auto PipelineType = GetPipelineType();
        for (Uint32 s = 0; s < NumShaders; ++s)
        {
            const auto ShaderType = pPRS->GetActiveShaderStageType(s);
            const auto ShaderInd  = GetShaderTypePipelineIndex(ShaderType, PipelineType);

            m_ActiveShaderStageIndex[ShaderInd] = static_cast<Int8>(s);
        }

        FixedLinearAllocator MemPool{GetRawAllocator()};
        MemPool.AddSpace<ShaderVariableManagerImplType>(NumShaders);
        MemPool.Reserve();
        static_assert(std::is_nothrow_constructible<ShaderVariableManagerImplType, decltype(*this), ShaderResourceCacheImplType&>::value,
                      "Constructor of ShaderVariableManagerImplType must be noexcept, so we can safely construct all managers");
        m_pShaderVarMgrs = MemPool.ConstructArray<ShaderVariableManagerImplType>(NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache));

        // The memory is now owned by ShaderResourceBindingBase and will be freed by destructor.
        auto* Ptr = MemPool.ReleaseOwnership();
        VERIFY_EXPR(Ptr == m_pShaderVarMgrs);
        (void)Ptr;

        // It is important to construct all objects before initializing them because if an exception is thrown,
        // destructors will be called for all objects

        pPRS->InitSRBResourceCache(m_ShaderResourceCache);

        auto& SRBMemAllocator = pPRS->GetSRBMemoryAllocator();
        for (Uint32 s = 0; s < NumShaders; ++s)
        {
            const auto ShaderType = pPRS->GetActiveShaderStageType(s);
            const auto ShaderInd  = GetShaderTypePipelineIndex(ShaderType, pPRS->GetPipelineType());
            const auto MgrInd     = m_ActiveShaderStageIndex[ShaderInd];
            VERIFY_EXPR(MgrInd >= 0 && MgrInd < static_cast<int>(NumShaders));

            auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);

            // Initialize vars manager to reference mutable and dynamic variables
            // Note that the cache has space for all variable types
            const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
            m_pShaderVarMgrs[MgrInd].Initialize(*pPRS, VarDataAllocator, VarTypes, _countof(VarTypes), ShaderType);
        }
    }

    ~ShaderResourceBindingBase()
    {
        if (m_pShaderVarMgrs != nullptr)
        {
            auto& SRBMemAllocator = GetSignature()->GetSRBMemoryAllocator();
            for (Uint32 s = 0; s < GetNumShaders(); ++s)
            {
                auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
                m_pShaderVarMgrs[s].Destroy(VarDataAllocator);
                m_pShaderVarMgrs[s].~ShaderVariableManagerImplType();
            }
            GetRawAllocator().Free(m_pShaderVarMgrs);
        }
    }

    IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBinding, TObjectBase)

    Uint32 GetBindingIndex() const
    {
        return m_pPRS->GetDesc().BindingIndex;
    }

    PIPELINE_TYPE GetPipelineType() const
    {
        return m_pPRS->GetPipelineType();
    }

    Uint32 GetNumShaders() const
    {
        return m_pPRS->GetNumActiveShaderStages();
    }

    /// Implementation of IShaderResourceBinding::GetPipelineResourceSignature().
    virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetPipelineResourceSignature() const override final
    {
        return GetSignature();
    }

    virtual bool DILIGENT_CALL_TYPE StaticResourcesInitialized() const override final
    {
        return m_bStaticResourcesInitialized;
    }

    ResourceSignatureType* GetSignature() const
    {
        return m_pPRS.template RawPtr<ResourceSignatureType>();
    }

    void SetStaticResourcesInitialized()
    {
        VERIFY_EXPR(!m_bStaticResourcesInitialized);
        m_bStaticResourcesInitialized = true;
    }

    /// Implementation of IShaderResourceBinding::GetVariableByName().
    virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return nullptr;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return nullptr;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariable(Name);
    }

    /// Implementation of IShaderResourceBinding::GetVariableCount().
    virtual Uint32 DILIGENT_CALL_TYPE GetVariableCount(SHADER_TYPE ShaderType) const override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return 0;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return 0;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariableCount();
    }

    /// Implementation of IShaderResourceBinding::GetVariableByIndex().
    virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to get mutable/dynamic variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return nullptr;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return nullptr;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariable(Index);
    }

    /// Implementation of IShaderResourceBinding::BindResources().
    virtual void DILIGENT_CALL_TYPE BindResources(Uint32            ShaderFlags,
                                                  IResourceMapping* pResMapping,
                                                  Uint32            Flags) override final
    {
        const auto PipelineType = GetPipelineType();
        for (Int32 ShaderInd = 0; ShaderInd < static_cast<Int32>(m_ActiveShaderStageIndex.size()); ++ShaderInd)
        {
            auto VarMngrInd = m_ActiveShaderStageIndex[ShaderInd];
            if (VarMngrInd >= 0)
            {
                // ShaderInd is the shader type pipeline index here
                const auto ShaderType = GetShaderTypeFromPipelineIndex(ShaderInd, PipelineType);
                if ((ShaderFlags & ShaderType) != 0)
                {
                    m_pShaderVarMgrs[VarMngrInd].BindResources(pResMapping, Flags);
                }
            }
        }
    }

    ShaderResourceCacheImplType&       GetResourceCache() { return m_ShaderResourceCache; }
    const ShaderResourceCacheImplType& GetResourceCache() const { return m_ShaderResourceCache; }

protected:
    /// Strong reference to pipeline resource signature. We must use strong reference, because
    /// shader resource binding uses pipeline resource signature's memory allocator to allocate
    /// memory for shader resource cache.
    RefCntAutoPtr<ResourceSignatureType> m_pPRS;

    // Index of the active shader stage that has resources, for every shader
    // type in the pipeline (given by GetShaderTypePipelineIndex(ShaderType, m_PipelineType)).
    std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ActiveShaderStageIndex = {-1, -1, -1, -1, -1, -1};
    static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");

    ShaderResourceCacheImplType    m_ShaderResourceCache;
    ShaderVariableManagerImplType* m_pShaderVarMgrs = nullptr; // [GetNumShaders()]

    bool m_bStaticResourcesInitialized = false;
};

} // namespace Diligent
<commit_msg>Fixed issue with destruction of ShaderResourceBindingBase<commit_after>/*
 *  Copyright 2019-2021 Diligent Graphics LLC
 *  Copyright 2015-2019 Egor Yusov
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  In no event and under no legal theory, whether in tort (including negligence),
 *  contract, or otherwise, unless required by applicable law (such as deliberate
 *  and grossly negligent acts) or agreed to in writing, shall any Contributor be
 *  liable for any damages, including any direct, indirect, special, incidental,
 *  or consequential damages of any character arising as a result of this License or
 *  out of the use or inability to use the software (including but not limited to damages
 *  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
 *  all other commercial damages or losses), even if such Contributor has been advised
 *  of the possibility of such damages.
 */

#pragma once

/// \file
/// Implementation of the Diligent::ShaderResourceBindingBase template class

#include <array>
#include <functional>

#include "PrivateConstants.h"
#include "ShaderResourceBinding.h"
#include "ObjectBase.hpp"
#include "GraphicsTypes.h"
#include "Constants.h"
#include "RefCntAutoPtr.hpp"
#include "GraphicsAccessories.hpp"
#include "ShaderResourceCacheCommon.hpp"
#include "FixedLinearAllocator.hpp"
#include "EngineMemory.h"

namespace Diligent
{

/// Template class implementing base functionality of the shader resource binding

/// \tparam EngineImplTraits - Engine implementation type traits.
template <typename EngineImplTraits>
class ShaderResourceBindingBase : public ObjectBase<typename EngineImplTraits::ShaderResourceBindingInterface>
{
public:
    // Base interface this class inherits (IShaderResourceBindingD3D12, IShaderResourceBindingVk, etc.)
    using BaseInterface = typename EngineImplTraits::ShaderResourceBindingInterface;

    // The type of the pipeline resource signature implementation (PipelineResourceSignatureD3D12Impl, PipelineResourceSignatureVkImpl, etc.).
    using ResourceSignatureType = typename EngineImplTraits::PipelineResourceSignatureImplType;

    // The type of the shader resource cache implementation (ShaderResourceCacheD3D12Impl, ShaderResourceCacheVkImpl, etc.)
    using ShaderResourceCacheImplType = typename EngineImplTraits::ShaderResourceCacheImplType;

    // The type of the shader resource variable manager (ShaderVariableManagerD3D12Impl, ShaderVariableManagerVkImpl, etc.)
    using ShaderVariableManagerImplType = typename EngineImplTraits::ShaderVariableManagerImplType;

    using TObjectBase = ObjectBase<BaseInterface>;

    /// \param pRefCounters - Reference counters object that controls the lifetime of this SRB.
    /// \param pPRS         - Pipeline resource signature that this SRB belongs to.
    ShaderResourceBindingBase(IReferenceCounters* pRefCounters, ResourceSignatureType* pPRS) :
        TObjectBase{pRefCounters},
        m_pPRS{pPRS},
        m_ShaderResourceCache{ResourceCacheContentType::SRB}
    {
        try
        {
            m_ActiveShaderStageIndex.fill(-1);

            const auto NumShaders   = GetNumShaders();
            const auto PipelineType = GetPipelineType();
            for (Uint32 s = 0; s < NumShaders; ++s)
            {
                const auto ShaderType = pPRS->GetActiveShaderStageType(s);
                const auto ShaderInd  = GetShaderTypePipelineIndex(ShaderType, PipelineType);

                m_ActiveShaderStageIndex[ShaderInd] = static_cast<Int8>(s);
            }

            FixedLinearAllocator MemPool{GetRawAllocator()};
            MemPool.AddSpace<ShaderVariableManagerImplType>(NumShaders);
            MemPool.Reserve();
            static_assert(std::is_nothrow_constructible<ShaderVariableManagerImplType, decltype(*this), ShaderResourceCacheImplType&>::value,
                          "Constructor of ShaderVariableManagerImplType must be noexcept, so we can safely construct all managers");
            m_pShaderVarMgrs = MemPool.ConstructArray<ShaderVariableManagerImplType>(NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache));

            // The memory is now owned by ShaderResourceBindingBase and will be freed by Destruct().
            auto* Ptr = MemPool.ReleaseOwnership();
            VERIFY_EXPR(Ptr == m_pShaderVarMgrs);
            (void)Ptr;

            // It is important to construct all objects before initializing them because if an exception is thrown,
            // Destruct() will call destructors for all non-null objects.

            pPRS->InitSRBResourceCache(m_ShaderResourceCache);

            auto& SRBMemAllocator = pPRS->GetSRBMemoryAllocator();
            for (Uint32 s = 0; s < NumShaders; ++s)
            {
                const auto ShaderType = pPRS->GetActiveShaderStageType(s);
                const auto ShaderInd  = GetShaderTypePipelineIndex(ShaderType, pPRS->GetPipelineType());
                const auto MgrInd     = m_ActiveShaderStageIndex[ShaderInd];
                VERIFY_EXPR(MgrInd >= 0 && MgrInd < static_cast<int>(NumShaders));

                auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);

                // Initialize vars manager to reference mutable and dynamic variables
                // Note that the cache has space for all variable types
                const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
                m_pShaderVarMgrs[MgrInd].Initialize(*pPRS, VarDataAllocator, VarTypes, _countof(VarTypes), ShaderType);
            }
        }
        catch (...)
        {
            // We must release objects manually as destructor will not be called.
            Destruct();
            throw;
        }
    }

    ~ShaderResourceBindingBase()
    {
        Destruct();
    }

    IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBinding, TObjectBase)

    Uint32 GetBindingIndex() const
    {
        return m_pPRS->GetDesc().BindingIndex;
    }

    PIPELINE_TYPE GetPipelineType() const
    {
        return m_pPRS->GetPipelineType();
    }

    Uint32 GetNumShaders() const
    {
        return m_pPRS->GetNumActiveShaderStages();
    }

    /// Implementation of IShaderResourceBinding::GetPipelineResourceSignature().
    virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetPipelineResourceSignature() const override final
    {
        return GetSignature();
    }

    virtual bool DILIGENT_CALL_TYPE StaticResourcesInitialized() const override final
    {
        return m_bStaticResourcesInitialized;
    }

    ResourceSignatureType* GetSignature() const
    {
        return m_pPRS.template RawPtr<ResourceSignatureType>();
    }

    void SetStaticResourcesInitialized()
    {
        VERIFY_EXPR(!m_bStaticResourcesInitialized);
        m_bStaticResourcesInitialized = true;
    }

    /// Implementation of IShaderResourceBinding::GetVariableByName().
    virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "' in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return nullptr;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return nullptr;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariable(Name);
    }

    /// Implementation of IShaderResourceBinding::GetVariableCount().
    virtual Uint32 DILIGENT_CALL_TYPE GetVariableCount(SHADER_TYPE ShaderType) const override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return 0;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return 0;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariableCount();
    }

    /// Implementation of IShaderResourceBinding::GetVariableByIndex().
    virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final
    {
        const auto PipelineType = GetPipelineType();
        if (!IsConsistentShaderType(ShaderType, PipelineType))
        {
            LOG_WARNING_MESSAGE("Unable to get mutable/dynamic variable at index ", Index, " in shader stage ", GetShaderTypeLiteralName(ShaderType),
                                " as the stage is invalid for ", GetPipelineTypeString(PipelineType), " pipeline resource signature '", m_pPRS->GetDesc().Name, "'.");
            return nullptr;
        }

        const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PipelineType);
        const auto MgrInd    = m_ActiveShaderStageIndex[ShaderInd];
        if (MgrInd < 0)
            return nullptr;

        VERIFY_EXPR(static_cast<Uint32>(MgrInd) < GetNumShaders());
        return m_pShaderVarMgrs[MgrInd].GetVariable(Index);
    }

    /// Implementation of IShaderResourceBinding::BindResources().
    virtual void DILIGENT_CALL_TYPE BindResources(Uint32            ShaderFlags,
                                                  IResourceMapping* pResMapping,
                                                  Uint32            Flags) override final
    {
        const auto PipelineType = GetPipelineType();
        for (Int32 ShaderInd = 0; ShaderInd < static_cast<Int32>(m_ActiveShaderStageIndex.size()); ++ShaderInd)
        {
            auto VarMngrInd = m_ActiveShaderStageIndex[ShaderInd];
            if (VarMngrInd >= 0)
            {
                // ShaderInd is the shader type pipeline index here
                const auto ShaderType = GetShaderTypeFromPipelineIndex(ShaderInd, PipelineType);
                if ((ShaderFlags & ShaderType) != 0)
                {
                    m_pShaderVarMgrs[VarMngrInd].BindResources(pResMapping, Flags);
                }
            }
        }
    }

    ShaderResourceCacheImplType&       GetResourceCache() { return m_ShaderResourceCache; }
    const ShaderResourceCacheImplType& GetResourceCache() const { return m_ShaderResourceCache; }

private:
    void Destruct()
    {
        if (m_pShaderVarMgrs != nullptr)
        {
            auto& SRBMemAllocator = GetSignature()->GetSRBMemoryAllocator();
            for (Uint32 s = 0; s < GetNumShaders(); ++s)
            {
                auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
                m_pShaderVarMgrs[s].Destroy(VarDataAllocator);
                m_pShaderVarMgrs[s].~ShaderVariableManagerImplType();
            }
            GetRawAllocator().Free(m_pShaderVarMgrs);
        }
    }

protected:
    /// Strong reference to pipeline resource signature. We must use strong reference, because
    /// shader resource binding uses pipeline resource signature's memory allocator to allocate
    /// memory for shader resource cache.
    RefCntAutoPtr<ResourceSignatureType> m_pPRS;

    // Index of the active shader stage that has resources, for every shader
    // type in the pipeline (given by GetShaderTypePipelineIndex(ShaderType, m_PipelineType)).
    std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ActiveShaderStageIndex = {-1, -1, -1, -1, -1, -1};
    static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");

    ShaderResourceCacheImplType    m_ShaderResourceCache;
    ShaderVariableManagerImplType* m_pShaderVarMgrs = nullptr; // [GetNumShaders()]

    bool m_bStaticResourcesInitialized = false;
};

} // namespace Diligent
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "PlatformWin.h"
#include "Framework.h"

#if defined(_WINDOWS)

namespace Foundation
{
    std::string PlatformWin::GetApplicationDataDirectory()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            char cpath[MAX_PATH];
            SHGetPathFromIDListA( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::string(cpath) + "\\" + framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name");
        }
        throw Core::Exception("Failed to access application data directory.");
    }

    std::wstring PlatformWin::GetApplicationDataDirectoryW()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            wchar_t cpath[MAX_PATH];
            SHGetPathFromIDListW( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::wstring(cpath) + L"\\" + Core::ToWString(framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name"));
        }
        throw Core::Exception("Failed to access application data directory.");
    }

    std::string PlatformWin::GetUserDocumentsDirectory()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            char cpath[MAX_PATH];
            SHGetPathFromIDListA( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::string(cpath) + "\\" + framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name");
        }
        throw Core::Exception("Failed to access user documents directory.");
    }

    std::wstring PlatformWin::GetUserDocumentsDirectoryW()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            wchar_t cpath[MAX_PATH];
            SHGetPathFromIDListW( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::wstring(cpath) + L"\\" + Core::ToWString(framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name"));
        }
        throw Core::Exception("Failed to access user documents directory.");
    }
}

#endif

<commit_msg>Using CSIDL_PERSONAL instead of CSIDL_MYDOCUMENTS, because Vista doesn't seem to like the latter.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "PlatformWin.h"
#include "Framework.h"

#if defined(_WINDOWS)

namespace Foundation
{
    std::string PlatformWin::GetApplicationDataDirectory()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            char cpath[MAX_PATH];
            SHGetPathFromIDListA( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::string(cpath) + "\\" + framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name");
        }
        throw Core::Exception("Failed to access application data directory.");
    }

    std::wstring PlatformWin::GetApplicationDataDirectoryW()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            wchar_t cpath[MAX_PATH];
            SHGetPathFromIDListW( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::wstring(cpath) + L"\\" + Core::ToWString(framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name"));
        }
        throw Core::Exception("Failed to access application data directory.");
    }

    std::string PlatformWin::GetUserDocumentsDirectory()
    {
        LPITEMIDLIST pidl;

        if (SHGetFolderLocation(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, &pidl) == S_OK)
        {
            char cpath[MAX_PATH];
            SHGetPathFromIDListA( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::string(cpath) + "\\" + framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name");
        }
        throw Core::Exception("Failed to access user documents directory.");
    }

    std::wstring PlatformWin::GetUserDocumentsDirectoryW()
    {
        LPITEMIDLIST pidl;

        int res = SHGetFolderLocation(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, &pidl);
        if (res == S_OK)
        {
            wchar_t cpath[MAX_PATH];
            SHGetPathFromIDListW( pidl, cpath );
            CoTaskMemFree(pidl);

            return std::wstring(cpath) + L"\\" + Core::ToWString(framework_->GetDefaultConfig().GetString(Framework::ConfigurationGroup(), "application_name"));
        }
        if (res == E_INVALIDARG)
        throw Core::Exception("Failed to access user documents directory.");
        else
           throw Core::Exception("Failed to access user documents directory.");
    }
}

#endif

<|endoftext|>


<commit_before>// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file DataWriterQos.hpp
 */

#include <fastdds/statistics/dds/subscriber/qos/DataReaderQos.hpp>

#include <fastdds/dds/core/policy/QosPolicies.hpp>

namespace eprosima {
namespace fastdds {
namespace statistics {
namespace dds {

DataReaderQos::DataReaderQos()
{
    // Specific implementation for recommended statistics DataReaderQos
    reliability().kind = eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS;
    durability().kind = eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS;
    history().kind = eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS;
    history().depth = 100;
}

} // dds
} // statistics
} // fastdds
} // eprosima
<commit_msg>Set recommended statistics DataReaderQos to PREALLOCATED_WITH_REALLOC (#2551)<commit_after>// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file DataWriterQos.hpp
 */

#include <fastdds/statistics/dds/subscriber/qos/DataReaderQos.hpp>

#include <fastdds/dds/core/policy/QosPolicies.hpp>
#include <fastdds/rtps/resources/ResourceManagement.h>

namespace eprosima {
namespace fastdds {
namespace statistics {
namespace dds {

DataReaderQos::DataReaderQos()
{
    /* Specific implementation for recommended statistics DataReaderQos */
    reliability().kind = eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS;
    durability().kind = eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS;
    history().kind = eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS;
    history().depth = 100;
    // Setting history memory policy to PREALLOCATED_WITH_REALLOC_MEMORY_MODE allows for future type
    // extension with backwards compatibility
    endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE;
}

} // dds
} // statistics
} // fastdds
} // eprosima
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// model a single track chain system, as part of a tracked vehicle. Uses JSON input files
//
// =============================================================================

#include <cstdio>

#include "subsys/trackSystem/TrackSystem.h"

namespace chrono {

// -----------------------------------------------------------------------------
// Static variables

// idler
const ChVector<> TrackSystem::m_idlerPos(-2.0, 0.75, 0);
const ChQuaternion<> TrackSystem::m_idlerRot(QUNIT);

// drive gear
const ChVector<> TrackSystem::m_gearPos(2.0, 0.75, 0);
const ChQuaternion<> TrackSystem::m_gearRot(QUNIT);

// Support rollers
const int TrackSystem::m_numRollers = 0;
const double TrackSystem::m_rollerMass = 100.0;
const double TrackSystem::m_roller_radius = 0.2;
const double TrackSystem::m_roller_width = 0.2;

// suspension
// const std::string m_suspensionFilename;
const int TrackSystem::m_numSuspensions = 5;

TrackSystem::TrackSystem(const std::string& name, int track_idx)
  : m_track_idx(track_idx), m_name(name)
{
  // FILE* fp = fopen(filename.c_str(), "r");
  // char readBuffer[65536];
  // fclose(fp);

  Create(track_idx);

}

// Create: 1) load/set the subsystem data, 2) use data to build subsystems
void TrackSystem::Create(int track_idx)
{
  /*
  // read idler info
  assert(d.HasMember("Idler"));
  m_idlerMass = d["Idler"]["Mass"].GetDouble();
  m_idlerPos = loadVector(d["Idler"]["Location"]);
  m_idlerInertia = loadVector(d["Idler"]["Inertia"]);
  m_idlerRadius = d["Spindle"]["Radius"].GetDouble();
  m_idlerWidth = d["Spindle"]["Width"].GetDouble();
  m_idler_K = d["Idler"]["SpringK"].GetDouble();
  m_idler_C = d["Idler"]["SpringC"].GetDouble();

  // Read Drive Gear data
  assert(d.HasMember("Drive Gear"));
  assert(d["Drive Gear"].IsObject());

  m_gearMass = d["Drive Gear"]["Mass"].GetDouble();
  m_gearPos = loadVector(d["Drive Gear"]["Location"]);
  m_gearInertia = loadVector(d["Drive Gear"]["Inertia"]);
  m_gearRadius = d["Drive Gear"]["Radius"].GetDouble();
  m_gearWidth = d["Drive Gear"]["Width"].GetDouble();

  // Read Support Roller info
  assert(d.HasMember("Support Roller"));
  assert(d["Support Roller"].IsObject());

  m_rollerMass = d["Support Roller"]["Mass"].GetDouble();
  m_rollerInertia = loadVector(d["Support Roller"]["Inertia"]);
  m_rollerRadius = d["Support Roller"]["Radius"].GetDouble();
  m_rollerWidth = d["Support Roller"]["Width"].GetDouble();

  assert(d["Support Roller"]["Location"].IsArray());
  m_NumRollers = d["Support Roller"]["Location"].Size();

  m_rollerLocs.resize(m_NumRollers);
  for(int i = 0; i < m_NumRollers; i++ )
  {
	m_rollerLocs[i] = loadVector(d["Support Roller"]["Location"][i]);
  }

  // Read Suspension data
  assert(d.HasMember("Suspension"));
  assert(d["Suspension"].IsObject());
  assert(d["Suspension"]["Location"].IsArray() );

  m_suspensionFilename = d["Suspension"]["Input File"].GetString();
  m_NumSuspensions = d["Suspension"]["Location"].Size();

  m_suspensionLocs.resize(m_NumSuspensions);
  for(int j = 0; j < m_NumSuspensions; j++)
  {
    m_suspensionLocs[j] = loadVector(d["Suspension"]["Locaiton"][j]);
  }

  // Read Track Chain data
  assert(d.HasMember("Track Chain"));
  assert(d["Track Chain"].IsObject());
  m_trackChainFilename = d["Track Chain"]["Input File"].GetString()

  */

  // create the various subsystems, from the hardcoded static variables in each subsystem class
  BuildSubsystems();

}

void TrackSystem::BuildSubsystems()
{
  // build one of each of the following subsystems. VisualizationType and CollisionType defaults are PRIMITIVES
  m_driveGear = ChSharedPtr<DriveGear>(new DriveGear("drive gear "+std::to_string(m_track_idx)) );
  m_idler = ChSharedPtr<IdlerSimple>(new IdlerSimple("idler "+std::to_string(m_track_idx)) );
  m_chain = ChSharedPtr<TrackChain>(new TrackChain("chain "+std::to_string(m_track_idx)) );

  // build suspension/road wheel subsystems
  m_suspensions.resize(m_numSuspensions);
  for(int i = 0; i < m_numSuspensions; i++)
  {
    m_suspensions[i] = ChSharedPtr<TorsionArmSuspension>(new TorsionArmSuspension("suspension "+std::to_string(i) +", chain "+std::to_string(m_track_idx)) );
  }

  // build support wheel subsystems (if any)
  m_supportRollers.resize(m_numRollers);
  m_supportRollers_rev.resize(m_numRollers);
  for(int j = 0; j < m_numRollers; j++)
  {
    m_supportRollers[j] = ChSharedPtr<ChBody>(new ChBody);
    m_supportRollers[j]->SetNameString("support roller"+std::to_string(j)+", chain "+std::to_string(m_track_idx) );
  }

}

void TrackSystem::Initialize(ChSharedPtr<ChBodyAuxRef> chassis,
			 const ChVector<>&  location)
{
  // initialize 1 of each of the following subsystems:
  m_driveGear->Initialize(chassis, m_gearPos, QUNIT);
  m_idler->Initialize(chassis, m_idlerPos, QUNIT);

  // initialize the road wheels & torsion arm suspension subsystems
  for(int i = 0; i < m_suspensionLocs.size(); i++)
  {
    m_suspensions[i]->Initialize(chassis, m_suspensionLocs[i], QUNIT);
  }

  // initialize the support rollers
  for(int j = 0; j < m_rollerLocs.size(); j++)
  {
    initialize_roller(m_supportRollers[j], chassis,
      m_rollerLocs[j], QUNIT, j);
  }

}

// initialize a roller at the specified location and orientation, w.r.t. TrackSystem c-sys
void TrackSystem::initialize_roller(ChSharedPtr<ChBody> body, ChSharedPtr<ChBodyAuxRef>  chassis,
                                    const ChVector<>& loc, const ChQuaternion<>& rot, int idx)
{
  // express loc and rot in the global c-sys
  ChFrame<> frame_to_abs(loc, rot);

  body->SetPos(loc);
  body->SetRot(rot);
  body->SetMass(m_rollerMass);

  // transform point to absolute frame and initialize

  // add the revolute joint at the location and w/ orientation specified

  // Add a visual asset
}

} // end namespace chrono
<commit_msg>provide the points, their clearance/offset and a valid start location to TrackChain->Init<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// model a single track chain system, as part of a tracked vehicle. Uses JSON input files
//
// =============================================================================

#include <cstdio>

#include "subsys/trackSystem/TrackSystem.h"

namespace chrono {

// -----------------------------------------------------------------------------
// Static variables

// idler
const ChVector<> TrackSystem::m_idlerPos(-2.0, 0.75, 0);
const ChQuaternion<> TrackSystem::m_idlerRot(QUNIT);

// drive gear
const ChVector<> TrackSystem::m_gearPos(2.0, 0.75, 0);
const ChQuaternion<> TrackSystem::m_gearRot(QUNIT);

// Support rollers
const int TrackSystem::m_numRollers = 0;
const double TrackSystem::m_rollerMass = 100.0;
const double TrackSystem::m_roller_radius = 0.2;
const double TrackSystem::m_roller_width = 0.2;

// suspension
// const std::string m_suspensionFilename;
const int TrackSystem::m_numSuspensions = 5;

TrackSystem::TrackSystem(const std::string& name, int track_idx)
  : m_track_idx(track_idx), m_name(name)
{
  // FILE* fp = fopen(filename.c_str(), "r");
  // char readBuffer[65536];
  // fclose(fp);

  Create(track_idx);

}

// Create: 1) load/set the subsystem data, 2) use data to build subsystems
void TrackSystem::Create(int track_idx)
{
  /*
  // read idler info
  assert(d.HasMember("Idler"));
  m_idlerMass = d["Idler"]["Mass"].GetDouble();
  m_idlerPos = loadVector(d["Idler"]["Location"]);
  m_idlerInertia = loadVector(d["Idler"]["Inertia"]);
  m_idlerRadius = d["Spindle"]["Radius"].GetDouble();
  m_idlerWidth = d["Spindle"]["Width"].GetDouble();
  m_idler_K = d["Idler"]["SpringK"].GetDouble();
  m_idler_C = d["Idler"]["SpringC"].GetDouble();

  // Read Drive Gear data
  assert(d.HasMember("Drive Gear"));
  assert(d["Drive Gear"].IsObject());

  m_gearMass = d["Drive Gear"]["Mass"].GetDouble();
  m_gearPos = loadVector(d["Drive Gear"]["Location"]);
  m_gearInertia = loadVector(d["Drive Gear"]["Inertia"]);
  m_gearRadius = d["Drive Gear"]["Radius"].GetDouble();
  m_gearWidth = d["Drive Gear"]["Width"].GetDouble();

  // Read Support Roller info
  assert(d.HasMember("Support Roller"));
  assert(d["Support Roller"].IsObject());

  m_rollerMass = d["Support Roller"]["Mass"].GetDouble();
  m_rollerInertia = loadVector(d["Support Roller"]["Inertia"]);
  m_rollerRadius = d["Support Roller"]["Radius"].GetDouble();
  m_rollerWidth = d["Support Roller"]["Width"].GetDouble();

  assert(d["Support Roller"]["Location"].IsArray());
  m_NumRollers = d["Support Roller"]["Location"].Size();

  m_rollerLocs.resize(m_NumRollers);
  for(int i = 0; i < m_NumRollers; i++ )
  {
	m_rollerLocs[i] = loadVector(d["Support Roller"]["Location"][i]);
  }

  // Read Suspension data
  assert(d.HasMember("Suspension"));
  assert(d["Suspension"].IsObject());
  assert(d["Suspension"]["Location"].IsArray() );

  m_suspensionFilename = d["Suspension"]["Input File"].GetString();
  m_NumSuspensions = d["Suspension"]["Location"].Size();

  m_suspensionLocs.resize(m_NumSuspensions);
  for(int j = 0; j < m_NumSuspensions; j++)
  {
    m_suspensionLocs[j] = loadVector(d["Suspension"]["Locaiton"][j]);
  }

  // Read Track Chain data
  assert(d.HasMember("Track Chain"));
  assert(d["Track Chain"].IsObject());
  m_trackChainFilename = d["Track Chain"]["Input File"].GetString()

  */

  // create the various subsystems, from the hardcoded static variables in each subsystem class
  BuildSubsystems();

}

void TrackSystem::BuildSubsystems()
{
  // build one of each of the following subsystems. VisualizationType and CollisionType defaults are PRIMITIVES
  m_driveGear = ChSharedPtr<DriveGear>(new DriveGear("drive gear "+std::to_string(m_track_idx)) );
  m_idler = ChSharedPtr<IdlerSimple>(new IdlerSimple("idler "+std::to_string(m_track_idx)) );
  m_chain = ChSharedPtr<TrackChain>(new TrackChain("chain "+std::to_string(m_track_idx)) );

  // build suspension/road wheel subsystems
  m_suspensions.resize(m_numSuspensions);
  for(int i = 0; i < m_numSuspensions; i++)
  {
    m_suspensions[i] = ChSharedPtr<TorsionArmSuspension>(new TorsionArmSuspension("suspension "+std::to_string(i) +", chain "+std::to_string(m_track_idx)) );
  }

  // build support wheel subsystems (if any)
  m_supportRollers.resize(m_numRollers);
  m_supportRollers_rev.resize(m_numRollers);
  for(int j = 0; j < m_numRollers; j++)
  {
    m_supportRollers[j] = ChSharedPtr<ChBody>(new ChBody);
    m_supportRollers[j]->SetNameString("support roller"+std::to_string(j)+", chain "+std::to_string(m_track_idx) );
  }

}

void TrackSystem::Initialize(ChSharedPtr<ChBodyAuxRef> chassis,
			 const ChVector<>&  location)
{
  // to create the track chain, need a list of control points and their clearance.
  // Points are centerof spheres with radius = clearance. Use a starting point on
  // the line, and the chain will be "wrapped" around the x-direction initially.
  // NOTE: MUST add the idler and sprocket as the first and last entries in the two lists,
  // ensures a list that is in an order than can be traversed successfully
  // by the TrackChain->Initilize() func.
  std::vector<ChVector<>> control_points;
  std::vector<double> clearance;

  // initialize 1 of each of the following subsystems:
  m_driveGear->Initialize(chassis, m_gearPos, QUNIT);
  m_idler->Initialize(chassis, m_idlerPos, QUNIT);

  // drive sprocket is First added to the lists passed into TrackChain Init()
  control_points.push_back(m_driveGear->GetBody()->GetPos() );
  clearance.push_back(m_driveGear->GetRadius() );

  // initialize the road wheels & torsion arm suspension subsystems
  for(int i = 0; i < m_suspensionLocs.size(); i++)
  {
    m_suspensions[i]->Initialize(chassis, m_suspensionLocs[i], QUNIT);

    // add these to the lists passed into the track chain
    control_points.push_back(m_suspensions[i]->GetWheelBody()->GetPos() );
    clearance.push_back(m_suspensions[i]->GetWheelRadius() );
  }

  // initialize the support rollers
  for(int j = 0; j < m_rollerLocs.size(); j++)
  {
    initialize_roller(m_supportRollers[j], chassis, m_rollerLocs[j], QUNIT, j);

    // add these to the points passed into the track chain
    control_points.push_back(m_supportRollers[j]->GetPos() );
    clearance.push_back( m_roller_radius);
  }

  // last control point: the idler body
  control_points.push_back(m_idler->GetBody()->GetPos() );
  clearance.push_back(m_idler->GetRadius() );

  // last, initialize the trackChain.
  // Starting position will be between idler and gear control points, with a vertical offset
  // that is the average of the two clearances.
  ChVector<> start_pos = (control_points[0] + control_points[control_points.size()-1])/2.0;
  start_pos.y += (clearance[0] + clearance[clearance.size()-1] )/2.0;

  m_chain->Initialize(control_points, clearance, start_pos);
}

// initialize a roller at the specified location and orientation, w.r.t. TrackSystem c-sys
void TrackSystem::initialize_roller(ChSharedPtr<ChBody> body, ChSharedPtr<ChBodyAuxRef>  chassis,
                                    const ChVector<>& loc, const ChQuaternion<>& rot, int idx)
{
  // express loc and rot in the global c-sys
  ChFrame<> frame_to_abs(loc, rot);

  body->SetPos(loc);
  body->SetRot(rot);
  body->SetMass(m_rollerMass);

  // transform point to absolute frame and initialize

  // add the revolute joint at the location and w/ orientation specified

  // Add a visual asset
}

} // end namespace chrono
<|endoftext|>


<commit_before>//
//  File: DKTimer.cpp
//  Author: Hongtae Kim (tiff2766@gmail.com)
//
//  Copyright (c) 2004-2016 Hongtae Kim. All rights reserved.
//

#include <time.h>
#include <math.h>

#ifdef _WIN32
	#include <windows.h>
#elif defined(__APPLE__) && defined(__MACH__)
	#include <mach/mach.h>
	#include <mach/mach_time.h>
#elif defined(__linux__)
	#include <time.h>
#else
	#include <sys/time.h>
	#warning High-Resolution Timer Unsupported. (Unknown OS)
#endif

#include "DKTimer.h"

using namespace DKFoundation;

DKTimer::DKTimer(void)
	: timeStamp(0)
{
	Reset();
}

DKTimer::~DKTimer(void)
{
}

double DKTimer::Reset(void)
{
	static double freq = static_cast<double>(SystemTickFrequency());
	Tick t = timeStamp;
	timeStamp = SystemTick();
	return static_cast<double>(timeStamp - t) / freq;
}

double DKTimer::Elapsed(void) const
{
	static double freq = static_cast<double>(SystemTickFrequency());
	return static_cast<double>(SystemTick() - timeStamp) / freq;
}

DKTimer::Tick DKTimer::SystemTick(void)
{
#ifdef _WIN32
	static LARGE_INTEGER frequency;
	static BOOL counterEnabled = ::QueryPerformanceFrequency(&frequency);
	if (counterEnabled)
	{
		LARGE_INTEGER count;
		::QueryPerformanceCounter(&count);
		return count.QuadPart;
	}
	return ::GetTickCount();
#elif defined(__APPLE__) && defined(__MACH__)
	return mach_absolute_time();
#elif defined(__linux__)
    struct timespec ts;
    ts.tv_sec = 0;
	ts.tv_nsec = 0;
    clock_gettime(CLOCK_MONOTONIC_HR, &ts);
	return static_cast<Tick>(ts.tv_sec) * 1000000000ULL + ts.tv_nsec;
#else
	timeval tm;
	gettimeofday(&tm, NULL);
	return static_cast<Tick>(tm.tv_sec) * 1000000ULL + tm.tv_usec;
#endif
}

DKTimer::Tick DKTimer::SystemTickFrequency(void)
{
#ifdef _WIN32
	static LARGE_INTEGER frequency;
	static BOOL counterEnabled = ::QueryPerformanceFrequency(&frequency);
	if (counterEnabled)
	{
		return frequency.QuadPart;
	}
	return 1000ULL;
#elif defined(__APPLE__) && defined(__MACH__)
	static struct MachTimeBase
	{
		MachTimeBase(void)
		{
			mach_timebase_info_data_t base;
			mach_timebase_info(&base);
			frequency = 1000000000ULL * base.denom / base.numer;
		}
		uint64_t frequency;
	} machTime;
	return machTime.frequency;
#elif defined(__linux__)
	return 1000000000ULL;
#else
	return 1000000ULL;
#endif
}
<commit_msg>no message<commit_after>//
//  File: DKTimer.cpp
//  Author: Hongtae Kim (tiff2766@gmail.com)
//
//  Copyright (c) 2004-2016 Hongtae Kim. All rights reserved.
//

#include <time.h>
#include <math.h>

#ifdef _WIN32
	#include <windows.h>
#elif defined(__APPLE__) && defined(__MACH__)
	#include <mach/mach.h>
	#include <mach/mach_time.h>
#elif defined(__linux__)
	#include <time.h>
#else
	#include <sys/time.h>
	#warning High-Resolution Timer Unsupported. (Unknown OS)
#endif

#include "DKTimer.h"

using namespace DKFoundation;

DKTimer::DKTimer(void)
	: timeStamp(0)
{
	Reset();
}

DKTimer::~DKTimer(void)
{
}

double DKTimer::Reset(void)
{
	static double freq = 1.0 / static_cast<double>(SystemTickFrequency());
	Tick t = timeStamp;
	timeStamp = SystemTick();
	return static_cast<double>(timeStamp - t) * freq;
}

double DKTimer::Elapsed(void) const
{
	static double freq = 1.0 / static_cast<double>(SystemTickFrequency());
	return static_cast<double>(SystemTick() - timeStamp) * freq;
}

DKTimer::Tick DKTimer::SystemTick(void)
{
#ifdef _WIN32
	LARGE_INTEGER count;
	::QueryPerformanceCounter(&count);
	return count.QuadPart;
#elif defined(__APPLE__) && defined(__MACH__)
	return mach_absolute_time();
#elif defined(__linux__)
    struct timespec ts;
    ts.tv_sec = 0;
	ts.tv_nsec = 0;
    clock_gettime(CLOCK_MONOTONIC_HR, &ts);
	return static_cast<Tick>(ts.tv_sec) * 1000000000ULL + ts.tv_nsec;
#else
	timeval tm;
	gettimeofday(&tm, NULL);
	return static_cast<Tick>(tm.tv_sec) * 1000000ULL + tm.tv_usec;
#endif
}

DKTimer::Tick DKTimer::SystemTickFrequency(void)
{
#ifdef _WIN32
	static LONGLONG frequency = []()->LONGLONG
	{
		LARGE_INTEGER frequency;
		::QueryPerformanceFrequency(&frequency);
		return frequency.QuadPart;
	}();
	return frequency;
#elif defined(__APPLE__) && defined(__MACH__)
	static uint64_t frequency = []()->uint64_t
	{
		mach_timebase_info_data_t base;
		mach_timebase_info(&base);
		uint64_t frequency = 1000000000ULL * base.denom / base.numer;
		return frequency;
	}();
	return frequency;
#elif defined(__linux__)
	return 1000000000ULL;
#else
	return 1000000ULL;
#endif
}
<|endoftext|>


<commit_before>/**
 * @file neighbor_search_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of Neighbor-Search class to perform all-nearest-neighbors on
 * two specified data sets.
 */
#ifndef __MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP
#define __MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP

#include <mlpack/core.hpp>

#include "neighbor_search_rules.hpp"

namespace mlpack {
namespace neighbor {

//! Call the tree constructor that does mapping.
template<typename TreeType>
TreeType* BuildTree(
    typename TreeType::Mat& dataset,
    std::vector<size_t>& oldFromNew,
    typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == true, TreeType*
    >::type = 0)
{
  return new TreeType(dataset, oldFromNew);
}

//! Call the tree constructor that does not do mapping.
template<typename TreeType>
TreeType* BuildTree(
    const typename TreeType::Mat& dataset,
    const std::vector<size_t>& /* oldFromNew */,
    const typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == false, TreeType*
    >::type = 0)
{
  return new TreeType(dataset);
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::
NeighborSearch(const typename TreeType::Mat& referenceSetIn,
               const typename TreeType::Mat& querySetIn,
               const bool naive,
               const bool singleMode,
               const MetricType metric) :
    referenceSet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    querySet(tree::TreeTraits<TreeType>::RearrangesDataset ? queryCopy
        : querySetIn),
    referenceTree(NULL),
    queryTree(NULL),
    treeOwner(!naive), // False if a tree was passed.  If naive, then no trees.
    hasQuerySet(true),
    naive(naive),
    singleMode(!naive && singleMode), // No single mode if naive.
    metric(metric)
{
  // C++11 will allow us to call out to other constructors so we can avoid this
  // copy/paste problem.

  // We'll time tree building, but only if we are building trees.
  Timer::Start("tree_building");

  // Copy the datasets, if they will be modified during tree building.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    referenceCopy = referenceSetIn;
    queryCopy = querySetIn;
  }

  // If not in naive mode, then we need to build trees.
  if (!naive)
  {
    // The const_cast is safe; if RearrangesDataset == false, then it'll be
    // casted back to const anyway, and if not, referenceSet points to
    // referenceCopy, which isn't const.
    referenceTree = BuildTree<TreeType>(
        const_cast<typename TreeType::Mat&>(referenceSet),
        oldFromNewReferences);

    if (!singleMode)
      queryTree = BuildTree<TreeType>(
          const_cast<typename TreeType::Mat&>(querySet), oldFromNewQueries);
  }

  // Stop the timer we started above (if we need to).
  Timer::Stop("tree_building");
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::
NeighborSearch(const typename TreeType::Mat& referenceSetIn,
               const bool naive,
               const bool singleMode,
               const MetricType metric) :
    referenceSet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    querySet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    referenceTree(NULL),
    queryTree(NULL),
    treeOwner(!naive), // If naive, then we are not building any trees.
    hasQuerySet(false),
    naive(naive),
    singleMode(!naive && singleMode), // No single mode if naive.
    metric(metric)
{
  // We'll time tree building, but only if we are building trees.
  Timer::Start("tree_building");

  // Copy the dataset, if it will be modified during tree building.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
    referenceCopy = referenceSetIn;

  // If not in naive mode, then we may need to construct trees.
  if (!naive)
  {
    // The const_cast is safe; if RearrangesDataset == false, then it'll be
    // casted back to const anyway, and if not, referenceSet points to
    // referenceCopy, which isn't const.
    referenceTree = BuildTree<TreeType>(
        const_cast<typename TreeType::Mat&>(referenceSet),
        oldFromNewReferences);

    if (!singleMode)
      queryTree = new TreeType(*referenceTree);
  }

  // Stop the timer we started above.
  Timer::Stop("tree_building");
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::NeighborSearch(
    TreeType* referenceTree,
    TreeType* queryTree,
    const typename TreeType::Mat& referenceSet,
    const typename TreeType::Mat& querySet,
    const bool singleMode,
    const MetricType metric) :
    referenceSet(referenceSet),
    querySet(querySet),
    referenceTree(referenceTree),
    queryTree(queryTree),
    treeOwner(false),
    hasQuerySet(true),
    naive(false),
    singleMode(singleMode),
    metric(metric)
{
  // Nothing else to initialize.
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::NeighborSearch(
    TreeType* referenceTree,
    const typename TreeType::Mat& referenceSet,
    const bool singleMode,
    const MetricType metric) :
    referenceSet(referenceSet),
    querySet(referenceSet),
    referenceTree(referenceTree),
    queryTree(NULL),
    treeOwner(false),
    hasQuerySet(false), // In this case we will own a tree, if singleMode.
    naive(false),
    singleMode(singleMode),
    metric(metric)
{
  Timer::Start("tree_building");

  // The query tree cannot be the same as the reference tree.
  if (referenceTree && !singleMode)
    queryTree = new TreeType(*referenceTree);

  Timer::Stop("tree_building");
}

/**
 * The tree is the only member we may be responsible for deleting.  The others
 * will take care of themselves.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::~NeighborSearch()
{
  if (treeOwner)
  {
    if (referenceTree)
      delete referenceTree;
    if (queryTree)
      delete queryTree;
  }
  else if (!treeOwner && !hasQuerySet && !(singleMode || naive))
  {
    // We replicated the reference tree to create a query tree.
    delete queryTree;
  }
}

/**
 * Computes the best neighbors and stores them in resultingNeighbors and
 * distances.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
void NeighborSearch<SortPolicy, MetricType, TreeType>::Search(
    const size_t k,
    arma::Mat<size_t>& resultingNeighbors,
    arma::mat& distances)
{
  Timer::Start("computing_neighbors");

  // If we have built the trees ourselves, then we will have to map all the
  // indices back to their original indices when this computation is finished.
  // To avoid an extra copy, we will store the neighbors and distances in a
  // separate matrix.
  arma::Mat<size_t>* neighborPtr = &resultingNeighbors;
  arma::mat* distancePtr = &distances;

  // Mapping is only necessary if the tree rearranges points.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    if (treeOwner && !(singleMode && hasQuerySet))
      distancePtr = new arma::mat; // Query indices need to be mapped.

    if (treeOwner)
      neighborPtr = new arma::Mat<size_t>; // All indices need mapping.
  }

  // Set the size of the neighbor and distance matrices.
  neighborPtr->set_size(k, querySet.n_cols);
  neighborPtr->fill(size_t() - 1);
  distancePtr->set_size(k, querySet.n_cols);
  distancePtr->fill(SortPolicy::WorstDistance());

  // Create the helper object for the tree traversal.
  typedef NeighborSearchRules<SortPolicy, MetricType, TreeType> RuleType;
  RuleType rules(referenceSet, querySet, *neighborPtr, *distancePtr, metric);

  if (naive)
  {
    // The naive brute-force traversal.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);
  }
  else if (singleMode)
  {
    // The search doesn't work if the root node is also a leaf node.
    // if this is the case, it is suggested that you use the naive method.
    assert(!(referenceTree->IsLeaf()));

    // Create the traverser.
    typename TreeType::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    Log::Info << rules.Scores() << " node combinations were scored.\n";
    Log::Info << rules.BaseCases() << " base cases were calculated.\n";
  }
  else // Dual-tree recursion.
  {
    // Create the traverser.
    typename TreeType::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*queryTree, *referenceTree);

    Log::Info << rules.Scores() << " node combinations were scored.\n";
    Log::Info << rules.BaseCases() << " base cases were calculated.\n";
  }

  Timer::Stop("computing_neighbors");

  // Now, do we need to do mapping of indices?
  if (!treeOwner || !tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    // No mapping needed.  We are done.
    return;
  }
  else if (treeOwner && hasQuerySet && !singleMode) // Map both sets.
  {
    // Set size of output matrices correctly.
    resultingNeighbors.set_size(k, querySet.n_cols);
    distances.set_size(k, querySet.n_cols);

    for (size_t i = 0; i < distances.n_cols; i++)
    {
      // Map distances (copy a column).
      distances.col(oldFromNewQueries[i]) = distancePtr->col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; j++)
      {
        resultingNeighbors(j, oldFromNewQueries[i]) =
            oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrices.
    delete neighborPtr;
    delete distancePtr;
  }
  else if (treeOwner && !hasQuerySet)
  {
    resultingNeighbors.set_size(k, querySet.n_cols);
    distances.set_size(k, querySet.n_cols);

    for (size_t i = 0; i < distances.n_cols; i++)
    {
      // Map distances (copy a column).
      distances.col(oldFromNewReferences[i]) = distancePtr->col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; j++)
      {
        resultingNeighbors(j, oldFromNewReferences[i]) =
            oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrices.
    delete neighborPtr;
    delete distancePtr;
  }
  else if (treeOwner && hasQuerySet && singleMode) // Map only references.
  {
    // Set size of neighbor indices matrix correctly.
    resultingNeighbors.set_size(k, querySet.n_cols);

    // Map indices of neighbors.
    for (size_t i = 0; i < resultingNeighbors.n_cols; i++)
    {
      for (size_t j = 0; j < resultingNeighbors.n_rows; j++)
      {
        resultingNeighbors(j, i) = oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrix.
    delete neighborPtr;
  }
} // Search

//Return a String of the Object.
template<typename SortPolicy, typename MetricType, typename TreeType>
std::string NeighborSearch<SortPolicy, MetricType, TreeType>::ToString() const
{
  std::ostringstream convert;
  convert << "NearestNeighborSearch [" << this << "]" << std::endl;
  convert << "  Reference Set: " << referenceSet.n_rows << "x" ;
  convert <<  referenceSet.n_cols << std::endl;
  if (&referenceSet != &querySet)
    convert << "  QuerySet: " << querySet.n_rows << "x" << querySet.n_cols
        << std::endl;
  convert << "  Reference Tree: " << referenceTree << std::endl;
  if (&referenceTree != &queryTree)
    convert << "  QueryTree: " << queryTree << std::endl;
  convert << "  Tree Owner: " << treeOwner << std::endl;
  convert << "  Naive: " << naive << std::endl;
  convert << "  Metric: " << std::endl;
  convert << mlpack::util::Indent(metric.ToString(),2);
  return convert.str();
}

}; // namespace neighbor
}; // namespace mlpack

#endif
<commit_msg>Now we have C++11, but there's no constructor copypasta problem anymore.<commit_after>/**
 * @file neighbor_search_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of Neighbor-Search class to perform all-nearest-neighbors on
 * two specified data sets.
 */
#ifndef __MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP
#define __MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP

#include <mlpack/core.hpp>

#include "neighbor_search_rules.hpp"

namespace mlpack {
namespace neighbor {

//! Call the tree constructor that does mapping.
template<typename TreeType>
TreeType* BuildTree(
    typename TreeType::Mat& dataset,
    std::vector<size_t>& oldFromNew,
    typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == true, TreeType*
    >::type = 0)
{
  return new TreeType(dataset, oldFromNew);
}

//! Call the tree constructor that does not do mapping.
template<typename TreeType>
TreeType* BuildTree(
    const typename TreeType::Mat& dataset,
    const std::vector<size_t>& /* oldFromNew */,
    const typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == false, TreeType*
    >::type = 0)
{
  return new TreeType(dataset);
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::
NeighborSearch(const typename TreeType::Mat& referenceSetIn,
               const typename TreeType::Mat& querySetIn,
               const bool naive,
               const bool singleMode,
               const MetricType metric) :
    referenceSet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    querySet(tree::TreeTraits<TreeType>::RearrangesDataset ? queryCopy
        : querySetIn),
    referenceTree(NULL),
    queryTree(NULL),
    treeOwner(!naive), // False if a tree was passed.  If naive, then no trees.
    hasQuerySet(true),
    naive(naive),
    singleMode(!naive && singleMode), // No single mode if naive.
    metric(metric)
{
  // We'll time tree building, but only if we are building trees.
  Timer::Start("tree_building");

  // Copy the datasets, if they will be modified during tree building.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    referenceCopy = referenceSetIn;
    queryCopy = querySetIn;
  }

  // If not in naive mode, then we need to build trees.
  if (!naive)
  {
    // The const_cast is safe; if RearrangesDataset == false, then it'll be
    // casted back to const anyway, and if not, referenceSet points to
    // referenceCopy, which isn't const.
    referenceTree = BuildTree<TreeType>(
        const_cast<typename TreeType::Mat&>(referenceSet),
        oldFromNewReferences);

    if (!singleMode)
      queryTree = BuildTree<TreeType>(
          const_cast<typename TreeType::Mat&>(querySet), oldFromNewQueries);
  }

  // Stop the timer we started above (if we need to).
  Timer::Stop("tree_building");
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::
NeighborSearch(const typename TreeType::Mat& referenceSetIn,
               const bool naive,
               const bool singleMode,
               const MetricType metric) :
    referenceSet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    querySet(tree::TreeTraits<TreeType>::RearrangesDataset ? referenceCopy
        : referenceSetIn),
    referenceTree(NULL),
    queryTree(NULL),
    treeOwner(!naive), // If naive, then we are not building any trees.
    hasQuerySet(false),
    naive(naive),
    singleMode(!naive && singleMode), // No single mode if naive.
    metric(metric)
{
  // We'll time tree building, but only if we are building trees.
  Timer::Start("tree_building");

  // Copy the dataset, if it will be modified during tree building.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
    referenceCopy = referenceSetIn;

  // If not in naive mode, then we may need to construct trees.
  if (!naive)
  {
    // The const_cast is safe; if RearrangesDataset == false, then it'll be
    // casted back to const anyway, and if not, referenceSet points to
    // referenceCopy, which isn't const.
    referenceTree = BuildTree<TreeType>(
        const_cast<typename TreeType::Mat&>(referenceSet),
        oldFromNewReferences);

    if (!singleMode)
      queryTree = new TreeType(*referenceTree);
  }

  // Stop the timer we started above.
  Timer::Stop("tree_building");
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::NeighborSearch(
    TreeType* referenceTree,
    TreeType* queryTree,
    const typename TreeType::Mat& referenceSet,
    const typename TreeType::Mat& querySet,
    const bool singleMode,
    const MetricType metric) :
    referenceSet(referenceSet),
    querySet(querySet),
    referenceTree(referenceTree),
    queryTree(queryTree),
    treeOwner(false),
    hasQuerySet(true),
    naive(false),
    singleMode(singleMode),
    metric(metric)
{
  // Nothing else to initialize.
}

// Construct the object.
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::NeighborSearch(
    TreeType* referenceTree,
    const typename TreeType::Mat& referenceSet,
    const bool singleMode,
    const MetricType metric) :
    referenceSet(referenceSet),
    querySet(referenceSet),
    referenceTree(referenceTree),
    queryTree(NULL),
    treeOwner(false),
    hasQuerySet(false), // In this case we will own a tree, if singleMode.
    naive(false),
    singleMode(singleMode),
    metric(metric)
{
  Timer::Start("tree_building");

  // The query tree cannot be the same as the reference tree.
  if (referenceTree && !singleMode)
    queryTree = new TreeType(*referenceTree);

  Timer::Stop("tree_building");
}

/**
 * The tree is the only member we may be responsible for deleting.  The others
 * will take care of themselves.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearch<SortPolicy, MetricType, TreeType>::~NeighborSearch()
{
  if (treeOwner)
  {
    if (referenceTree)
      delete referenceTree;
    if (queryTree)
      delete queryTree;
  }
  else if (!treeOwner && !hasQuerySet && !(singleMode || naive))
  {
    // We replicated the reference tree to create a query tree.
    delete queryTree;
  }
}

/**
 * Computes the best neighbors and stores them in resultingNeighbors and
 * distances.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
void NeighborSearch<SortPolicy, MetricType, TreeType>::Search(
    const size_t k,
    arma::Mat<size_t>& resultingNeighbors,
    arma::mat& distances)
{
  Timer::Start("computing_neighbors");

  // If we have built the trees ourselves, then we will have to map all the
  // indices back to their original indices when this computation is finished.
  // To avoid an extra copy, we will store the neighbors and distances in a
  // separate matrix.
  arma::Mat<size_t>* neighborPtr = &resultingNeighbors;
  arma::mat* distancePtr = &distances;

  // Mapping is only necessary if the tree rearranges points.
  if (tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    if (treeOwner && !(singleMode && hasQuerySet))
      distancePtr = new arma::mat; // Query indices need to be mapped.

    if (treeOwner)
      neighborPtr = new arma::Mat<size_t>; // All indices need mapping.
  }

  // Set the size of the neighbor and distance matrices.
  neighborPtr->set_size(k, querySet.n_cols);
  neighborPtr->fill(size_t() - 1);
  distancePtr->set_size(k, querySet.n_cols);
  distancePtr->fill(SortPolicy::WorstDistance());

  // Create the helper object for the tree traversal.
  typedef NeighborSearchRules<SortPolicy, MetricType, TreeType> RuleType;
  RuleType rules(referenceSet, querySet, *neighborPtr, *distancePtr, metric);

  if (naive)
  {
    // The naive brute-force traversal.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);
  }
  else if (singleMode)
  {
    // The search doesn't work if the root node is also a leaf node.
    // if this is the case, it is suggested that you use the naive method.
    assert(!(referenceTree->IsLeaf()));

    // Create the traverser.
    typename TreeType::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    Log::Info << rules.Scores() << " node combinations were scored.\n";
    Log::Info << rules.BaseCases() << " base cases were calculated.\n";
  }
  else // Dual-tree recursion.
  {
    // Create the traverser.
    typename TreeType::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*queryTree, *referenceTree);

    Log::Info << rules.Scores() << " node combinations were scored.\n";
    Log::Info << rules.BaseCases() << " base cases were calculated.\n";
  }

  Timer::Stop("computing_neighbors");

  // Now, do we need to do mapping of indices?
  if (!treeOwner || !tree::TreeTraits<TreeType>::RearrangesDataset)
  {
    // No mapping needed.  We are done.
    return;
  }
  else if (treeOwner && hasQuerySet && !singleMode) // Map both sets.
  {
    // Set size of output matrices correctly.
    resultingNeighbors.set_size(k, querySet.n_cols);
    distances.set_size(k, querySet.n_cols);

    for (size_t i = 0; i < distances.n_cols; i++)
    {
      // Map distances (copy a column).
      distances.col(oldFromNewQueries[i]) = distancePtr->col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; j++)
      {
        resultingNeighbors(j, oldFromNewQueries[i]) =
            oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrices.
    delete neighborPtr;
    delete distancePtr;
  }
  else if (treeOwner && !hasQuerySet)
  {
    resultingNeighbors.set_size(k, querySet.n_cols);
    distances.set_size(k, querySet.n_cols);

    for (size_t i = 0; i < distances.n_cols; i++)
    {
      // Map distances (copy a column).
      distances.col(oldFromNewReferences[i]) = distancePtr->col(i);

      // Map indices of neighbors.
      for (size_t j = 0; j < distances.n_rows; j++)
      {
        resultingNeighbors(j, oldFromNewReferences[i]) =
            oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrices.
    delete neighborPtr;
    delete distancePtr;
  }
  else if (treeOwner && hasQuerySet && singleMode) // Map only references.
  {
    // Set size of neighbor indices matrix correctly.
    resultingNeighbors.set_size(k, querySet.n_cols);

    // Map indices of neighbors.
    for (size_t i = 0; i < resultingNeighbors.n_cols; i++)
    {
      for (size_t j = 0; j < resultingNeighbors.n_rows; j++)
      {
        resultingNeighbors(j, i) = oldFromNewReferences[(*neighborPtr)(j, i)];
      }
    }

    // Finished with temporary matrix.
    delete neighborPtr;
  }
} // Search

//Return a String of the Object.
template<typename SortPolicy, typename MetricType, typename TreeType>
std::string NeighborSearch<SortPolicy, MetricType, TreeType>::ToString() const
{
  std::ostringstream convert;
  convert << "NearestNeighborSearch [" << this << "]" << std::endl;
  convert << "  Reference Set: " << referenceSet.n_rows << "x" ;
  convert <<  referenceSet.n_cols << std::endl;
  if (&referenceSet != &querySet)
    convert << "  QuerySet: " << querySet.n_rows << "x" << querySet.n_cols
        << std::endl;
  convert << "  Reference Tree: " << referenceTree << std::endl;
  if (&referenceTree != &queryTree)
    convert << "  QueryTree: " << queryTree << std::endl;
  convert << "  Tree Owner: " << treeOwner << std::endl;
  convert << "  Naive: " << naive << std::endl;
  convert << "  Metric: " << std::endl;
  convert << mlpack::util::Indent(metric.ToString(),2);
  return convert.str();
}

}; // namespace neighbor
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>#ifndef _DNACOMMON_ANCS_HPP_
#define _DNACOMMON_ANCS_HPP_

#include <unordered_set>
#include "DNACommon.hpp"
#include "BlenderConnection.hpp"
#include "CMDL.hpp"

namespace DataSpec
{
namespace DNAANCS
{

using Actor = HECL::BlenderConnection::DataStream::Actor;

template <typename IDTYPE>
struct CharacterResInfo
{
    std::string name;
    IDTYPE cmdl;
    IDTYPE cskr;
    IDTYPE cinf;
    std::vector<std::pair<HECL::FourCC, std::pair<IDTYPE, IDTYPE>>> overlays;
};

template <typename IDTYPE>
struct AnimationResInfo
{
    std::string name;
    IDTYPE animId;
    IDTYPE evntId;
    bool additive;
};

template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
                       const ANCSDNA& ancs,
                       const HECL::ProjectPath& outPath,
                       PAKRouter& pakRouter,
                       const typename PAKRouter::EntryType& entry,
                       const SpecBase& dataspec,
                       std::function<void(const HECL::SystemChar*)> fileChanged,
                       bool force=false)
{
    /* Extract character CMDL/CSKR first */
    std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
    ancs.getCharacterResInfo(chResInfo);
    for (const auto& info : chResInfo)
    {
        const NOD::Node* node;
        const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, true);
        if (cmdlE)
        {
            HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
            if (force || cmdlPath.getPathType() == HECL::ProjectPath::Type::None)
            {
                if (!conn.createBlend(cmdlPath, HECL::BlenderConnection::BlendType::Mesh))
                    return false;

                HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(*cmdlE));
                fileChanged(bestNameView.sys_str().c_str());

                typename ANCSDNA::CSKRType cskr;
                pakRouter.lookupAndReadDNA(info.cskr, cskr);
                typename ANCSDNA::CINFType cinf;
                pakRouter.lookupAndReadDNA(info.cinf, cinf);
                using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
                RigPair rigPair(&cskr, &cinf);

                PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
                DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
                        (conn, rs, pakRouter, *cmdlE, dataspec, rigPair);

                conn.saveBlend();
            }
        }
    }

    HECL::SystemStringView bestNameView(pakRouter.getBestEntryName(entry));
    fileChanged(bestNameView.sys_str().c_str());

    /* Establish ANCS blend */
    if (!conn.createBlend(outPath, HECL::BlenderConnection::BlendType::Actor))
        return false;
    HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);

    os.format("import bpy\n"
              "from mathutils import Vector\n"
              "bpy.context.scene.name = '%s'\n"
              "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
              "\n"
              "# Using 'Blender Game'\n"
              "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
              "\n"
              "# Clear Scene\n"
              "for ob in bpy.data.objects:\n"
              "    if ob.type != 'LAMP':\n"
              "        bpy.context.scene.objects.unlink(ob)\n"
              "        bpy.data.objects.remove(ob)\n"
              "\n"
              "actor_data = bpy.context.scene.hecl_sact_data\n",
              pakRouter.getBestEntryName(entry).c_str());

    typename ANCSDNA::CINFType cinf;
    std::unordered_set<typename PAKRouter::IDType> cinfsDone;
    for (const auto& info : chResInfo)
    {
        /* Provide data to add-on */
        os.format("actor_subtype = actor_data.subtypes.add()\n"
                  "actor_subtype.name = '%s'\n\n",
                  info.name.c_str());

        /* Build CINF if needed */
        if (cinfsDone.find(info.cinf) == cinfsDone.end())
        {
            pakRouter.lookupAndReadDNA(info.cinf, cinf);
            cinf.sendCINFToBlender(os, info.cinf);
            cinfsDone.insert(info.cinf);
        }
        else
            os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
        os << "actor_subtype.linked_armature = arm_obj.name\n";

        /* Link CMDL */
        const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, true);
        if (cmdlE)
        {
            HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
            os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(),
                         pakRouter.getBestEntryName(*cmdlE).c_str(), true);

            /* Attach CMDL to CINF */
            os << "if obj.name not in bpy.context.scene.objects:\n"
                  "    bpy.context.scene.objects.link(obj)\n"
                  "obj.parent = arm_obj\n"
                  "obj.parent_type = 'ARMATURE'\n"
                  "actor_subtype.linked_mesh = obj.name\n\n";
        }

        /* Link overlays */
        for (const auto& overlay : info.overlays)
        {
            os << "overlay = actor_subtype.overlays.add()\n";
            os.format("overlay.name = '%s'\n", overlay.first.toString().c_str());

            /* Link CMDL */
            const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, true);
            if (cmdlE)
            {
                HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
                os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(),
                             pakRouter.getBestEntryName(*cmdlE).c_str(), true);

                /* Attach CMDL to CINF */
                os << "if obj.name not in bpy.context.scene.objects:\n"
                      "    bpy.context.scene.objects.link(obj)\n"
                      "obj.parent = arm_obj\n"
                      "obj.parent_type = 'ARMATURE'\n"
                      "overlay.linked_mesh = obj.name\n\n";
            }
        }
    }

    /* Get animation primitives */
    std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
    ancs.getAnimationResInfo(animResInfo);
    for (const auto& id : animResInfo)
    {
        typename ANCSDNA::ANIMType anim;
        if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true))
        {
            os.format("act = bpy.data.actions.new('%s')\n"
                      "act.use_fake_user = True\n", id.second.name.c_str());
            anim.sendANIMToBlender(os, cinf, id.second.additive);
        }

        os.format("actor_action = actor_data.actions.add()\n"
                  "actor_action.name = '%s'\n", id.second.name.c_str());
    }

    os.close();
    conn.saveBlend();
    return true;
}

}
}

#endif // _DNACOMMON_ANCS_HPP_
<commit_msg>String residency fixes<commit_after>#ifndef _DNACOMMON_ANCS_HPP_
#define _DNACOMMON_ANCS_HPP_

#include <unordered_set>
#include "DNACommon.hpp"
#include "BlenderConnection.hpp"
#include "CMDL.hpp"

namespace DataSpec
{
namespace DNAANCS
{

using Actor = HECL::BlenderConnection::DataStream::Actor;

template <typename IDTYPE>
struct CharacterResInfo
{
    std::string name;
    IDTYPE cmdl;
    IDTYPE cskr;
    IDTYPE cinf;
    std::vector<std::pair<HECL::FourCC, std::pair<IDTYPE, IDTYPE>>> overlays;
};

template <typename IDTYPE>
struct AnimationResInfo
{
    std::string name;
    IDTYPE animId;
    IDTYPE evntId;
    bool additive;
};

template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
bool ReadANCSToBlender(HECL::BlenderConnection& conn,
                       const ANCSDNA& ancs,
                       const HECL::ProjectPath& outPath,
                       PAKRouter& pakRouter,
                       const typename PAKRouter::EntryType& entry,
                       const SpecBase& dataspec,
                       std::function<void(const HECL::SystemChar*)> fileChanged,
                       bool force=false)
{
    /* Extract character CMDL/CSKR first */
    std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
    ancs.getCharacterResInfo(chResInfo);
    for (const auto& info : chResInfo)
    {
        const NOD::Node* node;
        const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, true);
        if (cmdlE)
        {
            HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
            if (force || cmdlPath.getPathType() == HECL::ProjectPath::Type::None)
            {
                if (!conn.createBlend(cmdlPath, HECL::BlenderConnection::BlendType::Mesh))
                    return false;

                std::string bestName = pakRouter.getBestEntryName(*cmdlE);
                HECL::SystemStringView bestNameView(bestName);
                fileChanged(bestNameView.sys_str().c_str());

                typename ANCSDNA::CSKRType cskr;
                pakRouter.lookupAndReadDNA(info.cskr, cskr);
                typename ANCSDNA::CINFType cinf;
                pakRouter.lookupAndReadDNA(info.cinf, cinf);
                using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
                RigPair rigPair(&cskr, &cinf);

                PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
                DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
                        (conn, rs, pakRouter, *cmdlE, dataspec, rigPair);

                conn.saveBlend();
            }
        }
    }

    std::string bestName = pakRouter.getBestEntryName(entry);
    HECL::SystemStringView bestNameView(bestName);
    fileChanged(bestNameView.sys_str().c_str());

    /* Establish ANCS blend */
    if (!conn.createBlend(outPath, HECL::BlenderConnection::BlendType::Actor))
        return false;
    HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);

    os.format("import bpy\n"
              "from mathutils import Vector\n"
              "bpy.context.scene.name = '%s'\n"
              "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
              "\n"
              "# Using 'Blender Game'\n"
              "bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
              "\n"
              "# Clear Scene\n"
              "for ob in bpy.data.objects:\n"
              "    if ob.type != 'LAMP':\n"
              "        bpy.context.scene.objects.unlink(ob)\n"
              "        bpy.data.objects.remove(ob)\n"
              "\n"
              "actor_data = bpy.context.scene.hecl_sact_data\n",
              pakRouter.getBestEntryName(entry).c_str());

    typename ANCSDNA::CINFType cinf;
    std::unordered_set<typename PAKRouter::IDType> cinfsDone;
    for (const auto& info : chResInfo)
    {
        /* Provide data to add-on */
        os.format("actor_subtype = actor_data.subtypes.add()\n"
                  "actor_subtype.name = '%s'\n\n",
                  info.name.c_str());

        /* Build CINF if needed */
        if (cinfsDone.find(info.cinf) == cinfsDone.end())
        {
            pakRouter.lookupAndReadDNA(info.cinf, cinf);
            cinf.sendCINFToBlender(os, info.cinf);
            cinfsDone.insert(info.cinf);
        }
        else
            os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
        os << "actor_subtype.linked_armature = arm_obj.name\n";

        /* Link CMDL */
        const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, true);
        if (cmdlE)
        {
            HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
            os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(),
                         pakRouter.getBestEntryName(*cmdlE).c_str(), true);

            /* Attach CMDL to CINF */
            os << "if obj.name not in bpy.context.scene.objects:\n"
                  "    bpy.context.scene.objects.link(obj)\n"
                  "obj.parent = arm_obj\n"
                  "obj.parent_type = 'ARMATURE'\n"
                  "actor_subtype.linked_mesh = obj.name\n\n";
        }

        /* Link overlays */
        for (const auto& overlay : info.overlays)
        {
            os << "overlay = actor_subtype.overlays.add()\n";
            os.format("overlay.name = '%s'\n", overlay.first.toString().c_str());

            /* Link CMDL */
            const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, true);
            if (cmdlE)
            {
                HECL::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
                os.linkBlend(cmdlPath.getAbsolutePathUTF8().c_str(),
                             pakRouter.getBestEntryName(*cmdlE).c_str(), true);

                /* Attach CMDL to CINF */
                os << "if obj.name not in bpy.context.scene.objects:\n"
                      "    bpy.context.scene.objects.link(obj)\n"
                      "obj.parent = arm_obj\n"
                      "obj.parent_type = 'ARMATURE'\n"
                      "overlay.linked_mesh = obj.name\n\n";
            }
        }
    }

    /* Get animation primitives */
    std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
    ancs.getAnimationResInfo(animResInfo);
    for (const auto& id : animResInfo)
    {
        typename ANCSDNA::ANIMType anim;
        if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true))
        {
            os.format("act = bpy.data.actions.new('%s')\n"
                      "act.use_fake_user = True\n", id.second.name.c_str());
            anim.sendANIMToBlender(os, cinf, id.second.additive);
        }

        os.format("actor_action = actor_data.actions.add()\n"
                  "actor_action.name = '%s'\n", id.second.name.c_str());
    }

    os.close();
    conn.saveBlend();
    return true;
}

}
}

#endif // _DNACOMMON_ANCS_HPP_
<|endoftext|>