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 shape with half-extents derived from size.
capsule
staticmethod
¶
Capsule shape (cylinder + hemispherical end-caps, axis = body +Z).
convex_mesh
staticmethod
¶
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
¶
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:
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 |