physics

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var GPUBodySource string

GPUBodySource is the canonical WGSL definition of the Body struct. Matches GPUBody layout exactly (160 bytes, std430 aligned).

View Source
var GPUGridCellSource string

GPUGridCellSource is the canonical WGSL definition of the GridCell struct. Matches GPUGridCell layout exactly (32 bytes, std430 aligned).

View Source
var GPUGridParamsSource string

GPUGridParamsSource is the canonical WGSL definition of the GridParams struct. Matches GPUGridParams layout exactly (32 bytes, std430 aligned).

View Source
var GPUParticleSource string

GPUParticleSource is the canonical WGSL definition of the Particle struct. Matches GPUParticle layout exactly (96 bytes, std430 aligned).

View Source
var GPUPhysicsGlobalsSource string

GPUPhysicsGlobalsSource is the canonical WGSL definition of the PhysicsGlobals struct. Matches GPUPhysicsGlobals layout exactly (240 bytes, std140/WGSL uniform aligned).

Functions

func AssignBoneIndices

func AssignBoneIndices(particles []Particle, src model.Model)

AssignBoneIndices associates each voxel particle with its nearest bone from the source skinned model, transforming the particle's model-space position into bone-local space using the bone's inverse bind matrix. After this call every Particle in the slice has its BoneIndex set and its LocalPosition converted to bone-local coordinates, ready for GPU upload and per-frame bone-driven updates.

The algorithm is O(particles × vertices): for each particle, the nearest vertex is found by squared-distance, and the vertex's primary bone (highest weight among its four blend weights) is chosen. The particle's model-space position is then multiplied by the bone's inverse bind matrix so the GPU bone_particle_update shader can transform it back to world space using only the bone world matrix.

Parameters:

  • particles: the voxelized particle set (model-space positions)
  • src: the skinned Model whose vertex and skeleton data provide bone assignments

Types

type GPUBody

type GPUBody struct {
	Position        [4]float32  // offset   0: world-space center of mass (xyz), w unused       — §29.1.1 Eq. 3
	Quaternion      [4]float32  // offset  16: orientation quaternion (xyzw)                     — §29.1.2 Eq. 8
	LinearMomentum  [4]float32  // offset  32: linear momentum (xyz), w unused                  — §29.1.1 Eq. 1
	AngularMomentum [4]float32  // offset  48: angular momentum (xyz), w unused                 — §29.1.2 Eq. 4
	InvInertiaTBody [12]float32 // offset  64: body-space inverse inertia tensor (mat3x3<f32>)  — §29.1.2 Eq. 6
	InverseMass     float32     // offset 112: 1/mass (0 for static bodies)                    — §29.1.1 Eq. 2
	ParticleStart   uint32      // offset 116: start index into the global particle buffer      — §29.2.2
	ParticleCount   uint32      // offset 120: number of particles belonging to this body       — §29.2.2
	Flags           uint32      // offset 124: bit-packed: active (bit 0), static (1), kinematic (2)
	ExternalForce   [4]float32  // offset 128: CPU-uploaded force for this frame (xyz), w unused
	ExternalTorque  [4]float32  // offset 144: CPU-uploaded torque for this frame (xyz), w unused
}

GPUBody is the GPU-aligned representation of a single rigid body. One element per registered body in the physics storage buffer. Maps to the paper's "textures for linear and angular momenta, position, and the orientation quaternion" (GPU Gems 3, §29.2.2), packed into a single storage buffer instead of separate textures. Matches the WGSL Body struct layout exactly (see GPUBodySource). Size: 160 bytes (std430 / WGSL aligned).

func (*GPUBody) Marshal

func (g *GPUBody) Marshal() []byte

Marshal serializes the GPUBody struct into a byte buffer suitable for GPU upload. The mat3x3<f32> field is marshaled as 3 columns of vec3<f32>, each padded to 16 bytes (vec4 stride) per WGSL storage buffer layout rules.

Returns:

  • []byte: 160-byte buffer ready for GPU upload

func (*GPUBody) Size

func (g *GPUBody) Size() int

Size returns the size of the GPUBody struct in bytes.

Returns:

  • int: the struct size in bytes (160)

type GPUGridCell

type GPUGridCell struct {
	Indices0 [4]uint32 // offset  0: slots  0-3  particle indices (0xFFFFFFFF = empty) — §29.2.4
	Indices1 [4]uint32 // offset 16: slots  4-7  particle indices (0xFFFFFFFF = empty)
	Indices2 [4]uint32 // offset 32: slots  8-11 particle indices (0xFFFFFFFF = empty)
	Indices3 [4]uint32 // offset 48: slots 12-15 particle indices (0xFFFFFFFF = empty)
}

GPUGridCell is the GPU-aligned representation of a single cell in the uniform spatial grid used for collision broad-phase. Maps to the paper's "flat 3D texture" grid (GPU Gems 3, §29.2.2, §29.2.4) adapted for compute shader storage buffers. Each cell stores up to 16 particle indices; empty slots use the sentinel value 0xFFFFFFFF. Matches the WGSL GridCell struct layout exactly (see GPUGridCellSource). Size: 64 bytes (std430 / WGSL aligned).

func (*GPUGridCell) Marshal

func (g *GPUGridCell) Marshal() []byte

Marshal serializes the GPUGridCell struct into a byte buffer suitable for GPU upload.

Returns:

  • []byte: 64-byte buffer ready for GPU upload

func (*GPUGridCell) Size

func (g *GPUGridCell) Size() int

Size returns the size of the GPUGridCell struct in bytes.

Returns:

  • int: the struct size in bytes (64)

type GPUGridParams

type GPUGridParams struct {
	GridOrigin [4]float32 // offset  0: world-space grid origin (xyz), w unused  — §29.1.4 Eq. 9
	GridDims   [4]uint32  // offset 16: grid dimensions (x, y, z), w = total cell count — §29.2.2
}

GPUGridParams is the GPU-aligned representation of the spatial grid parameters. Written by the GPU AABB reduction shader (Stage 1.5) rather than uploaded from the CPU, which is why these fields live in a separate storage buffer instead of inside GPUPhysicsGlobals. Matches the WGSL GridParams struct layout exactly (see GPUGridParamsSource). Size: 32 bytes (std430 / WGSL aligned).

func (*GPUGridParams) Marshal

func (g *GPUGridParams) Marshal() []byte

Marshal serializes the GPUGridParams struct into a byte buffer suitable for GPU upload.

Returns:

  • []byte: 32-byte buffer ready for GPU upload

func (*GPUGridParams) Size

func (g *GPUGridParams) Size() int

Size returns the size of the GPUGridParams struct in bytes.

Returns:

  • int: the struct size in bytes (32)

type GPUParticle

type GPUParticle struct {
	WorldPosition [4]float32 // offset  0: current world-space position (xyz), w unused              — §29.2.3 Eq. 19
	Velocity      [4]float32 // offset 16: current velocity (xyz), w unused                          — §29.2.3 Eq. 20
	RelPosition   [4]float32 // offset 32: current relative position to body center (xyz), w unused  — §29.2.3 Eq. 18
	Force         [4]float32 // offset 48: accumulated collision force (xyz), w unused                — §29.2.5 Eqs. 10–12
	LocalPosition [4]float32 // offset 64: body-local rest position (xyz), w = bitcast<f32>(bodyIndex) — §29.2.3
	SurfaceNormal [4]float32 // offset 80: outward surface normal (xyz), w = 1.0 if valid (static)  — Fix A
}

GPUParticle is the GPU-aligned representation of a single particle across all rigid bodies. One element per particle in the global particle storage buffer. Maps to the paper's "textures for the particle's position, velocity, and relative position to the center of mass" (GPU Gems 3, §29.2.2). Matches the WGSL Particle struct layout exactly (see GPUParticleSource). Size: 96 bytes (std430 / WGSL aligned).

func (*GPUParticle) Marshal

func (g *GPUParticle) Marshal() []byte

Marshal serializes the GPUParticle struct into a byte buffer suitable for GPU upload. LocalPosition.w carries the owning body index as bitcast<f32>(u32); all other .w components are unused and marshaled as-is.

Returns:

  • []byte: 96-byte buffer ready for GPU upload

func (*GPUParticle) Size

func (g *GPUParticle) Size() int

Size returns the size of the GPUParticle struct in bytes.

Returns:

  • int: the struct size in bytes (96)

type GPUPhysicsGlobals

type GPUPhysicsGlobals struct {
	DeltaTime        float32       // offset  0: simulation timestep in seconds                         — Eqs. 1, 3, 4, 7–8
	ParticleDiameter float32       // offset  4: diameter of all particles (2 × radius)                 — §29.1.4
	SpringCoeff      float32       // offset  8: DEM spring coefficient k                               — §29.1.5 Eq. 10
	DampingCoeff     float32       // offset 12: DEM damping coefficient η                              — §29.1.5 Eq. 11
	ShearCoeff       float32       // offset 16: DEM tangential friction coefficient μ_t                — §29.1.5 Eq. 12
	BodyCount        uint32        // offset 20: number of active rigid bodies
	ParticleCount    uint32        // offset 24: total particle count across all bodies
	MaxGridCells     uint32        // offset 28: maximum total grid cells (x*y*z cap for AABB reduction)
	BoundaryCount    uint32        // offset 32: number of active boundary planes (0–6)
	GravityX         float32       // offset 36: gravitational acceleration X component (m/s²)
	GravityY         float32       // offset 40: gravitational acceleration Y component (m/s²)
	GravityZ         float32       // offset 44: gravitational acceleration Z component (m/s²)
	BoundaryPlanes   [6][4]float32 // offset  48: up to 6 half-plane definitions (normal.xyz, d)
	BoundaryYRanges  [6][4]float32 // offset 144: per-plane Y activation range (y_min, y_max, 0, 0)
}

GPUPhysicsGlobals is the GPU-aligned representation of the per-frame physics uniform buffer. A single instance is uploaded each frame, shared across all physics compute stages. Contains simulation constants (timestep, DEM coefficients), body/particle counts, and up to 6 analytical boundary half-planes with Y-height ranges. Grid-related fields (origin, dims) are stored separately in GPUGridParams so the GPU AABB reduction shader can write them directly without a CPU round-trip. Matches the WGSL PhysicsGlobals struct layout exactly (see GPUPhysicsGlobalsSource). Size: 240 bytes (std140 / WGSL uniform aligned).

func (*GPUPhysicsGlobals) Marshal

func (g *GPUPhysicsGlobals) Marshal() []byte

Marshal serializes the GPUPhysicsGlobals struct into a byte buffer suitable for GPU upload. Explicit padding bytes are written as zero to match WGSL alignment.

Returns:

  • []byte: 240-byte buffer ready for GPU upload

func (*GPUPhysicsGlobals) Size

func (g *GPUPhysicsGlobals) Size() int

Size returns the size of the GPUPhysicsGlobals struct in bytes.

Returns:

  • int: the struct size in bytes (240)

type Particle

type Particle struct {
	LocalPosition [3]float32
	SurfaceNormal [3]float32
	BodyIndex     uint32
	BoneIndex     uint32
}

Particle represents a single spherical collision element within a rigid body. Each particle stores a body-local position offset, an index identifying which body it belongs to (assigned during scene registration), and an optional bone index for kinematic skeletal bodies.

SurfaceNormal holds the outward-facing surface normal for particles created by VoxelizeMesh with surfaceOnly=true. It points from the solid interior toward empty space (i.e. toward the box interior for container inner faces). The collision shader uses this to prevent reversed spring forces when a particle penetrates past the wall surface.

func VoxelizeMesh

func VoxelizeMesh(src model.Model, particleRadius float32, surfaceOnly bool) []Particle

VoxelizeMesh converts a Model's mesh geometry into a set of spherical particles via ray-cast voxelization, following the method described in GPU Gems 3, Ch. 29 §1.3 (https://developer.nvidia.com/gpugems/gpugems3/part-v-physics-simulation/chapter-29-real-time-rigid-body-simulation-gpus).

The function extracts vertex positions and triangle indices directly from the Model's retained byte data. Vertex stride is determined by Model.Skinned() (96 bytes for GPUSkinnedVertex, 64 bytes for GPUVertex); position is always at byte offset 0.

The algorithm subdivides the mesh's AABB into a uniform 3D grid with cell size equal to the particle diameter (2 × particleRadius). For each (y, z) column of the grid a ray is cast along the +X axis and all triangle intersections are collected. The parity of crossings determines inside/outside status for each voxel in the column.

When surfaceOnly is true an additional filter pass removes interior particles, keeping only those adjacent to at least one empty (outside) neighbor. This dramatically reduces particle count for large solid bodies while preserving collision surface fidelity.

The column ray-casting phase is parallelized across available CPU cores using goroutines, as each (y, z) column writes to a disjoint region of the voxel grid.

Parameters:

  • src: the Model whose mesh data will be voxelized
  • particleRadius: the uniform radius of each generated particle
  • surfaceOnly: when true, only surface-adjacent particles are retained

Returns:

  • []Particle: the generated particle set in body-local space, or nil if the Model has insufficient vertex/index data

type Physics

type Physics interface {
	// Enabled returns whether the physics system is active. It becomes true when
	// at least one body is registered and false when all bodies are removed.
	//
	// Returns:
	//   - bool: true if physics simulation is active
	Enabled() bool

	// BodiesCount returns the number of body slots currently allocated (including
	// slots on the free list that have been deactivated but not yet reclaimed).
	//
	// Returns:
	//   - int: the total number of allocated body slots
	BodiesCount() int

	// ParticleCount returns the total number of particles across all registered bodies.
	//
	// Returns:
	//   - int: the total particle count
	ParticleCount() int

	// Buffers returns the primary BindGroupProvider that owns the physics storage
	// buffers (bodies at binding 0, particles at binding 1, etc.).
	//
	// Returns:
	//   - bind_group_provider.BindGroupProvider: the physics buffer provider
	Buffers() bind_group_provider.BindGroupProvider

	// Bgp returns the BindGroupProvider associated with the given compute stage key
	// (e.g. "collision", "integrate", "grid_insert").
	//
	// Parameters:
	//   - key: the stage identifier
	//
	// Returns:
	//   - bind_group_provider.BindGroupProvider: the provider for the requested stage, or nil if not found
	Bgp(key string) bind_group_provider.BindGroupProvider

	// Bgps returns the full map of compute-stage BindGroupProviders keyed by stage name.
	//
	// Returns:
	//   - map[string]bind_group_provider.BindGroupProvider: all compute-stage providers
	Bgps() map[string]bind_group_provider.BindGroupProvider

	// PipelineKey returns the compute pipeline cache key for the given stage name.
	//
	// Parameters:
	//   - key: the stage identifier
	//
	// Returns:
	//   - string: the pipeline cache key associated with the stage
	PipelineKey(key string) string

	// MaxBodies returns the upper limit of rigid bodies the system can hold.
	//
	// Returns:
	//   - uint32: the maximum body count
	MaxBodies() uint32

	// MaxParticles returns the upper limit of particles across all bodies.
	//
	// Returns:
	//   - uint32: the maximum particle count
	MaxParticles() uint32

	// MaxGridCells returns the upper limit of spatial grid cells (x*y*z cap).
	//
	// Returns:
	//   - uint32: the maximum grid cell count
	MaxGridCells() uint32

	// SetPipelineKey associates a compute pipeline cache key with the given stage name.
	//
	// Parameters:
	//   - name: the stage identifier
	//   - key: the pipeline cache key to store
	SetPipelineKey(name, key string)

	// RegisterBody registers a rigid body in the physics system, uploading its GPU
	// data (body struct, particles, sync mapping) via staged buffer writes. If a
	// previously freed slot exists it is reused; otherwise a new slot is allocated.
	//
	// Parameters:
	//   - objID: the unique game-object identifier used for lookup
	//   - position: world-space spawn position (XYZ)
	//   - rotation: Euler rotation angles in radians (XYZ)
	//   - rb: the RigidBody carrying mass, particles, and physics properties
	//   - instanceID: the Animator instance ID written to the sync map
	//
	// Returns:
	//   - int: the body slot index assigned to this registration
	RegisterBody(objID uint64, position, rotation [3]float32, rb RigidBody, instanceID uint32) int

	// RemoveBody deactivates a body by zeroing its GPU flags and inverse mass,
	// and returns the body slot to the free list for reuse by future registrations.
	//
	// Parameters:
	//   - objID: the unique game-object identifier to remove
	RemoveBody(objID uint64)

	// BodyIndex returns the GPU body buffer slot index for the given object ID.
	//
	// Parameters:
	//   - objID: the unique object identifier
	//
	// Returns:
	//   - int: the zero-based body slot index
	//   - bool: true if the object was found
	BodyIndex(objID uint64) (int, bool)

	// BodyParticleInfo returns the particle start index and count for a given body slot.
	//
	// Parameters:
	//   - bodyIndex: the body slot index returned by RegisterBody
	//
	// Returns:
	//   - start: the first particle index in the global particle buffer
	//   - count: the number of particles belonging to this body
	BodyParticleInfo(bodyIndex int) (start, count uint32)

	// StagedWriteData drains and returns all pending GPU buffer writes that have been
	// queued since the last call. The internal queue is reset after draining.
	//
	// Returns:
	//   - []bind_group_provider.BufferWrite: the accumulated buffer writes
	StagedWriteData() []bind_group_provider.BufferWrite

	// PrepareStep advances the physics accumulator by dt and determines how many
	// fixed-timestep substeps to execute this frame. It also drains pending
	// per-body forces/torques into staged buffer writes and builds the
	// GPUPhysicsGlobals uniform data.
	//
	// Parameters:
	//   - dt: wall-clock frame delta time in seconds
	//
	// Returns:
	//   - substeps: the number of fixed-timestep substeps to dispatch (0 if none)
	//   - globalsData: serialized GPUPhysicsGlobals bytes for GPU upload, or nil if substeps is 0
	PrepareStep(dt float32) (substeps int, globalsData []byte)

	// RequestReadback flags that a GPU-to-CPU readback of the body buffer should
	// be initiated on the next command submission.
	RequestReadback()

	// ConsumeReadbackRequest checks whether a readback was requested, clears the
	// request flag, and sets readbackPending so the scene knows a copy is in-flight.
	//
	// Returns:
	//   - bool: true if a readback was requested and consumed
	ConsumeReadbackRequest() bool

	// ReadbackPending returns whether a GPU readback copy is currently in-flight.
	//
	// Returns:
	//   - bool: true if a readback is pending
	ReadbackPending() bool

	// ClearReadbackPending resets the pending readback flag after the mapping
	// callback has completed.
	ClearReadbackPending()

	// StagingBuffer returns the GPU staging buffer used for readback mapping.
	//
	// Returns:
	//   - *wgpu.Buffer: the staging buffer, or nil if not yet created
	StagingBuffer() *wgpu.Buffer

	// SetStagingBuffer sets the GPU staging buffer used for readback mapping.
	//
	// Parameters:
	//   - buf: the staging buffer to store
	SetStagingBuffer(buf *wgpu.Buffer)

	// ProcessReadback unmarshals body positions and quaternions from the raw GPU
	// body buffer readback data and updates the corresponding CPU-side RigidBody
	// state. Each GPUBody is 160 bytes; only the Position (offset 0, 16 bytes)
	// and Quaternion (offset 16, 16 bytes) are extracted.
	//
	// Parameters:
	//   - data: the raw byte slice containing bodiesCount × 160 bytes of GPUBody data
	ProcessReadback(data []byte)
}

Physics defines the interface for the GPU-accelerated rigid body physics system. It manages body/particle registration, per-frame simulation stepping, GPU buffer staging, and asynchronous readback of simulation results. All physics compute pipeline dispatches and buffer bindings are driven through this interface.

func NewPhysics

func NewPhysics(options ...PhysicsBuilderOption) Physics

NewPhysics creates a new Physics instance with sensible defaults. The returned system starts disabled and becomes active upon the first RegisterBody call. Use PhysicsBuilderOption values to override default configuration.

Parameters:

  • options: variadic list of PhysicsBuilderOption functions to configure the physics system

Returns:

  • Physics: a new Physics instance

type PhysicsBuilderOption

type PhysicsBuilderOption func(*physicsImpl)

PhysicsBuilderOption is a functional option for configuring a physicsImpl during construction.

func WithBoundaryPlanes

func WithBoundaryPlanes(planes [][6]float32) PhysicsBuilderOption

WithBoundaryPlanes sets the analytical containment half-planes used for wall collision in the collision shader. Each plane is defined as [nx, ny, nz, d, y_min, y_max] where the normal points INTO the containment volume, dot(n, p) + d >= 0 indicates p is inside, and the plane is only active when the particle’s Y coordinate is within [y_min, y_max]. Up to 6 planes are supported.

Parameters:

  • planes: slice of [6]float32 plane definitions (max 6)

Returns:

  • PhysicsBuilderOption: a function that applies the boundary plane option to a physicsImpl

func WithDampingCoeff

func WithDampingCoeff(dampingCoeff float32) PhysicsBuilderOption

WithDampingCoeff sets the DEM damping coefficient used in particle collision response. Higher values dissipate more kinetic energy on contact.

Parameters:

  • dampingCoeff: DEM damping coefficient η

Returns:

  • PhysicsBuilderOption: a function that applies the damping coefficient option to a physicsImpl

func WithFixedDt

func WithFixedDt(fixedDt float32) PhysicsBuilderOption

WithFixedDt sets the fixed timestep used for each physics substep.

Parameters:

  • fixedDt: simulation timestep in seconds (e.g. 1/60 for 60 Hz)

Returns:

  • PhysicsBuilderOption: a function that applies the fixed timestep option to a physicsImpl

func WithGravity

func WithGravity(gravity [3]float32) PhysicsBuilderOption

WithGravity sets the gravitational acceleration vector applied to all dynamic bodies every substep. This is a field force built into the physics globals, not an external per-body force — it persists correctly across multiple substeps.

Parameters:

  • gravity: gravitational acceleration in m/s² (e.g. [3]float32{0, -9.81, 0})

Returns:

  • PhysicsBuilderOption: a function that applies the gravity option to a physicsImpl

func WithMaxBodies

func WithMaxBodies(maxBodies uint32) PhysicsBuilderOption

WithMaxBodies sets the maximum number of rigid bodies the physics system can hold. This determines the size of the GPU body storage buffer.

Parameters:

  • maxBodies: maximum body count

Returns:

  • PhysicsBuilderOption: a function that applies the max bodies option to a physicsImpl

func WithMaxGridCells

func WithMaxGridCells(maxGridCells uint32) PhysicsBuilderOption

WithMaxGridCells sets the maximum total number of spatial grid cells used for collision broad-phase. This caps the dimensions of the uniform grid (x*y*z).

Parameters:

  • maxGridCells: maximum grid cell count

Returns:

  • PhysicsBuilderOption: a function that applies the max grid cells option to a physicsImpl

func WithMaxParticles

func WithMaxParticles(maxParticles uint32) PhysicsBuilderOption

WithMaxParticles sets the maximum number of collision particles across all rigid bodies. This determines the size of the GPU particle storage buffer.

Parameters:

  • maxParticles: maximum particle count

Returns:

  • PhysicsBuilderOption: a function that applies the max particles option to a physicsImpl

func WithMaxSubsteps

func WithMaxSubsteps(maxSubsteps int) PhysicsBuilderOption

WithMaxSubsteps sets the maximum number of fixed-timestep substeps allowed per frame. Capping substeps prevents spiral-of-death when frame time significantly exceeds the fixed timestep.

Parameters:

  • maxSubsteps: maximum substep count per frame

Returns:

  • PhysicsBuilderOption: a function that applies the max substeps option to a physicsImpl

func WithShearCoeff

func WithShearCoeff(shearCoeff float32) PhysicsBuilderOption

WithShearCoeff sets the DEM tangential friction coefficient used in particle collision response. This controls the tangential (shear) force applied during contact.

Parameters:

  • shearCoeff: DEM tangential friction coefficient μ_t

Returns:

  • PhysicsBuilderOption: a function that applies the shear coefficient option to a physicsImpl

func WithSpringCoeff

func WithSpringCoeff(springCoeff float32) PhysicsBuilderOption

WithSpringCoeff sets the DEM spring coefficient used in particle collision response. Higher values produce stiffer collisions.

Parameters:

  • springCoeff: DEM spring coefficient k

Returns:

  • PhysicsBuilderOption: a function that applies the spring coefficient option to a physicsImpl

type RigidBody

type RigidBody interface {
	common.Delegate[RigidBody]

	// Position returns the world-space position of the rigid body.
	// This value is updated from GPU readback after each physics frame.
	//
	// Returns:
	//   - [3]float32: A 3D vector representing the world-space position.
	Position() [3]float32

	// Quaternion returns the orientation quaternion (xyzw) of the rigid body.
	// This value is updated from GPU readback after each physics frame.
	//
	// Returns:
	//   - [4]float32: The orientation quaternion in xyzw order.
	Quaternion() [4]float32

	// Velocity returns the linear velocity of the rigid body as a 3D vector.
	//
	// Returns:
	//   - [3]float32: A 3D vector representing the linear velocity of the rigid body.
	Velocity() [3]float32

	// AngularVelocity returns the angular velocity of the rigid body as a 3D vector.
	//
	// Returns:
	//   - [3]float32: A 3D vector representing the angular velocity of the rigid body.
	AngularVelocity() [3]float32

	// Mass returns the mass of the rigid body.
	//
	// Returns:
	//   - float32: The mass of the rigid body.
	Mass() float32

	// InverseMass returns the inverse of the mass of the rigid body.
	//
	// Returns:
	//   - float32: The inverse of the mass of the rigid body.
	InverseMass() float32

	// Bounce returns the bounce factor of the rigid body, which determines how much it bounces when colliding with other objects.
	//
	// Returns:
	//   - float32: The bounce factor of the rigid body.
	Bounce() float32

	// Friction returns the friction factor of the rigid body, which determines how much it resists sliding against other objects.
	//
	// Returns:
	//   - float32: The friction factor of the rigid body.
	Friction() float32

	// InverseInertiaTensorBody returns the inverse of the inertia tensor of the rigid body in body-local space.
	//
	// Returns:
	//   - [9]float32: A 3x3 matrix (flattened to a 1D array) representing the inverse inertia tensor of the rigid body in body-local space.
	InverseInertiaTensorBody() [9]float32

	// Active returns whether the rigid body is active in the simulation.
	//
	// Returns:
	//   - bool: True if the rigid body is active, false otherwise.
	Active() bool

	// Static returns whether the rigid body is static (immovable) in the simulation.
	//
	// Returns:
	//   - bool: True if the rigid body is static, false otherwise.
	Static() bool

	// Kinematic returns whether the rigid body is kinematic (moves according to animation or script) in the simulation.
	//
	// Returns:
	//   - bool: True if the rigid body is kinematic, false otherwise.
	Kinematic() bool

	// Particles returns the set of spherical collision elements that compose the rigid body.
	//
	// Returns:
	//   - []Particle: A slice of Particle structs representing the collision elements of the rigid body.
	Particles() []Particle

	// ParticleRadius returns the radius of each spherical particle generated for the Rigid Body.
	//
	// Returns:
	//   - float32: The radius of each spherical particle generated for the Rigid Body.
	ParticleRadius() float32

	// SurfaceOnly returns whether only surface particles are generated during voxelization.
	//
	// Returns:
	//   - bool: True if only surface particles are generated during voxelization, false otherwise.
	SurfaceOnly() bool

	// SetVelocity sets the linear velocity of the rigid body.
	//
	// Parameters:
	//   - velocity: A 3D vector (XYZ) representing the linear velocity to set for the rigid body.
	SetVelocity(velocity [3]float32)

	// SetAngularVelocity sets the angular velocity of the rigid body.
	//
	// Parameters:
	//   - angularVelocity: A 3D vector (XYZ) representing the angular velocity to set for the rigid body.
	SetAngularVelocity(angularVelocity [3]float32)

	// SetMass sets the mass of the rigid body.
	//
	// Parameters:
	//   - mass: The mass to set for the rigid body.
	SetMass(mass float32)

	// SetInverseMass sets the inverse of the mass of the rigid body.
	//
	// Parameters:
	//   - inverseMass: The inverse of the mass to set for the rigid body.
	SetInverseMass(inverseMass float32)

	// SetBounce sets the bounce factor of the rigid body.
	//
	// Parameters:
	//   - bounce: The bounce factor to set for the rigid body.
	SetBounce(bounce float32)

	// SetFriction sets the friction factor of the rigid body.
	//
	// Parameters:
	//   - friction: The friction factor to set for the rigid body.
	SetFriction(friction float32)

	// SetActive sets whether the rigid body is active in the simulation.
	//
	// Parameters:
	//   - active: True to set the rigid body as active, false to set it as inactive.
	SetActive(active bool)

	// SetStatic sets whether the rigid body is static (immovable) in the simulation.
	//
	// Parameters:
	//   - static: True to set the rigid body as static, false to set it as non-static.
	SetStatic(static bool)

	// SetKinematic sets whether the rigid body is kinematic (moves according to animation or script) in the simulation.
	//
	// Parameters:
	//   - kinematic: True to set the rigid body as kinematic, false to set it as non-kinematic.
	SetKinematic(kinematic bool)

	// SetParticles sets the collision particles of the rigid body.
	//
	// Parameters:
	//   - particles: A slice of Particle structs representing the collision elements to set for the rigid body.
	SetParticles(particles []Particle)

	// SetParticleRadius sets the radius of each spherical particle generated for the Rigid Body.
	//
	// Parameters:
	//   - radius: The radius to set for each spherical particle generated for the Rigid Body.
	SetParticleRadius(radius float32)

	// SetSurfaceOnly sets whether only surface particles are generated during voxelization.
	//
	// Parameters:
	//   - surfaceOnly: True to set only surface particles to be generated during voxelization, false to allow internal particles as well.
	SetSurfaceOnly(surfaceOnly bool)

	// SetPosition sets the world-space position of the rigid body.
	// This is primarily called during GPU readback processing.
	//
	// Parameters:
	//   - position: A 3D vector (XYZ) representing the world-space position to set.
	SetPosition(position [3]float32)

	// SetQuaternion sets the orientation quaternion of the rigid body.
	// This is primarily called during GPU readback processing.
	//
	// Parameters:
	//   - quaternion: A quaternion (XYZW) representing the orientation to set.
	SetQuaternion(quaternion [4]float32)

	// ApplyForce adds a force vector to the pending force accumulator.
	// This is safe to call from any goroutine (e.g. the tick callback).
	// The accumulated force is drained by the physics controller each frame
	// and uploaded as GPUBody.ExternalForce.
	//
	// Parameters:
	//   - force: the force vector (XYZ) to accumulate.
	ApplyForce(force [3]float32)

	// ApplyTorque adds a torque vector to the pending torque accumulator.
	// This is safe to call from any goroutine (e.g. the tick callback).
	// The accumulated torque is drained by the physics controller each frame
	// and uploaded as GPUBody.ExternalTorque.
	//
	// Parameters:
	//   - torque: the torque vector (XYZ) to accumulate.
	ApplyTorque(torque [3]float32)
}

RigidBody is the interface that defines the behavior of a rigid body in a physics simulation.

func NewRigidBody

func NewRigidBody(options ...RigidBodyOption) RigidBody

NewRigidBody creates a new RigidBody with default physical properties. Defaults are: mass=1, bounce=0.5, friction=0.5, surfaceOnly=true. If mass is zero and the body is not kinematic it is automatically marked static. The inverse inertia tensor is computed from the particle layout when particles are provided.

Parameters:

  • options: variadic list of RigidBodyOption functions to configure the rigid body

Returns:

  • RigidBody: a new RigidBody instance

type RigidBodyOption

type RigidBodyOption func(*rigidBody)

RigidBodyOption is a functional option for configuring a rigidBody during construction.

func WithActive

func WithActive(active bool) RigidBodyOption

WithActive sets whether the rigid body is active in the simulation.

Parameters:

  • active: True if the rigid body is active, false otherwise.

Returns:

  • RigidBodyOption: A function that can be used to set the active state of a rigid body.

func WithAngularVelocity

func WithAngularVelocity(angularVelocity [3]float32) RigidBodyOption

WithAngularVelocity sets the angular velocity of the rigid body.

Parameters:

  • angularVelocity: A 3D vector representing the angular velocity of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the angular velocity of a rigid body.

func WithBounce

func WithBounce(bounce float32) RigidBodyOption

WithBounce sets the bounce factor of the rigid body.

Parameters:

  • bounce: The bounce factor of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the bounce factor of a rigid body.

func WithFriction

func WithFriction(friction float32) RigidBodyOption

WithFriction sets the friction factor of the rigid body.

Parameters:

  • friction: The friction factor of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the friction factor of a rigid body.

func WithInverseMass

func WithInverseMass(inverseMass float32) RigidBodyOption

WithInverseMass sets the inverse of the mass of the rigid body.

Parameters:

  • inverseMass: The inverse of the mass of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the inverse mass of a rigid body.

func WithKinematic

func WithKinematic(kinematic bool) RigidBodyOption

WithKinematic sets whether the rigid body is kinematic (moves according to animation or script) in the simulation.

Parameters:

  • kinematic: True if the rigid body is kinematic, false otherwise.

Returns:

  • RigidBodyOption: A function that can be used to set the kinematic state of a rigid body.

func WithMass

func WithMass(mass float32) RigidBodyOption

WithMass sets the mass of the rigid body.

Parameters:

  • mass: The mass of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the mass of a rigid body.

func WithParticleRadius

func WithParticleRadius(radius float32) RigidBodyOption

WithParticleRadius sets the radius of each spherical collision particle for the rigid body. This value is used by the physics controller to derive the global particle diameter.

Parameters:

  • radius: The radius of each particle.

Returns:

  • RigidBodyOption: A function that applies the particle radius option to a rigidBody.

func WithParticles

func WithParticles(particles []Particle) RigidBodyOption

WithParticles sets the collision particles of the rigid body.

Parameters:

  • particles: A slice of Particle structs representing the collision elements of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the collision particles of a rigid body.

func WithStatic

func WithStatic(static bool) RigidBodyOption

WithStatic sets whether the rigid body is static (immovable) in the simulation.

Parameters:

  • static: True if the rigid body is static, false otherwise.

Returns:

  • RigidBodyOption: A function that can be used to set the static state of a rigid body.

func WithVelocity

func WithVelocity(velocity [3]float32) RigidBodyOption

WithVelocity sets the linear velocity of the rigid body.

Parameters:

  • velocity: A 3D vector representing the linear velocity of the rigid body.

Returns:

  • RigidBodyOption: A function that can be used to set the velocity of a rigid body.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL