# `omath::primitives::create_box` — Build an oriented box as 12 triangles > Header: your project’s `primitives/box.hpp` (declares `create_box`) > Namespace: `omath::primitives` > Depends on: `omath::Triangle>`, `omath::Vector3` ```cpp [[nodiscard]] std::array>, 12> create_box(const Vector3& top, const Vector3& bottom, const Vector3& dir_forward, const Vector3& dir_right, float ratio = 4.f) noexcept; ``` --- ## What it does Constructs a **rectangular cuboid (“box”)** oriented in 3D space and returns its surface as **12 triangles** (2 per face × 6 faces). The box’s central axis runs from `bottom` → `top`. The **up** direction is inferred from that segment; the **forward** and **right** directions define the box’s orientation around that axis. The lateral half-extents are derived from the axis length and `ratio`: > Let `H = |top - bottom|`. Lateral half-size ≈ `H / ratio` along both `dir_forward` and `dir_right` > (i.e., the cross-section is a square of side `2H/ratio`). > **Note:** This describes the intended behavior from the interface. If you rely on a different sizing rule, document it next to your implementation. --- ## Parameters * `top` Center of the **top face**. * `bottom` Center of the **bottom face**. * `dir_forward` A direction that orients the box around its up axis. Should be **non-zero** and **not collinear** with `top - bottom`. * `dir_right` A direction roughly orthogonal to both `dir_forward` and `top - bottom`. Used to fully fix orientation. * `ratio` (default `4.0f`) Controls thickness relative to height. Larger values → thinner box. With the default rule above, half-extent = `|top-bottom|/ratio`. --- ## Return value `std::array>, 12>` — the six faces of the box, triangulated. Winding is intended to be **outward-facing** (right-handed coordinates). Do not rely on a specific **face ordering**; treat the array as opaque unless your implementation guarantees an order. --- ## Expected math & robustness * Define `u = normalize(top - bottom)`. * Re-orthonormalize the basis to avoid skew: ```cpp f = normalize(dir_forward - u * u.dot(dir_forward)); // drop any up component r = normalize(u.cross(f)); // right-handed basis // (Optionally recompute f = r.cross(u) for orthogonality) ``` * Half-extents: `h = length(top - bottom) / ratio; hf = h * f; hr = h * r`. * Corners (top): `t±r±f = top ± hr ± hf`; (bottom): `b±r±f = bottom ± hr ± hf`. * Triangulate each face with consistent CCW winding when viewed from outside. --- ## Example ```cpp using omath::Vector3; using omath::Triangle; using omath::primitives::create_box; // Axis from bottom to top (height 2) Vector3 bottom{0, 0, 0}; Vector3 top {0, 2, 0}; // Orientation around the axis Vector3 forward{0, 0, 1}; Vector3 right {1, 0, 0}; // Ratio 4 → lateral half-size = height/4 = 0.5 auto tris = create_box(top, bottom, forward, right, 4.0f); // Use the triangles (normals, rendering, collision, etc.) for (const auto& tri : tris) { auto n = tri.calculate_normal(); (void)n; } ``` --- ## Usage notes & pitfalls * **Degenerate axis**: If `top == bottom`, the box is undefined (zero height). Guard against this. * **Directions**: Provide **non-zero**, **reasonably orthogonal** `dir_forward`/`dir_right`. A robust implementation should project/normalize internally, but callers should still pass sensible inputs. * **Winding**: If your renderer or collision expects a specific winding, verify with a unit test and flip vertex order per face if necessary. * **Thickness policy**: This doc assumes both lateral half-extents equal `|top-bottom|/ratio`. If your implementation diverges (e.g., separate forward/right ratios), document it. --- ## See also * `omath::Triangle` (vertex utilities: normals, centroid, etc.) * `omath::Vector3` (geometry operations used by the construction) --- *Last updated: 31 Oct 2025*