Program Listing for File StaticGeometry.h

Program Listing for File StaticGeometry.h#

Return to documentation for file (include/Karana/Scene/StaticGeometry.h)

/*
 * Copyright (c) 2024-2026 Karana Dynamics Pty Ltd. All rights reserved.
 *
 * NOTICE TO USER:
 *
 * This source code and/or documentation (the "Licensed Materials") is
 * the confidential and proprietary information of Karana Dynamics Inc.
 * Use of these Licensed Materials is governed by the terms and conditions
 * of a separate software license agreement between Karana Dynamics and the
 * Licensee ("License Agreement"). Unless expressly permitted under that
 * agreement, any reproduction, modification, distribution, or disclosure
 * of the Licensed Materials, in whole or in part, to any third party
 * without the prior written consent of Karana Dynamics is strictly prohibited.
 *
 * THE LICENSED MATERIALS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
 * KARANA DYNAMICS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL KARANA DYNAMICS BE LIABLE FOR ANY DAMAGES WHATSOEVER,
 * INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS, DATA, OR USE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, WHETHER IN CONTRACT, TORT,
 * OR OTHERWISE ARISING OUT OF OR IN CONNECTION WITH THE LICENSED MATERIALS.
 *
 * U.S. Government End Users: The Licensed Materials are a "commercial item"
 * as defined at 48 C.F.R. 2.101, and are provided to the U.S. Government
 * only as a commercial end item under the terms of this license.
 *
 * Any use of the Licensed Materials in individual or commercial software must
 * include, in the user documentation and internal source code comments,
 * this Notice, Disclaimer, and U.S. Government Use Provision.
 */

/**
 * @file
 * @brief Contains the declarations for the geometry classes, such as StaticMeshGeometry or
 * BoxGeometry.
 */

#pragma once
#include <string>
#include <variant>

#include "Karana/KCore/Base.h"
#include "Karana/KCore/SharedPointer.h"
#include "Karana/Math/AABB.h"

namespace Karana::Scene {
    class StaticMeshGeometry;

    /**
     * @class AbstractStaticGeometry
     * @brief Interface for static geometry types
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class AbstractStaticGeometry : public Karana::Core::Base {
      public:
        /**
         * @brief Constructor
         *
         * @param name the geometry's name
         *
         */
        AbstractStaticGeometry(std::string_view name);

        virtual ~AbstractStaticGeometry();

        /**
         * @brief Convert to a triangular mesh
         * @return The converted mesh
         */
        virtual operator StaticMeshGeometry() const = 0;

        /**
         * @brief Compute the axis-aligned bounding box (AABB)
         * @return The AABB
         */
        virtual Karana::Math::AABB aabb() const = 0;
    };

    /**
     * @class BoxGeometry
     * @brief Concrete box geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class BoxGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from side-lengths
         *
         * @param width side length in the x direction
         * @param height side length in the y direction
         * @param depth side length in the z direction
         *
         */
        BoxGeometry(float width, float height, float depth);

        /// Copy constructor
        BoxGeometry(const BoxGeometry &);

        BoxGeometry &operator=(const BoxGeometry &) = delete;

        BoxGeometry(BoxGeometry &&) = delete;
        BoxGeometry &operator=(BoxGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// side length in the x direction
        const float width;

        /// side length in the y direction
        const float height;

        /// side length in the z direction
        const float depth;
    };

    /**
     * @class CapsuleGeometry
     * @brief Geometry class for a cylinder capped with hemispheres
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class CapsuleGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from a radius and height
         *
         * @param radius radius of the capsule
         * @param height height of the capsule's middle section
         */
        CapsuleGeometry(float radius, float height);

        /// Copy constructor
        CapsuleGeometry(const CapsuleGeometry &);

        CapsuleGeometry &operator=(const CapsuleGeometry &) = delete;

        CapsuleGeometry(CapsuleGeometry &&) = delete;
        CapsuleGeometry &operator=(CapsuleGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// radius of the capsule
        const float radius;

        /// height of the capsule's middle section
        const float height;
    };

    /**
     * @class ConeGeometry
     * @brief Concrete cone geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class ConeGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from a radius and height
         *
         * @param radius radius of the cone
         * @param height height of the cone
         */
        ConeGeometry(float radius, float height);

        /// Copy constructor
        ConeGeometry(const ConeGeometry &);

        ConeGeometry &operator=(const ConeGeometry &) = delete;

        ConeGeometry(ConeGeometry &&) = delete;
        ConeGeometry &operator=(ConeGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// radius of the cone
        const float radius;

        /// height of the cone
        const float height;
    };

    /**
     * @class CylinderGeometry
     * @brief Concrete cylinder geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class CylinderGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from a radius and height
         *
         * @param radius radius of the cylinder
         * @param height height of the cylinder
         */
        CylinderGeometry(float radius, float height);

        /// Copy constructor
        CylinderGeometry(const CylinderGeometry &);

        CylinderGeometry &operator=(const CylinderGeometry &) = delete;

        CylinderGeometry(CylinderGeometry &&) = delete;
        CylinderGeometry &operator=(CylinderGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// radius of the cylinder
        const float radius;

        /// height of the cylinder
        const float height;
    };

    /**
     * @class RoundFrustumGeometry
     * @brief Concrete round frustum geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class RoundFrustumGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from a radii and height
         *
         * @param bottom_radius radius of bottom face
         * @param top_radius radius of top face
         * @param height height of the frustum
         */
        RoundFrustumGeometry(float bottom_radius, float top_radius, float height);

        /// Copy constructor
        RoundFrustumGeometry(const RoundFrustumGeometry &);
        RoundFrustumGeometry &operator=(const RoundFrustumGeometry &) = delete;

        RoundFrustumGeometry(RoundFrustumGeometry &&) = delete;
        RoundFrustumGeometry &operator=(RoundFrustumGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// radius of the bottom face
        const float bottom_radius;

        /// radius of the top face
        const float top_radius;

        /// height of the frustum
        const float height;
    };

    /**
     * @class SphereGeometry
     * @brief Concrete sphere geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class SphereGeometry : public AbstractStaticGeometry {
      public:
        /**
         * @brief Constructor from a radius
         *
         * @param radius radius of the sphere
         */
        SphereGeometry(float radius);

        /// Copy constructor
        SphereGeometry(const SphereGeometry &);
        SphereGeometry &operator=(const SphereGeometry &) = delete;

        SphereGeometry(SphereGeometry &&) = delete;
        SphereGeometry &operator=(SphereGeometry &&) = delete;

        operator StaticMeshGeometry() const override;

        Karana::Math::AABB aabb() const override;

        /// radius of the sphere
        const float radius;
    };

    /**
     * @class StaticMeshGeometry
     * @brief Concrete triangular mesh geometry class
     *
     * See \sref{scene_layer_sec} for more discussion on
     * the scene layer.
     */
    class StaticMeshGeometry : public AbstractStaticGeometry {
      public:
        // Using RowMajor so that the underlying
        // buffer can be used as-is in client
        // libraries
        /// type alias for real-valued 3-vector array
        using Float3Array = Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::RowMajor>;
        /// type alias for real-valued 2-vector array
        using Float2Array = Eigen::Matrix<float, Eigen::Dynamic, 2, Eigen::RowMajor>;
        /// type alias for integer-valued 3-vector array
        using Int3Array = Eigen::Matrix<int, Eigen::Dynamic, 3, Eigen::RowMajor>;

        /**
         * @brief Constructor from vertices and faces
         *
         * @param positions matrix of vertex positions
         * @param faces matrix of triangles as three vertex indices
         * @param normals matrix of vertex normals
         * @param surface_map_coords matrix of uv (texture) coords
         *
         */
        StaticMeshGeometry(const Float3Array &positions,
                           const Int3Array &faces,
                           const Float3Array &normals,
                           const Float2Array &surface_map_coords);

        /// copy constructor
        StaticMeshGeometry(const StaticMeshGeometry &);

        StaticMeshGeometry &operator=(const StaticMeshGeometry &) = delete;

        StaticMeshGeometry(StaticMeshGeometry &&) = delete;
        StaticMeshGeometry &operator=(StaticMeshGeometry &&) = delete;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-conversion"
        // A conversion operator to the same type is pointless and generates a warning.
        // We still need an implementation to be concrete, so we suppress the warning.
        /// Convert to a triangular mesh
        operator StaticMeshGeometry() const override;
#pragma GCC diagnostic pop

        Karana::Math::AABB aabb() const override;

        /// vertex positions
        const Float3Array positions;
        /// triangles consisting of three vertex indices
        const Int3Array faces;
        /// vertex normals
        const Float3Array normals;
        /// vertex uv (texture) coordinates
        const Float2Array surface_map_coords;

        /// If this mesh comes from a file, this is the filename.
        std::string filename = "";
    };

    /**
     * Variant type containing all known static geometries as well as
     * AbstractStaticGeometry for any unknown derivations
     */
    using VarStaticGeometry = std::variant<Karana::Core::ks_ptr<BoxGeometry>,
                                           Karana::Core::ks_ptr<CapsuleGeometry>,
                                           Karana::Core::ks_ptr<ConeGeometry>,
                                           Karana::Core::ks_ptr<CylinderGeometry>,
                                           Karana::Core::ks_ptr<RoundFrustumGeometry>,
                                           Karana::Core::ks_ptr<SphereGeometry>,
                                           Karana::Core::ks_ptr<StaticMeshGeometry>,
                                           Karana::Core::ks_ptr<AbstractStaticGeometry>>;

    /**
     * Gets the default geometry
     *
     * @return The default geometry
     */
    const VarStaticGeometry &defaultGeometry();
} // namespace Karana::Scene