LCOV - code coverage report
Current view: top level - rbc/shapes - Cone.hpp (source / functions) Coverage Total Hit
Test: coverage_clean.info Lines: 0.0 % 21 0
Test Date: 2026-03-30 03:13:12 Functions: 0.0 % 2 0

            Line data    Source code
       1              : #pragma once
       2              : #include <math3d/math3d.hpp>
       3              : #include "rbc/AABB.hpp"
       4              : 
       5              : namespace rbc
       6              : {
       7              :     // ── Cone ──────────────────────────────────────────────────────────────────
       8              :     // Right circular cone. In local space:
       9              :     //   Apex   = (0, +half_height, 0)
      10              :     //   Base centre = (0, -half_height, 0), radius = base_radius
      11              :     // Total height = 2*half_height.
      12              :     struct Cone
      13              :     {
      14              :         m3d::scalar half_height;
      15              :         m3d::scalar base_radius;
      16              : 
      17              :         Cone() : half_height(0.5), base_radius(0.5) {}
      18              :         Cone(m3d::scalar half_height, m3d::scalar base_radius)
      19              :             : half_height(half_height), base_radius(base_radius) {}
      20              : 
      21              :         inline bool operator==(const Cone &o) const
      22              :         {
      23              :             return half_height == o.half_height && base_radius == o.base_radius;
      24              :         }
      25              :         inline bool operator!=(const Cone &o) const { return !(*this == o); }
      26              :     };
      27              : 
      28              :     // ── Support function (local space) ────────────────────────────────────────
      29              :     // Candidates: apex (0, h, 0) or base-circle edge point.
      30              :     // We compare d·apex vs d·(base_point), pick the larger.
      31              :     //   apex_dot       = d.y · h
      32              :     //   base_edge_dot  = d_radial · base_radius − d.y · h
      33              :     // where d_radial = sqrt(d.x² + d.z²).
      34            0 :     inline m3d::vec3 support(const Cone &c, const m3d::vec3 &dir)
      35              :     {
      36            0 :         const m3d::scalar d_radial = m3d::sqrt(dir.x * dir.x + dir.z * dir.z);
      37              : 
      38            0 :         if (d_radial < m3d::EPSILON)
      39              :         {
      40              :             // Direction is purely axial
      41            0 :             return (dir.y >= 0.0)
      42            0 :                        ? m3d::vec3(0.0, c.half_height, 0.0)             // apex
      43            0 :                        : m3d::vec3(c.base_radius, -c.half_height, 0.0); // base edge (arbitrary angle)
      44              :         }
      45              : 
      46            0 :         const m3d::scalar apex_dot = dir.y * c.half_height;
      47            0 :         const m3d::scalar base_edge_dot = d_radial * c.base_radius - dir.y * c.half_height;
      48              : 
      49            0 :         if (apex_dot >= base_edge_dot)
      50            0 :             return m3d::vec3(0.0, c.half_height, 0.0); // apex wins
      51              : 
      52              :         // Base-circle edge point in the radial direction of dir
      53            0 :         const m3d::scalar scale = c.base_radius / d_radial;
      54            0 :         return m3d::vec3(dir.x * scale, -c.half_height, dir.z * scale);
      55              :     }
      56              : 
      57              :     inline m3d::scalar compute_volume(const Cone &c)
      58              :     {
      59              :         return (1.0 / 3.0) * m3d::PI * c.base_radius * c.base_radius * (2.0 * c.half_height);
      60              :     }
      61              : 
      62              :     // Inertia tensor about the cone's local axes (unit density).
      63              :     // For a solid cone of height H=2h, base radius R, mass m:
      64              :     //   Iyy (axial)     = (3/10) · m · R²
      65              :     //   Ixx (transverse) = (3/20) · m · (R² + H²/4) shifted to centroid
      66              :     // The centroid is at 3H/8 from the base = h/4 from the centre (positive Y side).
      67              :     inline m3d::smat3 compute_inertia_tensor(const Cone &c)
      68              :     {
      69              :         const m3d::scalar mass = compute_volume(c);
      70              :         const m3d::scalar R2 = c.base_radius * c.base_radius;
      71              :         const m3d::scalar H = 2.0 * c.half_height;
      72              :         const m3d::scalar Iyy = (3.0 / 10.0) * mass * R2;
      73              :         // Transverse about apex, then shift to centroid (h/4 from mid-point)
      74              :         const m3d::scalar Ixx_apex = (3.0 / 5.0) * mass * (R2 / 4.0 + H * H);
      75              :         const m3d::scalar d_centroid = 3.0 * H / 8.0 - c.half_height; // offset from local origin
      76              :         const m3d::scalar Ixx = Ixx_apex - mass * d_centroid * d_centroid;
      77              :         return m3d::smat3(Ixx, Iyy, Ixx, 0.0, 0.0, 0.0);
      78              :     }
      79              : 
      80              :     // ── Tight AABB via 6-direction support ────────────────────────────────────
      81              :     // More accurate than a bounding sphere, still O(1).
      82            0 :     inline AABB compute_aabb(const Cone &c, const m3d::tf &tf)
      83              :     {
      84              :         const m3d::vec3 world_axes[6] = {
      85            0 :             {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
      86              : 
      87            0 :         m3d::vec3 mn = tf.pos, mx = tf.pos;
      88            0 :         for (const auto &axis : world_axes)
      89              :         {
      90            0 :             const m3d::vec3 local_dir = tf.inverse_rotate_vector(axis);
      91            0 :             const m3d::vec3 world_sup = tf.pos + tf.rotate_vector(support(c, local_dir));
      92            0 :             mn = m3d::vec3(m3d::min(mn.x, world_sup.x), m3d::min(mn.y, world_sup.y), m3d::min(mn.z, world_sup.z));
      93            0 :             mx = m3d::vec3(m3d::max(mx.x, world_sup.x), m3d::max(mx.y, world_sup.y), m3d::max(mx.z, world_sup.z));
      94              :         }
      95            0 :         return {mn, mx};
      96              :     }
      97              : } // namespace rbc
        

Generated by: LCOV version 2.0-1