Skip to content

forge3d.Shape & Material

Shape

Shape descriptors define the collision geometry of a body.

Shape dataclass

Collision / visual shape descriptor.

Create via factory methods::

Shape.box(size=(1, 1, 1))
Shape.sphere(radius=0.5)
Shape.capsule(radius=0.2, half_length=0.5)
Shape.convex_mesh(mesh_data)   # MeshData from load_obj()

box staticmethod

box(size: Any = (1.0, 1.0, 1.0)) -> Shape

Box shape with half-extents derived from size.

sphere staticmethod

sphere(radius: float = 0.5) -> Shape

Sphere shape.

capsule staticmethod

capsule(radius: float = 0.2, half_length: float = 0.5) -> Shape

Capsule shape (cylinder + hemispherical end-caps, axis = body +Z).

convex_mesh staticmethod

convex_mesh(mesh_data: Any) -> Shape

Convex-hull collision shape from a MeshData object.

Load mesh data with::

from forge3d.io import load_obj
mesh = load_obj("model.obj")
shape = Shape.convex_mesh(mesh)

Material

Material describes the visual appearance (PBR).

Material dataclass

Surface appearance for a rigid body.

Color can be a preset name (str) or an RGB tuple in [0, 1]. Preset names: 'default', 'red', 'blue', 'green', 'orange', 'ground', 'gold', 'white'. Use texture_path for an albedo image (PNG/JPEG, loaded at render time).

Examples

Material(color="red") Material(color=(0.9, 0.4, 0.1), roughness=0.3) Material(color="default", metallic=0.8, roughness=0.2) Material(texture_path="wall.png")

Material parameters

Field Type Default Description
color str \| tuple "default" Preset name or (R, G, B) in [0, 1]
roughness float 0.5 0 = mirror, 1 = fully diffuse
metallic float 0.0 0 = dielectric, 1 = conductor
emissive float 0.0 Emissive glow intensity (0 = no glow)
texture_path str \| None None Path to albedo PNG/JPEG
normal_map_path str \| None None Path to tangent-space normal map
# Standard PBR material
f3d.Material(color=(0.1, 0.5, 0.9), roughness=0.2, metallic=0.8)

# Glowing object (e.g. lava, neon sign)
f3d.Material(color=(1.0, 0.3, 0.0), emissive=3.0)

# Textured surface
f3d.Material(texture_path="assets/sand.png", roughness=0.9)

Built-in colour presets

Name RGB
"default" (0.75, 0.75, 0.75)
"red" (0.90, 0.20, 0.10)
"blue" (0.15, 0.35, 0.90)
"green" (0.15, 0.70, 0.25)
"orange" (0.95, 0.55, 0.05)
"gold" (0.83, 0.68, 0.21) metallic=1
"white" (0.95, 0.95, 0.95)
"ground" (0.30, 0.48, 0.28)

CollisionLayer

Bit-field constants for collision filtering.

CollisionLayer

Named bit-field constants for collision layers.

Collision rule: bodies A and B collide if and only if: (A.collision_layer & B.collision_mask) != 0 and (B.collision_layer & A.collision_mask) != 0

The default is layer 0x0001 with mask 0xFFFF (collide with everything).

mask_for staticmethod

mask_for(*layers: int) -> int

Return a bitmask that matches any of the given layers.

Example::

# Player body collides with terrain and enemies:
player.collision_mask = CollisionLayer.mask_for(
    CollisionLayer.TERRAIN,
    CollisionLayer.ENEMY,
)
# → 0b00001100 = 0x000C

Layer table

Constant Value Typical use
DEFAULT 0x0001 Generic objects
PLAYER 0x0002 Player character
ENEMY 0x0004 Enemy bodies
TERRAIN 0x0008 Heightfield terrain
TRIGGER 0x0010 Trigger zones
BULLET 0x0020 Projectiles
DEBRIS 0x0040 Breakable pieces
SENSOR 0x0080 Sensor-only bodies
NONE 0x0000 Disable all collision
ALL 0xFFFF Collide with everything

Collision rule

Bodies A and B collide if and only if:

(A.collision_layer & B.collision_mask) != 0
AND
(B.collision_layer & A.collision_mask) != 0

Usage

from forge3d import CollisionLayer

player = world.add_capsule(radius=0.3, half_length=0.9, name="player")
player.collision_layer = CollisionLayer.PLAYER
player.collision_mask  = CollisionLayer.mask_for(
    CollisionLayer.TERRAIN,
    CollisionLayer.ENEMY,
)  # player collides with terrain and enemies only

bullet = world.add_sphere(radius=0.05, mass=0.01)
bullet.collision_layer = CollisionLayer.BULLET
bullet.collision_mask  = CollisionLayer.mask_for(
    CollisionLayer.ENEMY,
    CollisionLayer.DEFAULT,
)  # bullets hit enemies and default objects, not other bullets

# Filter overlap / raycast queries by layer
hits = world.raycast_all(origin, direction,
                          layer_mask=CollisionLayer.ENEMY)

JointType

Type-safe enumeration for world.add_joint().

JointType

Bases: StrEnum

Enumeration of supported joint types.

Pass to :meth:forge3d.World.add_joint as joint_type::

hinge = world.add_joint(JointType.HINGE, door, frame,
                        anchor_a=(-0.5, 0, 0),
                        anchor_b=( 0.5, 0, 0),
                        axis=(0, 0, 1))

All values are also accepted as plain strings (case-insensitive): "hinge" == JointType.HINGE.

from forge3d import JointType

hinge = world.add_joint(
    JointType.HINGE, door, frame,
    anchor_a=(-0.5, 0, 0), anchor_b=(0.5, 0, 0),
    axis=(0, 0, 1), limits=(-1.5, 0.0),
)
spring = world.add_joint(
    JointType.SPRING, box, ceiling,
    stiffness=200.0, damping=10.0, rest_length=2.0,
)
Value Alias DOF Typical use
FIXED 0 Rigid weld
BALL 3 rot Shoulder, ball-socket
HINGE REVOLUTE 1 rot Door hinge, wheel
PRISMATIC SLIDER 1 lin Piston, elevator
DISTANCE Keep anchor distance
SPRING Elastic tether