Source code for simvx.core.physics._material

"""Physics material, body modes, contacts, and shared helpers.

Private leaf module: import via the ``simvx.core.physics`` facade.
"""

from dataclasses import dataclass
from enum import IntEnum
from typing import Any

import numpy as np

__all__ = [
    "PhysicsMaterial",
    "BodyMode",
    "Contact",
]

# ============================================================================
# PhysicsMaterial
# ============================================================================

[docs] @dataclass(slots=True) class PhysicsMaterial: """Surface properties for physics bodies. Attributes: friction: Coefficient of friction [0..1]. Higher = more grip. restitution: Coefficient of restitution [0..1]. 1 = perfectly elastic bounce. density: Mass per unit volume. Used for auto-computing mass from shape volume. """ friction: float = 0.5 restitution: float = 0.3 density: float = 1.0
# ============================================================================ # BodyMode # ============================================================================
[docs] class BodyMode(IntEnum): """Physics body simulation mode.""" DYNAMIC = 0 # Fully simulated: affected by forces and collisions KINEMATIC = 1 # Moved by code only, not affected by forces, but participates in collisions STATIC = 2 # Never moves: infinite mass, zero velocity
# ============================================================================ # Contact: Collision contact point # ============================================================================
[docs] @dataclass(slots=True) class Contact: """A single collision contact between two bodies. Attributes: body_a: First body in the collision pair. body_b: Second body in the collision pair. normal: Contact normal pointing from A to B (normalized). point: Contact point in world space. depth: Penetration depth (positive when overlapping). """ body_a: Any body_b: Any normal: np.ndarray point: np.ndarray depth: float
# ============================================================================ # Shared helpers # ============================================================================ def _quat_to_matrix(q) -> np.ndarray: """Convert a quaternion to a 3x3 rotation matrix.""" x, y, z, w = float(q.x), float(q.y), float(q.z), float(q.w) return np.array([ [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)], [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)], [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)], ], dtype=np.float32)