<commit_before>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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.
//*****************************************************************************

#pragma once

#include <cmath>
#include <cstring>
#include <sstream>

#include "ngraph/coordinate_diff.hpp"
#include "ngraph/node.hpp"
#include "ngraph/runtime/aligned_buffer.hpp"
#include "ngraph/type/element_type.hpp"
#include "ngraph/util.hpp"

namespace ngraph
{
    namespace op
    {
        namespace v0
        {
            /// \brief Class for constants.
            class NGRAPH_API Constant : public Op
            {
            public:
                static constexpr NodeTypeInfo type_info{"Constant", 0};
                const NodeTypeInfo& get_type_info() const override { return type_info; }
                Constant() = default;
                /// \brief Constructs a tensor constant.
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A vector of literals for initializing the tensor constant. The
                ///               size of values must match the size of the shape.
                template <typename T>
                Constant(const element::Type& type, Shape shape, const std::vector<T>& values)
                    : m_element_type(type)
                    , m_shape(shape)
                    , m_data(new runtime::AlignedBuffer(shape_size(m_shape) * m_element_type.size(),
                                                        host_alignment()))
                {
                    NODE_VALIDATION_CHECK(
                        this,
                        values.size() == 1 || values.size() == shape_size(m_shape),
                        "Did not get the expected number of literals for a constant of shape ",
                        m_shape,
                        " (got ",
                        values.size(),
                        ", expected ",
                        (shape_size(m_shape) == 1 ? "" : "1 or "),
                        shape_size(m_shape),
                        ").");

                    if (values.size() == 1)
                    {
                        write_values(std::vector<T>(shape_size(m_shape), values[0]));
                    }
                    else
                    {
                        write_values(values);
                    }
                    constructor_validate_and_infer_types();
                    m_all_elements_bitwise_identical = are_all_data_elements_bitwise_identical();
                }

                /// \brief Constructs a tensor constant
                ///        This constructor is mainly to support deserialization of constants.
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A list of string values to use as the constant data.
                Constant(const element::Type& type,
                         Shape shape,
                         const std::vector<std::string>& values);

                /// \brief Constructs a tensor constant with the supplied data
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param data A void* to constant data.
                Constant(const element::Type& type, const Shape& shape, const void* data);

                Constant(const Constant& other);

                virtual ~Constant() override;

                void validate_and_infer_types() override
                {
                    infer_element_type();
                    set_output_type(0, m_element_type, m_shape);
                }

                /// \brief Returns the value of the constant node as a Shape object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Shape get_shape_val() const;
                /// \brief Returns the value of the constant node as a Strides
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Strides get_strides_val() const;
                /// \brief Returns the value of the constant node as a Coordinate
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Coordinate get_coordinate_val() const;
                /// \brief Returns the value of the constant node as a
                ///        CoordinateDiff object
                ///        Can only be used on element::i64 nodes.
                CoordinateDiff get_coordinate_diff_val() const;
                /// \brief Returns the value of the constant node as an AxisVector
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                AxisVector get_axis_vector_val() const;
                /// \brief Returns the value of the constant node as an AxisSet
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                ///        Repeated values are allowed.
                AxisSet get_axis_set_val() const;

                /// \brief Wrapper around constructing a shared_ptr of a Constant
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A vector of values to use as the constant data.
                template <typename T>
                static std::shared_ptr<op::v0::Constant>
                    create(const element::Type& type, Shape shape, const std::vector<T> values)
                {
                    auto result = std::make_shared<op::v0::Constant>(type, shape, values);
                    result->validate_and_infer_types();
                    return result;
                }

                /// \brief Wrapper around constructing a shared_ptr of a Constant
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values An initializer_list of values to use as the constant data.
                template <typename T>
                static std::shared_ptr<op::v0::Constant>
                    create(const element::Type& type, Shape shape, std::initializer_list<T> values)
                {
                    auto result =
                        std::make_shared<op::v0::Constant>(type, shape, std::vector<T>{values});
                    result->validate_and_infer_types();
                    return result;
                }

                virtual std::shared_ptr<Node>
                    copy_with_new_args(const NodeVector& new_args) const override;

                /// \return The initialization literals for the tensor constant.
                std::vector<std::string> get_value_strings() const;

                template <typename T>
                std::vector<T> get_vector() const
                {
                    if (sizeof(T) > m_element_type.size() && shape_size(m_shape) > 0)
                    {
                        throw ngraph_error("Buffer over-read");
                    }

                    std::vector<T> rc;
                    const T* p = reinterpret_cast<const T*>(m_data->get_ptr());
                    for (size_t i = 0; i < shape_size(m_shape); i++)
                    {
                        rc.push_back(p[i]);
                    }
                    return rc;
                }

                /// \brief Return the Constant's value as a vector cast to type T
                ///
                /// \tparam T  Type to which data vector's entries will be cast.
                /// \return    Constant's data vector.
                template <typename T>
                std::vector<T> cast_vector() const
                {
                    auto source_type = get_element_type();
                    switch (source_type)
                    {
                    case element::Type_t::boolean:
                    {
                        auto vector = get_vector<char>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::bf16:
                    {
                        auto vector = get_vector<bfloat16>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f16:
                    {
                        auto vector = get_vector<float16>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f32:
                    {
                        auto vector = get_vector<float>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f64:
                    {
                        auto vector = get_vector<double>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i8:
                    {
                        auto vector = get_vector<int8_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i16:
                    {
                        auto vector = get_vector<int16_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i32:
                    {
                        auto vector = get_vector<int32_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i64:
                    {
                        auto vector = get_vector<int64_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u8:
                    {
                        auto vector = get_vector<uint8_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u16:
                    {
                        auto vector = get_vector<uint16_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u32:
                    {
                        auto vector = get_vector<uint32_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u64:
                    {
                        auto vector = get_vector<uint64_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u1:
                    case element::Type_t::undefined:
                    case element::Type_t::dynamic: throw std::runtime_error("unsupported type");
                    }
                }

                const void* get_data_ptr() const { return (m_data ? m_data->get_ptr() : nullptr); }
                template <typename T>
                const T* get_data_ptr() const
                {
                    return reinterpret_cast<const T*>(get_data_ptr());
                }

                bool is_constant() const override { return true; }
                bool get_all_data_elements_bitwise_identical() const
                {
                    return m_all_elements_bitwise_identical;
                }
                std::string convert_value_to_string(size_t index) const;

            protected:
                void* get_data_ptr_nc() { return (m_data ? m_data->get_ptr() : nullptr); }
                Constant(const OutputVector& args)
                    : Op(args)
                    , m_shape({})
                {
                }

                virtual void infer_element_type() {}
                template <typename T>
                void write_values(const std::vector<T>& values)
                {
                    write_to_buffer(
                        m_element_type, m_shape, values, get_data_ptr_nc(), shape_size(m_shape));
                }

                template <typename T, typename U>
                void write_buffer(void* target, const std::vector<U>& source, size_t count)
                {
                    T* p = reinterpret_cast<T*>(target);
                    for (size_t i = 0; i < count; i++)
                    {
                        p[i] = static_cast<T>(source[i]);
                    }
                }

                template <typename T>
                void write_to_buffer(const element::Type& target_type,
                                     const Shape& /* target_shape */,
                                     const std::vector<T>& source,
                                     void* target,
                                     size_t target_element_count)
                {
                    if (source.size() != target_element_count)
                    {
                        throw std::runtime_error("Constant initializer does not match shape");
                    }
#if defined(__GNUC__) && !(__GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
                    switch (target_type)
                    {
                    case element::Type_t::boolean:
                        write_buffer<char, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::bf16:
                        write_buffer<bfloat16, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f16:
                        write_buffer<float16, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f32:
                        write_buffer<float, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f64:
                        write_buffer<double, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i8:
                        write_buffer<int8_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i16:
                        write_buffer<int16_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i32:
                        write_buffer<int32_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i64:
                        write_buffer<int64_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u8:
                        write_buffer<uint8_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u16:
                        write_buffer<uint16_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u32:
                        write_buffer<uint32_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u64:
                        write_buffer<uint64_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u1: throw std::runtime_error("unsupported type");
                    case element::Type_t::undefined: throw std::runtime_error("unsupported type");
                    case element::Type_t::dynamic: throw std::runtime_error("unsupported type");
                    }
#if defined(__GNUC__) && !(__GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic pop
#endif
                }

                static constexpr size_t host_alignment() { return 64; }
                element::Type m_element_type;
                Shape m_shape{};
                std::shared_ptr<runtime::AlignedBuffer> m_data;
                bool m_all_elements_bitwise_identical;
                bool are_all_data_elements_bitwise_identical() const;
            };

            /// \brief A scalar constant whose element type is the same as like.
            class NGRAPH_API ScalarConstantLike : public Constant
            {
            public:
                static constexpr NodeTypeInfo type_info{"ScalarConstantLike", 0};
                const NodeTypeInfo& get_type_info() const override { return type_info; }
                /// \brief A scalar constant whose element type is the same as like.
                ///
                /// Once the element type is known, the dependency on like will be removed and
                /// this node will be replaced with an equivalent constant.
                ///
                /// \param like A tensor that will supply the element type.
                /// \param value The value of the scalar.
                template <typename T>
                ScalarConstantLike(const Output<Node>& like, T value)
                    : Constant({like})
                    , m_value(static_cast<double>(value))
                {
                    constructor_validate_and_infer_types();
                }

                ScalarConstantLike() = default;

                std::shared_ptr<Node> copy_with_new_args(const NodeVector& new_args) const override;
                std::shared_ptr<op::v0::Constant> as_constant() const;

            protected:
                void infer_element_type() override;

                double m_value;
            };
        }
        using v0::Constant;
        using v0::ScalarConstantLike;
    }
}
<commit_msg>Fixed warning "control reaches end of non-void function" (#4297)<commit_after>//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// 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.
//*****************************************************************************

#pragma once

#include <cmath>
#include <cstring>
#include <sstream>

#include "ngraph/coordinate_diff.hpp"
#include "ngraph/node.hpp"
#include "ngraph/runtime/aligned_buffer.hpp"
#include "ngraph/type/element_type.hpp"
#include "ngraph/util.hpp"

namespace ngraph
{
    namespace op
    {
        namespace v0
        {
            /// \brief Class for constants.
            class NGRAPH_API Constant : public Op
            {
            public:
                static constexpr NodeTypeInfo type_info{"Constant", 0};
                const NodeTypeInfo& get_type_info() const override { return type_info; }
                Constant() = default;
                /// \brief Constructs a tensor constant.
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A vector of literals for initializing the tensor constant. The
                ///               size of values must match the size of the shape.
                template <typename T>
                Constant(const element::Type& type, Shape shape, const std::vector<T>& values)
                    : m_element_type(type)
                    , m_shape(shape)
                    , m_data(new runtime::AlignedBuffer(shape_size(m_shape) * m_element_type.size(),
                                                        host_alignment()))
                {
                    NODE_VALIDATION_CHECK(
                        this,
                        values.size() == 1 || values.size() == shape_size(m_shape),
                        "Did not get the expected number of literals for a constant of shape ",
                        m_shape,
                        " (got ",
                        values.size(),
                        ", expected ",
                        (shape_size(m_shape) == 1 ? "" : "1 or "),
                        shape_size(m_shape),
                        ").");

                    if (values.size() == 1)
                    {
                        write_values(std::vector<T>(shape_size(m_shape), values[0]));
                    }
                    else
                    {
                        write_values(values);
                    }
                    constructor_validate_and_infer_types();
                    m_all_elements_bitwise_identical = are_all_data_elements_bitwise_identical();
                }

                /// \brief Constructs a tensor constant
                ///        This constructor is mainly to support deserialization of constants.
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A list of string values to use as the constant data.
                Constant(const element::Type& type,
                         Shape shape,
                         const std::vector<std::string>& values);

                /// \brief Constructs a tensor constant with the supplied data
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param data A void* to constant data.
                Constant(const element::Type& type, const Shape& shape, const void* data);

                Constant(const Constant& other);

                virtual ~Constant() override;

                void validate_and_infer_types() override
                {
                    infer_element_type();
                    set_output_type(0, m_element_type, m_shape);
                }

                /// \brief Returns the value of the constant node as a Shape object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Shape get_shape_val() const;
                /// \brief Returns the value of the constant node as a Strides
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Strides get_strides_val() const;
                /// \brief Returns the value of the constant node as a Coordinate
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                Coordinate get_coordinate_val() const;
                /// \brief Returns the value of the constant node as a
                ///        CoordinateDiff object
                ///        Can only be used on element::i64 nodes.
                CoordinateDiff get_coordinate_diff_val() const;
                /// \brief Returns the value of the constant node as an AxisVector
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                AxisVector get_axis_vector_val() const;
                /// \brief Returns the value of the constant node as an AxisSet
                ///        object
                ///        Can only be used on element::i64 nodes and interprets
                ///        negative values as zeros.
                ///        Repeated values are allowed.
                AxisSet get_axis_set_val() const;

                /// \brief Wrapper around constructing a shared_ptr of a Constant
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values A vector of values to use as the constant data.
                template <typename T>
                static std::shared_ptr<op::v0::Constant>
                    create(const element::Type& type, Shape shape, const std::vector<T> values)
                {
                    auto result = std::make_shared<op::v0::Constant>(type, shape, values);
                    result->validate_and_infer_types();
                    return result;
                }

                /// \brief Wrapper around constructing a shared_ptr of a Constant
                ///
                /// \param type The element type of the tensor constant.
                /// \param shape The shape of the tensor constant.
                /// \param values An initializer_list of values to use as the constant data.
                template <typename T>
                static std::shared_ptr<op::v0::Constant>
                    create(const element::Type& type, Shape shape, std::initializer_list<T> values)
                {
                    auto result =
                        std::make_shared<op::v0::Constant>(type, shape, std::vector<T>{values});
                    result->validate_and_infer_types();
                    return result;
                }

                virtual std::shared_ptr<Node>
                    copy_with_new_args(const NodeVector& new_args) const override;

                /// \return The initialization literals for the tensor constant.
                std::vector<std::string> get_value_strings() const;

                template <typename T>
                std::vector<T> get_vector() const
                {
                    if (sizeof(T) > m_element_type.size() && shape_size(m_shape) > 0)
                    {
                        throw ngraph_error("Buffer over-read");
                    }

                    std::vector<T> rc;
                    const T* p = reinterpret_cast<const T*>(m_data->get_ptr());
                    for (size_t i = 0; i < shape_size(m_shape); i++)
                    {
                        rc.push_back(p[i]);
                    }
                    return rc;
                }

                /// \brief Return the Constant's value as a vector cast to type T
                ///
                /// \tparam T  Type to which data vector's entries will be cast.
                /// \return    Constant's data vector.
                template <typename T>
                std::vector<T> cast_vector() const
                {
                    auto source_type = get_element_type();
                    switch (source_type)
                    {
                    case element::Type_t::boolean:
                    {
                        auto vector = get_vector<char>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::bf16:
                    {
                        auto vector = get_vector<bfloat16>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f16:
                    {
                        auto vector = get_vector<float16>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f32:
                    {
                        auto vector = get_vector<float>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::f64:
                    {
                        auto vector = get_vector<double>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i8:
                    {
                        auto vector = get_vector<int8_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i16:
                    {
                        auto vector = get_vector<int16_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i32:
                    {
                        auto vector = get_vector<int32_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::i64:
                    {
                        auto vector = get_vector<int64_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u8:
                    {
                        auto vector = get_vector<uint8_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u16:
                    {
                        auto vector = get_vector<uint16_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u32:
                    {
                        auto vector = get_vector<uint32_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    case element::Type_t::u64:
                    {
                        auto vector = get_vector<uint64_t>();
                        return std::vector<T>(vector.begin(), vector.end());
                    }
                    default: throw std::runtime_error("unsupported type");
                    }
                }

                const void* get_data_ptr() const { return (m_data ? m_data->get_ptr() : nullptr); }
                template <typename T>
                const T* get_data_ptr() const
                {
                    return reinterpret_cast<const T*>(get_data_ptr());
                }

                bool is_constant() const override { return true; }
                bool get_all_data_elements_bitwise_identical() const
                {
                    return m_all_elements_bitwise_identical;
                }
                std::string convert_value_to_string(size_t index) const;

            protected:
                void* get_data_ptr_nc() { return (m_data ? m_data->get_ptr() : nullptr); }
                Constant(const OutputVector& args)
                    : Op(args)
                    , m_shape({})
                {
                }

                virtual void infer_element_type() {}
                template <typename T>
                void write_values(const std::vector<T>& values)
                {
                    write_to_buffer(
                        m_element_type, m_shape, values, get_data_ptr_nc(), shape_size(m_shape));
                }

                template <typename T, typename U>
                void write_buffer(void* target, const std::vector<U>& source, size_t count)
                {
                    T* p = reinterpret_cast<T*>(target);
                    for (size_t i = 0; i < count; i++)
                    {
                        p[i] = static_cast<T>(source[i]);
                    }
                }

                template <typename T>
                void write_to_buffer(const element::Type& target_type,
                                     const Shape& /* target_shape */,
                                     const std::vector<T>& source,
                                     void* target,
                                     size_t target_element_count)
                {
                    if (source.size() != target_element_count)
                    {
                        throw std::runtime_error("Constant initializer does not match shape");
                    }
#if defined(__GNUC__) && !(__GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
                    switch (target_type)
                    {
                    case element::Type_t::boolean:
                        write_buffer<char, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::bf16:
                        write_buffer<bfloat16, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f16:
                        write_buffer<float16, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f32:
                        write_buffer<float, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::f64:
                        write_buffer<double, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i8:
                        write_buffer<int8_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i16:
                        write_buffer<int16_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i32:
                        write_buffer<int32_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::i64:
                        write_buffer<int64_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u8:
                        write_buffer<uint8_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u16:
                        write_buffer<uint16_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u32:
                        write_buffer<uint32_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u64:
                        write_buffer<uint64_t, T>(target, source, target_element_count);
                        break;
                    case element::Type_t::u1: throw std::runtime_error("unsupported type");
                    case element::Type_t::undefined: throw std::runtime_error("unsupported type");
                    case element::Type_t::dynamic: throw std::runtime_error("unsupported type");
                    }
#if defined(__GNUC__) && !(__GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic pop
#endif
                }

                static constexpr size_t host_alignment() { return 64; }
                element::Type m_element_type;
                Shape m_shape{};
                std::shared_ptr<runtime::AlignedBuffer> m_data;
                bool m_all_elements_bitwise_identical;
                bool are_all_data_elements_bitwise_identical() const;
            };

            /// \brief A scalar constant whose element type is the same as like.
            class NGRAPH_API ScalarConstantLike : public Constant
            {
            public:
                static constexpr NodeTypeInfo type_info{"ScalarConstantLike", 0};
                const NodeTypeInfo& get_type_info() const override { return type_info; }
                /// \brief A scalar constant whose element type is the same as like.
                ///
                /// Once the element type is known, the dependency on like will be removed and
                /// this node will be replaced with an equivalent constant.
                ///
                /// \param like A tensor that will supply the element type.
                /// \param value The value of the scalar.
                template <typename T>
                ScalarConstantLike(const Output<Node>& like, T value)
                    : Constant({like})
                    , m_value(static_cast<double>(value))
                {
                    constructor_validate_and_infer_types();
                }

                ScalarConstantLike() = default;

                std::shared_ptr<Node> copy_with_new_args(const NodeVector& new_args) const override;
                std::shared_ptr<op::v0::Constant> as_constant() const;

            protected:
                void infer_element_type() override;

                double m_value;
            };
        }
        using v0::Constant;
        using v0::ScalarConstantLike;
    }
}
<|endoftext|>


<commit_before>/*!
 * Copyright (c) 2017 by Contributors
 * \file softmax.cc
 * \brief CPU Implementation of softmax
 */
#include "./softmax-inl.h"
#include "../tensor/elemwise_unary_op.h"
#include "../tensor/elemwise_binary_op.h"

namespace mxnet {
namespace op {
DMLC_REGISTER_PARAMETER(SoftmaxParam);

MXNET_OPERATOR_REGISTER_UNARY(softmax)
.describe(R"code(Applies the softmax function. The resulting array contains
 elements in the range (0,1) and the elements along the given axis sum up to 1.

.. math::
   softmax(\mathbf{z})_j = \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}}

for :math:`j = 1, …, K`

Example::

  x = [[ 1.  1.  1.]
       [ 1.  1.  1.]]

  softmax(x,axis=0) = [[ 0.5  0.5  0.5]
                       [ 0.5  0.5  0.5]]

  softmax(x,axis=1) = [[ 0.33333334,  0.33333334,  0.33333334],
                       [ 0.33333334,  0.33333334,  0.33333334]]

)code" ADD_FILELINE)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxCompute<cpu, mxnet_op::softmax_fwd>)
.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseOut{"_backward_softmax"})
.add_arguments(SoftmaxParam::__FIELDS__());

MXNET_OPERATOR_REGISTER_BINARY(_backward_softmax)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxGradCompute<cpu, mshadow::op::mul,
                                                        mxnet_op::softmax_bwd>);

MXNET_OPERATOR_REGISTER_UNARY(log_softmax)
.describe(R"code(Compute the log softmax of the input.
This is equivalent to computing softmax followed by log.

Examples::

  >>> x = mx.nd.array([1, 2, .1])
  >>> mx.nd.log_softmax(x).asnumpy()
  array([-1.41702998, -0.41702995, -2.31702995], dtype=float32)

  >>> x = mx.nd.array( [[1, 2, .1],[.1, 2, 1]] )
  >>> mx.nd.log_softmax(x, axis=0).asnumpy()
  array([[-0.34115392, -0.69314718, -1.24115396],
         [-1.24115396, -0.69314718, -0.34115392]], dtype=float32)

)code")
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxCompute<cpu, mxnet_op::log_softmax_fwd>)
.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseOut{"_backward_log_softmax"})
.add_arguments(SoftmaxParam::__FIELDS__());

MXNET_OPERATOR_REGISTER_BINARY(_backward_log_softmax)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxGradCompute<cpu, mshadow_op::left,
                                                        mxnet_op::log_softmax_bwd>);

}  // namespace op
}  // namespace mxnet
<commit_msg>fix UnicodeDecodeError (#5908)<commit_after>/*!
 * Copyright (c) 2017 by Contributors
 * \file softmax.cc
 * \brief CPU Implementation of softmax
 */
#include "./softmax-inl.h"
#include "../tensor/elemwise_unary_op.h"
#include "../tensor/elemwise_binary_op.h"

namespace mxnet {
namespace op {
DMLC_REGISTER_PARAMETER(SoftmaxParam);

MXNET_OPERATOR_REGISTER_UNARY(softmax)
.describe(R"code(Applies the softmax function. The resulting array contains
 elements in the range (0,1) and the elements along the given axis sum up to 1.

.. math::
   softmax(\mathbf{z})_j = \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}}

for :math:`j = 1, ..., K`

Example::

  x = [[ 1.  1.  1.]
       [ 1.  1.  1.]]

  softmax(x,axis=0) = [[ 0.5  0.5  0.5]
                       [ 0.5  0.5  0.5]]

  softmax(x,axis=1) = [[ 0.33333334,  0.33333334,  0.33333334],
                       [ 0.33333334,  0.33333334,  0.33333334]]

)code" ADD_FILELINE)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxCompute<cpu, mxnet_op::softmax_fwd>)
.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseOut{"_backward_softmax"})
.add_arguments(SoftmaxParam::__FIELDS__());

MXNET_OPERATOR_REGISTER_BINARY(_backward_softmax)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxGradCompute<cpu, mshadow::op::mul,
                                                        mxnet_op::softmax_bwd>);

MXNET_OPERATOR_REGISTER_UNARY(log_softmax)
.describe(R"code(Compute the log softmax of the input.
This is equivalent to computing softmax followed by log.

Examples::

  >>> x = mx.nd.array([1, 2, .1])
  >>> mx.nd.log_softmax(x).asnumpy()
  array([-1.41702998, -0.41702995, -2.31702995], dtype=float32)

  >>> x = mx.nd.array( [[1, 2, .1],[.1, 2, 1]] )
  >>> mx.nd.log_softmax(x, axis=0).asnumpy()
  array([[-0.34115392, -0.69314718, -1.24115396],
         [-1.24115396, -0.69314718, -0.34115392]], dtype=float32)

)code")
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxCompute<cpu, mxnet_op::log_softmax_fwd>)
.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseOut{"_backward_log_softmax"})
.add_arguments(SoftmaxParam::__FIELDS__());

MXNET_OPERATOR_REGISTER_BINARY(_backward_log_softmax)
.set_attr_parser(ParamParser<SoftmaxParam>)
.set_attr<FCompute>("FCompute<cpu>", SoftmaxGradCompute<cpu, mshadow_op::left,
                                                        mxnet_op::log_softmax_bwd>);

}  // namespace op
}  // namespace mxnet
<|endoftext|>


<commit_before>#include "opt/wire/scheduler.h"

#include "design/resource_attr.h"
#include "iroha/i_design.h"
#include "opt/bb_set.h"
#include "opt/delay_info.h"
#include "opt/wire/data_path.h"

namespace iroha {
namespace opt {
namespace wire {

SchedulerCore::SchedulerCore(DataPathSet *data_path_set, DelayInfo *delay_info)
  : data_path_set_(data_path_set), delay_info_(delay_info) {
}

void SchedulerCore::Schedule() {
  auto &paths = data_path_set_->GetPaths();
  for (auto &p : paths) {
    Scheduler sch(p.second, delay_info_);
    sch.Schedule();
  }
}

Scheduler::Scheduler(DataPath *data_path, DelayInfo *delay_info)
  : data_path_(data_path), delay_info_(delay_info) {
}

bool Scheduler::IsSchedulable() {
  // TODO: We might split a basic block before/after special insns, because
  // this is too awkward.
  BB *bb = data_path_->GetBB();
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      if (ResourceAttr::IsExtAccessInsn(insn) ||
	  ResourceAttr::IsExtWaitInsn(insn)) {
	return false;
      }
    }
  }
  return true;
}

void Scheduler::Schedule() {
  if (!IsSchedulable()) {
    return;
  }
  ClearSchedule();
  // Sort by accumlated latency from leafs.
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    sorted_nodes_[n->accumlated_delay_].push_back(n);
  }
  // Iterate from leafs.
  bool has_unscheduled;
  do {
    has_unscheduled = false;
    for (auto &lt : sorted_nodes_) {
      auto &ev = lt.second;
      for (auto *n : ev) {
	if (!ScheduleNode(n)) {
	  has_unscheduled = true;
	}
      }
    }
  } while (has_unscheduled);
}

bool Scheduler::ScheduleNode(PathNode *n) {
  if (n->final_st_index_ > -1) {
    // already scheduled.
    return true;
  }
  int min_st_index = 0;
  // Determines the location.
  for (auto &s : n->source_edges_) {
    PathNode *source_node = s.second->source_node_;
    if (source_node->final_st_index_ < 0) {
      // not yet scheduled. fail and try later again.
      return false;
    }
    if (min_st_index < source_node->final_st_index_) {
      min_st_index = source_node->final_st_index_;
    }
    if (min_st_index == source_node->final_st_index_) {
      int tmp_local_delay =
	source_node->state_local_delay_ + n->node_delay_;
      if (tmp_local_delay > delay_info_->GetMaxDelay()) {
	// Go to next state.
	++min_st_index;
      }
    }
  }
  // Calculates local delay.
  int source_local_delay = 0;
  for (auto &s : n->source_edges_) {
    PathNode *source_node = s.second->source_node_;
    if (source_node->final_st_index_ < min_st_index) {
      continue;
    }
    if (source_local_delay < source_node->state_local_delay_) {
      source_local_delay = source_node->state_local_delay_;
    }
  }
  if (n->insn_->GetResource()->GetClass()->IsExclusive()) {
    ScheduleExclusive(n, min_st_index, source_local_delay);
  } else {
    ScheduleNonExclusive(n, min_st_index, source_local_delay);
  }

  return true;
}

void Scheduler::ClearSchedule() {
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    n->final_st_index_ = -1;
    n->state_local_delay_ = 0;
  }
}

void Scheduler::ScheduleExclusive(PathNode *n, int min_index,
				  int source_local_delay) {
  int loc = min_index;
  while (true) {
    auto key = std::make_tuple(n->insn_->GetResource(), loc);
    auto it = resource_slots_.find(key);
    if (it == resource_slots_.end()) {
      resource_slots_.insert(key);
      break;
    }
    ++loc;
  }
  n->state_local_delay_ = n->node_delay_;
  if (loc == min_index) {
    n->state_local_delay_ += source_local_delay;
  }
  n->final_st_index_ = loc;
}

void Scheduler::ScheduleNonExclusive(PathNode *n, int min_index,
				     int source_local_delay) {
  n->final_st_index_ = min_index;
  n->state_local_delay_ = source_local_delay + n->node_delay_;
}

}  // namespace wire
}  // namespace opt
}  // namespace iroha
<commit_msg>Don't touch a block if there are insns with dependencies.<commit_after>#include "opt/wire/scheduler.h"

#include "design/resource_attr.h"
#include "iroha/i_design.h"
#include "opt/bb_set.h"
#include "opt/delay_info.h"
#include "opt/wire/data_path.h"

namespace iroha {
namespace opt {
namespace wire {

SchedulerCore::SchedulerCore(DataPathSet *data_path_set, DelayInfo *delay_info)
  : data_path_set_(data_path_set), delay_info_(delay_info) {
}

void SchedulerCore::Schedule() {
  auto &paths = data_path_set_->GetPaths();
  for (auto &p : paths) {
    Scheduler sch(p.second, delay_info_);
    sch.Schedule();
  }
}

Scheduler::Scheduler(DataPath *data_path, DelayInfo *delay_info)
  : data_path_(data_path), delay_info_(delay_info) {
}

bool Scheduler::IsSchedulable() {
  // TODO: We might split a basic block before/after special insns, because
  // this is too awkward.
  BB *bb = data_path_->GetBB();
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      if (ResourceAttr::IsExtAccessInsn(insn) ||
	  ResourceAttr::IsExtWaitInsn(insn)) {
	return false;
      }
      // This is really awkward...
      if (insn->depending_insns_.size() > 0) {
	return false;
      }
    }
  }
  return true;
}

void Scheduler::Schedule() {
  if (!IsSchedulable()) {
    return;
  }
  ClearSchedule();
  // Sort by accumlated latency from leafs.
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    sorted_nodes_[n->accumlated_delay_].push_back(n);
  }
  // Iterate from leafs.
  bool has_unscheduled;
  do {
    has_unscheduled = false;
    for (auto &lt : sorted_nodes_) {
      auto &ev = lt.second;
      for (auto *n : ev) {
	if (!ScheduleNode(n)) {
	  has_unscheduled = true;
	}
      }
    }
  } while (has_unscheduled);
}

bool Scheduler::ScheduleNode(PathNode *n) {
  if (n->final_st_index_ > -1) {
    // already scheduled.
    return true;
  }
  int min_st_index = 0;
  // Determines the location.
  for (auto &s : n->source_edges_) {
    PathNode *source_node = s.second->source_node_;
    if (source_node->final_st_index_ < 0) {
      // not yet scheduled. fail and try later again.
      return false;
    }
    if (min_st_index < source_node->final_st_index_) {
      min_st_index = source_node->final_st_index_;
    }
    if (min_st_index == source_node->final_st_index_) {
      int tmp_local_delay =
	source_node->state_local_delay_ + n->node_delay_;
      if (tmp_local_delay > delay_info_->GetMaxDelay()) {
	// Go to next state.
	++min_st_index;
      }
    }
  }
  // Calculates local delay.
  int source_local_delay = 0;
  for (auto &s : n->source_edges_) {
    PathNode *source_node = s.second->source_node_;
    if (source_node->final_st_index_ < min_st_index) {
      continue;
    }
    if (source_local_delay < source_node->state_local_delay_) {
      source_local_delay = source_node->state_local_delay_;
    }
  }
  if (n->insn_->GetResource()->GetClass()->IsExclusive()) {
    ScheduleExclusive(n, min_st_index, source_local_delay);
  } else {
    ScheduleNonExclusive(n, min_st_index, source_local_delay);
  }

  return true;
}

void Scheduler::ClearSchedule() {
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    n->final_st_index_ = -1;
    n->state_local_delay_ = 0;
  }
}

void Scheduler::ScheduleExclusive(PathNode *n, int min_index,
				  int source_local_delay) {
  int loc = min_index;
  while (true) {
    auto key = std::make_tuple(n->insn_->GetResource(), loc);
    auto it = resource_slots_.find(key);
    if (it == resource_slots_.end()) {
      resource_slots_.insert(key);
      break;
    }
    ++loc;
  }
  n->state_local_delay_ = n->node_delay_;
  if (loc == min_index) {
    n->state_local_delay_ += source_local_delay;
  }
  n->final_st_index_ = loc;
}

void Scheduler::ScheduleNonExclusive(PathNode *n, int min_index,
				     int source_local_delay) {
  n->final_st_index_ = min_index;
  n->state_local_delay_ = source_local_delay + n->node_delay_;
}

}  // namespace wire
}  // namespace opt
}  // namespace iroha
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights 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: Alessandro Tasora
// =============================================================================
//
// Demo code about collisions of triangle meshes
//
// =============================================================================

#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChParticlesClones.h"
#include "chrono/assets/ChTexture.h"
#include "chrono/assets/ChTriangleMeshShape.h"
#include "chrono/geometry/ChTriangleMeshConnected.h"

#include "chrono_irrlicht/ChIrrApp.h"

// Use the namespaces of Chrono
using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::irrlicht;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;

int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create a ChronoENGINE physical system
    ChSystemNSC mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Collisions between objects", core::dimension2d<u32>(1280, 720), false);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    ChIrrWizard::add_typical_Logo(application.GetDevice());
    ChIrrWizard::add_typical_Sky(application.GetDevice());
    ChIrrWizard::add_typical_Lights(application.GetDevice());
    ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0, 1, -1));

    application.AddLightWithShadow(core::vector3df(1.5f, 5.5f, -2.5f), core::vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512,
                                   video::SColorf(0.8f, 0.8f, 1.0f));

    application.SetContactsDrawMode(ChIrrTools::eCh_ContactsDrawMode::CONTACT_DISTANCES);

    //
    // Create all the rigid bodies.
    //

    collision::ChCollisionModel::SetDefaultSuggestedEnvelope(0.0025);
    collision::ChCollisionModel::SetDefaultSuggestedMargin(0.0025);

    // - Create a floor

    auto mfloor2 = std::make_shared<ChBody>();
    mfloor2->SetPos(ChVector<>(0, -1, 0));
    mfloor2->SetBodyFixed(true);
    mphysicalSystem.Add(mfloor2);

    ChTriangleMeshConnected mmeshbox;
    mmeshbox.LoadWavefrontMesh(GetChronoDataFile("cube.obj"),true,true);

    mfloor2->GetCollisionModel()->ClearModel();
    mfloor2->GetCollisionModel()->AddTriangleMesh(mmeshbox,false, false, VNULL, ChMatrix33<>(1), 0.005);
    mfloor2->GetCollisionModel()->BuildModel();
    mfloor2->SetCollide(true);

    auto masset_meshbox = std::make_shared<ChTriangleMeshShape>();
    masset_meshbox->SetMesh(mmeshbox);
    mfloor2->AddAsset(masset_meshbox);

    auto masset_texture = std::make_shared<ChTexture>();
    masset_texture->SetTextureFilename(GetChronoDataFile("concrete.jpg"));
    mfloor2->AddAsset(masset_texture);

    // - Create a falling item with triangle mesh shape

    ChTriangleMeshConnected mmesh;
    mmesh.LoadWavefrontMesh(GetChronoDataFile("shoe_view.obj"),false,true);
    mmesh.Transform(ChVector<>(-0.15,0,0), ChMatrix33<>(1.2)); // scale to a smaller cube
    mmesh.RepairDuplicateVertexes(1e-9); // if meshes are not watertight
    // compute mass inertia from mesh
    double mmass;
    ChVector<>mcog;
    ChMatrix33<> minertia;
    mmesh.ComputeMassProperties(true,mmass,mcog,minertia);

    for (int j= 0; j<10;++j) {
        auto mfalling = std::make_shared<ChBody>();
        //  mfalling->SetPos(ChVector<>(0.1, 0.24, 0));
        mfalling->SetPos(ChVector<>(ChRandom() * 0.4, 0.2 + j * 0.12, ChRandom() * 0.4));
        mphysicalSystem.Add(mfalling);
        mfalling->SetMass(mmass*1000);
        mfalling->SetInertia(minertia*1000);

        mfalling->GetCollisionModel()->ClearModel();
        mfalling->GetCollisionModel()->AddTriangleMesh(mmesh,false, false, VNULL, ChMatrix33<>(1), 0.005);
        mfalling->GetCollisionModel()->BuildModel();
        mfalling->SetCollide(true);

        auto masset_mesh = std::make_shared<ChTriangleMeshShape>();
        masset_mesh->SetMesh(mmesh);
        masset_mesh->SetBackfaceCull(true);
        mfalling->AddAsset(masset_mesh);

        auto masset_texturew = std::make_shared<ChTexture>();
        masset_texturew->SetTextureFilename(GetChronoDataFile("cubetexture_wood.png"));
        mfalling->AddAsset(masset_texturew);
    }

    for (int bi = 0; bi < 20; bi++) {
        // Create a bunch of ChronoENGINE rigid bodies (spheres and
        // boxes etc.) which will fall..

        auto msphereBody = std::make_shared<ChBodyEasySphere>(0.05,             // radius size
                                                              1000,             // density
                                                              true,             // collide enable?
                                                              true);            // visualization?
        msphereBody->SetPos(ChVector<>(-0.5 + ChRandom() * 1, 1.4, -0.5 + ChRandom()));
        msphereBody->GetMaterialSurfaceNSC()->SetFriction(0.2f);

        auto mballcolor = std::make_shared<ChColorAsset>();
        mballcolor->SetColor(ChColor(0.3f, 0.3f, 0.6f));
        msphereBody->AddAsset(mballcolor);

        mphysicalSystem.Add(msphereBody);
    }

    //-----------

    // Use this function for adding a ChIrrNodeAsset to all items
    // Otherwise use application.AssetBind(myitem); on a per-item basis.
    application.AssetBindAll();

    // Use this function for 'converting' assets into Irrlicht meshes
    application.AssetUpdateAll();

    // Use shadows in realtime view
    application.AddShadowAll();

    application.SetTimestep(0.005);

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    while (application.GetDevice()->run()) {
        application.BeginScene(true, true, SColor(255, 140, 161, 192));

        application.DrawAll();

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
<commit_msg>Improved demo on colliding triangle mesh shapes<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights 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: Alessandro Tasora
// =============================================================================
//
// Demo code about collisions of triangle meshes
//
// =============================================================================

#include "chrono/physics/ChSystemNSC.h"
#include "chrono/physics/ChBodyEasy.h"
#include "chrono/physics/ChParticlesClones.h"
#include "chrono/assets/ChTexture.h"
#include "chrono/assets/ChTriangleMeshShape.h"
#include "chrono/geometry/ChTriangleMeshConnected.h"

#include "chrono_irrlicht/ChIrrApp.h"

// Use the namespaces of Chrono
using namespace chrono;
using namespace chrono::geometry;
using namespace chrono::irrlicht;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;

int main(int argc, char* argv[]) {
    GetLog() << "Copyright (c) 2017 projectchrono.org\nChrono version: " << CHRONO_VERSION << "\n\n";

    // Create a ChronoENGINE physical system
    ChSystemNSC mphysicalSystem;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&mphysicalSystem, L"Collisions between objects", core::dimension2d<u32>(1280, 720), false);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    ChIrrWizard::add_typical_Logo(application.GetDevice());
    ChIrrWizard::add_typical_Sky(application.GetDevice());
    ChIrrWizard::add_typical_Lights(application.GetDevice());
    ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0, 1, -1));

    application.AddLightWithShadow(core::vector3df(1.5f, 5.5f, -2.5f), core::vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512,
                                   video::SColorf(0.8f, 0.8f, 1.0f));

    application.SetContactsDrawMode(ChIrrTools::eCh_ContactsDrawMode::CONTACT_DISTANCES);

    //
    // Create all the rigid bodies.
    //

    collision::ChCollisionModel::SetDefaultSuggestedEnvelope(0.0025);
    collision::ChCollisionModel::SetDefaultSuggestedMargin(0.0025);

    // - Create a floor

    auto mfloor2 = std::make_shared<ChBody>();
    mfloor2->SetPos(ChVector<>(0, -1, 0));
    mfloor2->SetBodyFixed(true);
    mphysicalSystem.Add(mfloor2);

    ChTriangleMeshConnected mmeshbox;
    mmeshbox.LoadWavefrontMesh(GetChronoDataFile("cube.obj"),true,true);

    mfloor2->GetCollisionModel()->ClearModel();
    mfloor2->GetCollisionModel()->AddTriangleMesh(mmeshbox,false, false, VNULL, ChMatrix33<>(1), 0.005);
    mfloor2->GetCollisionModel()->BuildModel();
    mfloor2->SetCollide(true);

    auto masset_meshbox = std::make_shared<ChTriangleMeshShape>();
    masset_meshbox->SetMesh(mmeshbox);
    mfloor2->AddAsset(masset_meshbox);

    auto masset_texture = std::make_shared<ChTexture>();
    masset_texture->SetTextureFilename(GetChronoDataFile("concrete.jpg"));
    mfloor2->AddAsset(masset_texture);

    // - Create a falling item with triangle mesh shape

	// Note: one can create easily a colliding shape using the following
	// piece of code:
	//
	// auto mfalling = std::make_shared<ChBodyEasyMesh>(
	//	  GetChronoDataFile("shoe_view.obj"),   ///< .OBJ mesh defined respect REF c.sys of body (initially REF=0,0,0 pos.)
	//	  1000,              ///< density of the body
	//	  true,			   ///< automatic evaluation of mass, COG position, inertia tensor
	//	  true,			   ///< enable the collision detection
	//	  0.005,			   ///< radius of 'inflating' of mesh, the larger the more robust collision detection
	//	  true 			  ///< attach a visualization asset to the body
	//	  );
	// mfalling->SetFrame_REF_to_abs(ChFrame<>(ChVector<>(-0.9 + ChRandom() * 1.4, 0.4 + j * 0.12, -0.9 + ChRandom() * 1.4)));
	// mphysicalSystem.Add(mfalling);
	//
	// but here we want to show a more low-level control of this process, for
	// various reasons, for example: we want to share a single ChTriangleMeshConnected
	// between 15 falling shapes; also we want to call RepairDuplicateVertexes() on the
	// imported mesh; also we want to scale the imported mesh using Transform().

    ChTriangleMeshConnected mmesh;
    mmesh.LoadWavefrontMesh(GetChronoDataFile("shoe_view.obj"),false,true);
    mmesh.Transform(ChVector<>(0,0,0), ChMatrix33<>(1.2)); // scale to a different size
    mmesh.RepairDuplicateVertexes(1e-9); // if meshes are not watertight
    // compute mass inertia from mesh
    double mmass;
    ChVector<>mcog;
    ChMatrix33<> minertia;
    double mdensity = 1000;
    mmesh.ComputeMassProperties(true,mmass,mcog,minertia);
    ChMatrix33<> principal_inertia_csys;
    double principal_I[3];
    minertia.FastEigen(principal_inertia_csys, principal_I);

    for (int j= 0; j<15;++j) {

        auto mfalling = std::make_shared<ChBodyAuxRef>();
        mfalling->SetMass(mmass * mdensity);
        mfalling->SetInertiaXX(ChVector<>(principal_I[0] * mdensity, principal_I[1] * mdensity, principal_I[2] * mdensity));
        // Set the COG coordinates to barycenter, without displacing the REF reference
        mfalling->SetFrame_COG_to_REF(ChFrame<>(mcog, principal_inertia_csys));

		// Set the absolute position of the body:
        mfalling->SetFrame_REF_to_abs(ChFrame<>(ChVector<>(-0.9+ChRandom() * 1.4, 0.4 + j * 0.12, -0.9+ChRandom() * 1.4)));
        mphysicalSystem.Add(mfalling);
        mfalling->SetMass(mmass*1000);
        mfalling->SetInertia(minertia*1000);

        mfalling->GetCollisionModel()->ClearModel();
        mfalling->GetCollisionModel()->AddTriangleMesh(mmesh,false, false, VNULL, ChMatrix33<>(1), 0.005);
        mfalling->GetCollisionModel()->BuildModel();
        mfalling->SetCollide(true);

        auto masset_mesh = std::make_shared<ChTriangleMeshShape>();
        masset_mesh->SetMesh(mmesh);
        masset_mesh->SetBackfaceCull(true);
        mfalling->AddAsset(masset_mesh);
    }

    for (int bi = 0; bi < 20; bi++) {
        // Create a bunch of ChronoENGINE rigid bodies (spheres and
        // boxes etc.) which will fall..

        auto msphereBody = std::make_shared<ChBodyEasySphere>(0.05,             // radius size
                                                              1000,             // density
                                                              true,             // collide enable?
                                                              true);            // visualization?
        msphereBody->SetPos(ChVector<>(-0.5 + ChRandom() * 1, 1.4, -0.5 + ChRandom()));
        msphereBody->GetMaterialSurfaceNSC()->SetFriction(0.2f);

        auto mballcolor = std::make_shared<ChColorAsset>();
        mballcolor->SetColor(ChColor(0.3f, 0.3f, 0.6f));
        msphereBody->AddAsset(mballcolor);

        mphysicalSystem.Add(msphereBody);
    }

    //-----------

    // Use this function for adding a ChIrrNodeAsset to all items
    // Otherwise use application.AssetBind(myitem); on a per-item basis.
    application.AssetBindAll();

    // Use this function for 'converting' assets into Irrlicht meshes
    application.AssetUpdateAll();

    // Use shadows in realtime view
    application.AddShadowAll();

    application.SetTimestep(0.005);

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    while (application.GetDevice()->run()) {
        application.BeginScene(true, true, SColor(255, 140, 161, 192));

        application.DrawAll();

        application.DoStep();

        application.EndScene();
    }

    return 0;
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osg/Texture2D>
#include <osg/CoordinateSystemNode>
#include <osg/TexEnv>
#include <osg/io_utils>

#include <osgUtil/CullVisitor>
#include <osgSim/OverlayNode>

using namespace osgSim;
using namespace osg;

OverlayNode::OverlayNode():
    _texEnvMode(GL_DECAL),
    _textureUnit(1),
    _textureSizeHint(1024),
    _continuousUpdate(false)
{
    init();
}

OverlayNode::OverlayNode(const OverlayNode& copy, const osg::CopyOp& copyop):
    osg::Group(copy,copyop),
    _overlaySubgraph(copy._overlaySubgraph),
    _texEnvMode(copy._texEnvMode),
    _textureUnit(copy._textureUnit),
    _textureSizeHint(copy._textureSizeHint),
    _continuousUpdate(copy._continuousUpdate)
{
    init();
}

void OverlayNode::init()
{

    unsigned int tex_width = _textureSizeHint;
    unsigned int tex_height = _textureSizeHint;

    if (!_texture)
    {
        osg::Texture2D* texture = new osg::Texture2D;
        texture->setTextureSize(tex_width, tex_height);
        texture->setInternalFormat(GL_RGBA);
        texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
        texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
        texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
        texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
        texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
        _texture = texture;
    }

    // set up the render to texture camera.
    if (!_camera)
    {
        // create the camera
        _camera = new osg::CameraNode;

        _camera->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));

        // set viewport
        _camera->setViewport(0,0,tex_width,tex_height);

        // set the camera to render before the main camera.
        _camera->setRenderOrder(osg::CameraNode::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        _camera->setRenderTargetImplementation(osg::CameraNode::FRAME_BUFFER_OBJECT);

        // attach the texture and use it as the color buffer.
        _camera->attach(osg::CameraNode::COLOR_BUFFER, _texture.get());
    }

    if (!_texgenNode) _texgenNode = new osg::TexGenNode;

    if (!_mainSubgraphStateSet) _mainSubgraphStateSet = new osg::StateSet;

    setOverlayTextureUnit(_textureUnit);
}

void OverlayNode::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
    {
        Group::traverse(nv);
        return;
    }

    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
    if (!cv)
    {
        Group::traverse(nv);
        return;
    }

    unsigned int contextID = cv->getState()!=0 ? cv->getState()->getContextID() : 0;

    // if we need to redraw then do cull traversal on camera.
    if (!_textureObjectValidList[contextID] || _continuousUpdate)
    {

        // now compute the camera's view and projection matrix to point at the shadower (the camera's children)
        osg::BoundingSphere bs;
        for(unsigned int i=0; i<_camera->getNumChildren(); ++i)
        {
            bs.expandBy(_camera->getChild(i)->getBound());
        }

        if (bs.valid())
        {
            // see if we are within a coordinate system node.
            osg::CoordinateSystemNode* csn = 0;
            osg::NodePath& nodePath = nv.getNodePath();
            for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
                itr != nodePath.rend() && csn==0;
                ++itr)
            {
                csn = dynamic_cast<osg::CoordinateSystemNode*>(*itr);
            }

            _camera->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF);

            if (csn)
            {
                osg::Vec3d eyePoint(0.0,0.0,0.0); // center of the planet
                double centerDistance = (eyePoint-osg::Vec3d(bs.center())).length();

                double znear = centerDistance-bs.radius();
                double zfar  = centerDistance+bs.radius();
                double zNearRatio = 0.001f;
                if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

                double top   = (bs.radius()/centerDistance)*znear;
                double right = top;

                _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
                _camera->setViewMatrixAsLookAt(eyePoint, bs.center(), osg::Vec3(0.0f,1.0f,0.0f));
            }
            else
            {
                osg::Vec3d upDirection(0.0,1.0,0.0);
                osg::Vec3d viewDirection(0.0,0.0,1.0);

                double viewDistance = 2.0*bs.radius();
                osg::Vec3d center = bs.center();
                osg::Vec3d eyePoint = center+viewDirection*viewDistance;

                double znear = viewDistance-bs.radius();
                double zfar  = viewDistance+bs.radius();

                float top   = bs.radius();
                float right = top;

                _camera->setProjectionMatrixAsOrtho(-right,right,-top,top,znear,zfar);
                _camera->setViewMatrixAsLookAt(eyePoint,center,upDirection);

            }

            // compute the matrix which takes a vertex from local coords into tex coords
            // will use this later to specify osg::TexGen..
            osg::Matrix MVP = _camera->getViewMatrix() *
                              _camera->getProjectionMatrix();

            osg::Matrix MVPT = MVP *
                               osg::Matrix::translate(1.0,1.0,1.0) *
                               osg::Matrix::scale(0.5,0.5,0.5);

            _texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
            _texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);

            _textureFrustum.setToUnitFrustum(false,false);
//            const osg::Matrix modelView = (cv->getModelViewMatrix());
//            _textureFrustum.transformProvidingInverse(osg::Matrix::inverse(modelView)*MVP);
            _textureFrustum.transformProvidingInverse(MVP);

            _camera->accept(*cv);

            _textureObjectValidList[contextID] = 1;
        }
    }

    // now set up the drawing of the main scene.
#if 0
    // Disable for time being as _overlaySubgraphBound isn't accurate for
    // detecting whether the overaly texture will sit over affect the rendering
    // of the children of the OverlayNode.  Frustrum intersection may prove more
    // fruitful.

    // note needs to use bound when captured not current bound.
    if (!_overlaySubgraphBound.valid() || cv->isCulled(_overlaySubgraphBound))
    {
        Group::traverse(nv);
    }
    else
#endif
    {

        _texgenNode->accept(*cv);

        const osg::Matrix modelView = (cv->getModelViewMatrix());
        osg::Polytope viewTextureFrustum;
        viewTextureFrustum.setAndTransformProvidingInverse(_textureFrustum, osg::Matrix::inverse(modelView));

        cv->getProjectionCullingStack().back().addStateFrustum(_mainSubgraphStateSet.get(), viewTextureFrustum);
        cv->getCurrentCullingSet().addStateFrustum(_mainSubgraphStateSet.get(), _textureFrustum);

        // push the stateset.
        // cv->pushStateSet(_mainSubgraphStateSet.get());

        Group::traverse(nv);

        // cv->popStateSet();

        cv->getCurrentCullingSet().getStateFrustumList().pop_back();
        cv->getProjectionCullingStack().back().getStateFrustumList().pop_back();
    }
}

void OverlayNode::setOverlaySubgraph(osg::Node* node)
{
    if (_overlaySubgraph == node) return;

    _overlaySubgraph = node;

    _camera->removeChildren(0, _camera->getNumChildren());
    _camera->addChild(node);

    dirtyOverlayTexture();
}

void OverlayNode::dirtyOverlayTexture()
{
    _textureObjectValidList.setAllElementsTo(0);
}

void OverlayNode::setOverlayClearColor(const osg::Vec4& color)
{
    _camera->setClearColor(color);
}

const osg::Vec4& OverlayNode::getOverlayClearColor() const
{
    return _camera->getClearColor();
}

void OverlayNode::setTexEnvMode(GLenum mode)
{
    _texEnvMode = mode;
    updateMainSubgraphStateSet();
}

void OverlayNode::setOverlayTextureUnit(unsigned int unit)
{
    _textureUnit = unit;

    _texgenNode->setTextureUnit(_textureUnit);

    updateMainSubgraphStateSet();
}

void OverlayNode::setOverlayTextureSizeHint(unsigned int size)
{
    if (_textureSizeHint == size) return;

    _textureSizeHint = size;
    //_texture->dirtyTextureObject();
    _texture->setTextureSize(_textureSizeHint, _textureSizeHint);
    _camera->setViewport(0,0,_textureSizeHint,_textureSizeHint);
}

void OverlayNode::updateMainSubgraphStateSet()
{
    _mainSubgraphStateSet->clear();
    _mainSubgraphStateSet->setTextureAttributeAndModes(_textureUnit, _texture.get(), osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);

    if (_texEnvMode!=GL_NONE)
    {
        _mainSubgraphStateSet->setTextureAttribute(_textureUnit, new osg::TexEnv((osg::TexEnv::Mode)_texEnvMode));
    }
}
<commit_msg>Fixed crash due on multipipe systems due by moving the local camera update code from the cull into the update traversal.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osg/Texture2D>
#include <osg/CoordinateSystemNode>
#include <osg/TexEnv>
#include <osg/io_utils>

#include <osgUtil/CullVisitor>
#include <osgSim/OverlayNode>

using namespace osgSim;
using namespace osg;

OverlayNode::OverlayNode():
    _texEnvMode(GL_DECAL),
    _textureUnit(1),
    _textureSizeHint(1024),
    _continuousUpdate(false)
{
    setNumChildrenRequiringUpdateTraversal(1);
    init();
}

OverlayNode::OverlayNode(const OverlayNode& copy, const osg::CopyOp& copyop):
    osg::Group(copy,copyop),
    _overlaySubgraph(copy._overlaySubgraph),
    _texEnvMode(copy._texEnvMode),
    _textureUnit(copy._textureUnit),
    _textureSizeHint(copy._textureSizeHint),
    _continuousUpdate(copy._continuousUpdate)
{
    setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
    init();
}

void OverlayNode::init()
{

    unsigned int tex_width = _textureSizeHint;
    unsigned int tex_height = _textureSizeHint;

    if (!_texture)
    {
        osg::Texture2D* texture = new osg::Texture2D;
        texture->setTextureSize(tex_width, tex_height);
        texture->setInternalFormat(GL_RGBA);
        texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
        texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
        texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
        texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
        texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
        _texture = texture;
    }

    // set up the render to texture camera.
    if (!_camera)
    {
        // create the camera
        _camera = new osg::CameraNode;

        _camera->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));

        // set viewport
        _camera->setViewport(0,0,tex_width,tex_height);

        // set the camera to render before the main camera.
        _camera->setRenderOrder(osg::CameraNode::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        _camera->setRenderTargetImplementation(osg::CameraNode::FRAME_BUFFER_OBJECT);

        // attach the texture and use it as the color buffer.
        _camera->attach(osg::CameraNode::COLOR_BUFFER, _texture.get());
    }

    if (!_texgenNode) _texgenNode = new osg::TexGenNode;

    if (!_mainSubgraphStateSet) _mainSubgraphStateSet = new osg::StateSet;

    setOverlayTextureUnit(_textureUnit);
}

void OverlayNode::traverse(osg::NodeVisitor& nv)
{
    if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
    {

        Group::traverse(nv);

        if (_continuousUpdate)
        {

            // now compute the camera's view and projection matrix to point at the shadower (the camera's children)
            osg::BoundingSphere bs;
            for(unsigned int i=0; i<_camera->getNumChildren(); ++i)
            {
                bs.expandBy(_camera->getChild(i)->getBound());
            }

            if (bs.valid())
            {
                // see if we are within a coordinate system node.
                osg::CoordinateSystemNode* csn = 0;
                osg::NodePath& nodePath = nv.getNodePath();
                for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
                    itr != nodePath.rend() && csn==0;
                    ++itr)
                {
                    csn = dynamic_cast<osg::CoordinateSystemNode*>(*itr);
                }

                _camera->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF);

                if (csn)
                {
                    osg::Vec3d eyePoint(0.0,0.0,0.0); // center of the planet
                    double centerDistance = (eyePoint-osg::Vec3d(bs.center())).length();

                    double znear = centerDistance-bs.radius();
                    double zfar  = centerDistance+bs.radius();
                    double zNearRatio = 0.001f;
                    if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

                    double top   = (bs.radius()/centerDistance)*znear;
                    double right = top;

                    _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
                    _camera->setViewMatrixAsLookAt(eyePoint, bs.center(), osg::Vec3(0.0f,1.0f,0.0f));
                }
                else
                {
                    osg::Vec3d upDirection(0.0,1.0,0.0);
                    osg::Vec3d viewDirection(0.0,0.0,1.0);

                    double viewDistance = 2.0*bs.radius();
                    osg::Vec3d center = bs.center();
                    osg::Vec3d eyePoint = center+viewDirection*viewDistance;

                    double znear = viewDistance-bs.radius();
                    double zfar  = viewDistance+bs.radius();

                    float top   = bs.radius();
                    float right = top;

                    _camera->setProjectionMatrixAsOrtho(-right,right,-top,top,znear,zfar);
                    _camera->setViewMatrixAsLookAt(eyePoint,center,upDirection);

                }

                // compute the matrix which takes a vertex from local coords into tex coords
                // will use this later to specify osg::TexGen..
                osg::Matrix MVP = _camera->getViewMatrix() *
                                  _camera->getProjectionMatrix();

                osg::Matrix MVPT = MVP *
                                   osg::Matrix::translate(1.0,1.0,1.0) *
                                   osg::Matrix::scale(0.5,0.5,0.5);

                _texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
                _texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);

                _textureFrustum.setToUnitFrustum(false,false);
                _textureFrustum.transformProvidingInverse(MVP);
            }
        }

        return;
    }

    if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
    {
        Group::traverse(nv);
        return;
    }

    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
    if (!cv)
    {
        Group::traverse(nv);
        return;
    }

    unsigned int contextID = cv->getState()!=0 ? cv->getState()->getContextID() : 0;

    // if we need to redraw then do cull traversal on camera.
    if (!_textureObjectValidList[contextID] || _continuousUpdate)
    {
        _camera->accept(*cv);
        _textureObjectValidList[contextID] = 1;
    }

    // now set up the drawing of the main scene.
#if 0
    // Disable for time being as _overlaySubgraphBound isn't accurate for
    // detecting whether the overaly texture will sit over affect the rendering
    // of the children of the OverlayNode.  Frustrum intersection may prove more
    // fruitful.

    // note needs to use bound when captured not current bound.
    if (!_overlaySubgraphBound.valid() || cv->isCulled(_overlaySubgraphBound))
    {
        Group::traverse(nv);
    }
    else
#endif
    {

        _texgenNode->accept(*cv);

        const osg::Matrix modelView = (cv->getModelViewMatrix());
        osg::Polytope viewTextureFrustum;
        viewTextureFrustum.setAndTransformProvidingInverse(_textureFrustum, osg::Matrix::inverse(modelView));

        cv->getProjectionCullingStack().back().addStateFrustum(_mainSubgraphStateSet.get(), viewTextureFrustum);
        cv->getCurrentCullingSet().addStateFrustum(_mainSubgraphStateSet.get(), _textureFrustum);

        // push the stateset.
        // cv->pushStateSet(_mainSubgraphStateSet.get());

        Group::traverse(nv);

        // cv->popStateSet();

        cv->getCurrentCullingSet().getStateFrustumList().pop_back();
        cv->getProjectionCullingStack().back().getStateFrustumList().pop_back();
    }
}

void OverlayNode::setOverlaySubgraph(osg::Node* node)
{
    if (_overlaySubgraph == node) return;

    _overlaySubgraph = node;

    _camera->removeChildren(0, _camera->getNumChildren());
    _camera->addChild(node);

    dirtyOverlayTexture();
}

void OverlayNode::dirtyOverlayTexture()
{
    _textureObjectValidList.setAllElementsTo(0);
}

void OverlayNode::setOverlayClearColor(const osg::Vec4& color)
{
    _camera->setClearColor(color);
}

const osg::Vec4& OverlayNode::getOverlayClearColor() const
{
    return _camera->getClearColor();
}

void OverlayNode::setTexEnvMode(GLenum mode)
{
    _texEnvMode = mode;
    updateMainSubgraphStateSet();
}

void OverlayNode::setOverlayTextureUnit(unsigned int unit)
{
    _textureUnit = unit;

    _texgenNode->setTextureUnit(_textureUnit);

    updateMainSubgraphStateSet();
}

void OverlayNode::setOverlayTextureSizeHint(unsigned int size)
{
    if (_textureSizeHint == size) return;

    _textureSizeHint = size;
    //_texture->dirtyTextureObject();
    _texture->setTextureSize(_textureSizeHint, _textureSizeHint);
    _camera->setViewport(0,0,_textureSizeHint,_textureSizeHint);
}

void OverlayNode::updateMainSubgraphStateSet()
{
    _mainSubgraphStateSet->clear();
    _mainSubgraphStateSet->setTextureAttributeAndModes(_textureUnit, _texture.get(), osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
    _mainSubgraphStateSet->setTextureMode(_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);

    if (_texEnvMode!=GL_NONE)
    {
        _mainSubgraphStateSet->setTextureAttribute(_textureUnit, new osg::TexEnv((osg::TexEnv::Mode)_texEnvMode));
    }
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgTerrain/Locator>
#include <osg/Notify>

#include <list>

using namespace osgTerrain;

//////////////////////////////////////////////////////////////////////////////
//
// Locator
//
Locator::Locator():
    _coordinateSystemType(PROJECTED),
    _ellipsoidModel(new osg::EllipsoidModel()),
    _definedInFile(false)
{
}

Locator::Locator(const Locator& locator,const osg::CopyOp& copyop):
    osg::Object(locator,copyop),
    _coordinateSystemType(locator._coordinateSystemType),
    _ellipsoidModel(locator._ellipsoidModel),
    _format(locator._format),
    _cs(locator._cs),
    _transform(locator._transform),
    _definedInFile(locator._definedInFile)
{
}

Locator::~Locator()
{
}

void Locator::setTransformAsExtents(double minX, double minY, double maxX, double maxY)
{
    _transform.set(maxX-minX, 0.0,       0.0, 0.0,
                   0.0,       maxY-minY, 0.0, 0.0,
                   0.0,       0.0,       1.0, 0.0,
                   minX,      minY,      0.0, 1.0);
}

bool Locator::computeLocalBounds(Locator& source, osg::Vec3d& bottomLeft, osg::Vec3d& topRight)
{
    typedef std::list<osg::Vec3d> Corners;
    Corners corners;

    osg::Vec3d cornerNDC;
    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(0.0,0.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(1.0,0.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(0.0,1.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(1.0,1.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (corners.empty()) return false;

    for(Corners::iterator itr = corners.begin();
        itr != corners.end();
        ++itr)
    {
        bottomLeft.x() = osg::minimum( bottomLeft.x(), itr->x());
        bottomLeft.y() = osg::minimum( bottomLeft.y(), itr->y());
        topRight.x() = osg::maximum( topRight.x(), itr->x());
        topRight.y() = osg::maximum( topRight.y(), itr->y());
    }

    return true;
}

bool Locator::orientationOpenGL() const
{
    return _transform(0,0) * _transform(1,1) >= 0.0;
}

bool Locator::convertLocalToModel(const osg::Vec3d& local, osg::Vec3d& world) const
{
    switch(_coordinateSystemType)
    {
        case(GEOCENTRIC):
        {
            osg::Vec3d geographic = local * _transform;

            _ellipsoidModel->convertLatLongHeightToXYZ(geographic.x(), geographic.y(), geographic.z(),
                                                       world.x(), world.y(), world.z());
            return true;
        }
        case(GEOGRAPHIC):
        {
            world = local * _transform;
            return true;
        }
        case(PROJECTED):
        {
            world = local * _transform;
            return true;
        }
    }

    return false;
}

bool Locator::convertModelToLocal(const osg::Vec3d& world, osg::Vec3d& local) const
{
    switch(_coordinateSystemType)
    {
        case(GEOCENTRIC):
        {
            double longitude, latitude, height;

            _ellipsoidModel->convertXYZToLatLongHeight(world.x(), world.y(), world.z(),
                                                       latitude, longitude, height );

            local = osg::Vec3d(longitude, latitude, height) * _inverse;

            return true;
        }
        case(GEOGRAPHIC):
        {
            local = world * _inverse;

            return true;
        }
        case(PROJECTED):
        {
            local = world * _inverse;
            return true;
        }
    }

    return false;
}
<commit_msg>From Maria Ten, fix lat/long usage.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgTerrain/Locator>
#include <osg/Notify>

#include <list>

using namespace osgTerrain;

//////////////////////////////////////////////////////////////////////////////
//
// Locator
//
Locator::Locator():
    _coordinateSystemType(PROJECTED),
    _ellipsoidModel(new osg::EllipsoidModel()),
    _definedInFile(false)
{
}

Locator::Locator(const Locator& locator,const osg::CopyOp& copyop):
    osg::Object(locator,copyop),
    _coordinateSystemType(locator._coordinateSystemType),
    _ellipsoidModel(locator._ellipsoidModel),
    _format(locator._format),
    _cs(locator._cs),
    _transform(locator._transform),
    _definedInFile(locator._definedInFile)
{
}

Locator::~Locator()
{
}

void Locator::setTransformAsExtents(double minX, double minY, double maxX, double maxY)
{
    _transform.set(maxX-minX, 0.0,       0.0, 0.0,
                   0.0,       maxY-minY, 0.0, 0.0,
                   0.0,       0.0,       1.0, 0.0,
                   minX,      minY,      0.0, 1.0);
}

bool Locator::computeLocalBounds(Locator& source, osg::Vec3d& bottomLeft, osg::Vec3d& topRight)
{
    typedef std::list<osg::Vec3d> Corners;
    Corners corners;

    osg::Vec3d cornerNDC;
    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(0.0,0.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(1.0,0.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(0.0,1.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (Locator::convertLocalCoordBetween(source, osg::Vec3d(1.0,1.0,0.0), *this, cornerNDC))
    {
        corners.push_back(cornerNDC);
    }

    if (corners.empty()) return false;

    for(Corners::iterator itr = corners.begin();
        itr != corners.end();
        ++itr)
    {
        bottomLeft.x() = osg::minimum( bottomLeft.x(), itr->x());
        bottomLeft.y() = osg::minimum( bottomLeft.y(), itr->y());
        topRight.x() = osg::maximum( topRight.x(), itr->x());
        topRight.y() = osg::maximum( topRight.y(), itr->y());
    }

    return true;
}

bool Locator::orientationOpenGL() const
{
    return _transform(0,0) * _transform(1,1) >= 0.0;
}

bool Locator::convertLocalToModel(const osg::Vec3d& local, osg::Vec3d& world) const
{
    switch(_coordinateSystemType)
    {
        case(GEOCENTRIC):
        {
            osg::Vec3d geographic = local * _transform;

            _ellipsoidModel->convertLatLongHeightToXYZ(geographic.y(), geographic.x(), geographic.z(),
                                                       world.x(), world.y(), world.z());
            return true;
        }
        case(GEOGRAPHIC):
        {
            world = local * _transform;
            return true;
        }
        case(PROJECTED):
        {
            world = local * _transform;
            return true;
        }
    }

    return false;
}

bool Locator::convertModelToLocal(const osg::Vec3d& world, osg::Vec3d& local) const
{
    switch(_coordinateSystemType)
    {
        case(GEOCENTRIC):
        {
            double longitude, latitude, height;

            _ellipsoidModel->convertXYZToLatLongHeight(world.x(), world.y(), world.z(),
                                                       latitude, longitude, height );

            local = osg::Vec3d(longitude, latitude, height) * _inverse;

            return true;
        }
        case(GEOGRAPHIC):
        {
            local = world * _inverse;

            return true;
        }
        case(PROJECTED):
        {
            local = world * _inverse;
            return true;
        }
    }

    return false;
}
<|endoftext|>