physics

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: May 5, 2024 License: BSD-3-Clause Imports: 6 Imported by: 0

README

XYZ Physics Engine

This physics engine is a scenegraph-based 3D physics simulator for creating virtual environments. It provides a Body node for rigid body physics, along with some basic geometrical shapes thereof. The physics scene contains just the bare physics bodies and other elements, which can be updated independent of any visualization.

Currently, it provides collision detection and basic forward Euler physics updating, but it does not yet compute any forces for the interactions among the bodies. Ultimately we hope to figure out how the Bullet system works and get that running here, in a clean and simple implementation.

Incrementally, we will start with a basic explicitly driven form of physics that is sufficient to get started, and build from there.

The world visualization sub-package generates an xyz 3D scenegraph based on the physics bodies, and updates this visualization efficiently as the physics is updated. world2d provides a 2D projection of the 3D physics world, using corresponding SVG nodes. This can provide simpler representations for map-like layouts etc.

See physics example for an implemented example that shows how to do everything.

Organizing the World

It is most efficient to create a relatively deep tree with Group nodes that collect nearby Body objects at multiple levels of spatial scale. Bounding Boxes are computed at every level of Group, and pruning is done at every level, so large chunks of the tree can be eliminated easily with this strategy.

Also, Nodes must be specifically flagged as being Dynamic -- otherwise they are assumed to be static -- and each type should be organized into separate top-level Groups (there can be multiple of each, but don't mix Dynamic and Static). Static nodes are never collided against each-other. Ideally, all the Dynamic nodes are in separate top-level, or at least second-to-top level groups -- this eliminates redundant A vs. B and B vs. A collisions and focuses each collision on the most relevant information.

Updating Modes

There are two major modes of updating: Scripted or Physics -- scripted requires a program to control what happens on every time step, while physics uses computed forces from contacts, plus joint constraints, to update velocities (not yet supported). The update modes are just about which methods you call.

The Group has a set of World* methods that should be used on the top-level world Group node node to do all the init and update steps. The update loops automatically exclude non Dynamic nodes.

  • WorldInit -- everyone calls this at the start to set the initial config

  • WorldRelToAbs -- for scripted mode when updating relative positions, rotations.

  • WorldStep -- for either scripted or physics modes, to update state from current velocities.

  • WorldCollide -- returns list of potential collision contacts based on projected motion, focusing on dynamic vs. static and dynamic vs. dynamic bodies, with optimized tree filtering. This is the first pass for collision detection.

Scripted Mode

For Scripted mode, each update step typically involves manually updating the Rel.Pos and .Quat fields on Body objects to update their relative positions. This field is a State type and has MoveOnAxis and RotateOnAxis (and a number of other rotation methods). The Move methods update the LinVel field to reflect any delta in movement.

It is also possible to manually set the Abs.LinVel and Abs.AngVel fields and call Step to update.

For collision detection, it is essential to have the Abs.LinVel field set to anticipate the effects of motion and determine likely future impacts. The RelToAbs update call does this automatically, and if you're instead using Step the LinVel is already set. Both calls will automatically compute an updated BBox and VelBBox.

It is up to the user to manage the list of potential collisions, e.g., by setting velocity to 0 or bouncing back etc.

Physics Mode

The good news so far is that the full physics version as in Bullet is actually not too bad. The core update step is a super simple forward Euler, intuitive update (just add velocity to position, with a step size factor). The remaining work is just in computing the forces to update those velocities. Bullet uses a hybrid approach that is clearly described in the Mirtich thesis, which combines impulses with a particular way of handling joints, due originally to Featherstone. Impulses are really simple conceptually: when two objects collide, they bounce back off of each other in proportion to their Bounce (coefficient of restitution) factor -- these collision impact forces dominate everything else, and aren't that hard to compute (similar conceptually to the marbles example in GoGi). The joint constraint stuff is a bit more complicated but not the worst. Everything can be done incrementally. And the resulting system will avoid the brittle nature of the full constraint-based approach taken in ODE, which caused a lot of crashes and instability in cemer.

One of the major problems with the impulse-based approach: it causes otherwise "still" objects to jiggle around and slip down planes, seems eminently tractable with special-case code that doesn't seem too hard.

more info: https://caseymuratori.com/blog_0003

Documentation

Index

Constants

View Source
const (
	// DynsTopGps is passed to WorldCollide when all dynamic objects are in separate top groups
	DynsTopGps = true

	// DynsSubGps is passed to WorldCollide when all dynamic objects are in separate groups under top
	// level (i.e., one level deeper)
	DynsSubGps
)
View Source
const AngMotionMax = math.Pi / 4

AngMotionMax is maximum angular motion that can be taken per update

Variables

View Source
var BodyBaseType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.BodyBase", IDName: "body-base", Doc: "BodyBase is the base type for all specific Body types", Embeds: []types.Field{{Name: "NodeBase"}}, Fields: []types.Field{{Name: "Rigid", Doc: "rigid body properties, including mass, bounce, friction etc"}, {Name: "Vis", Doc: "visualization name -- looks up an entry in the scene library that provides the visual representation of this body"}, {Name: "Color", Doc: "default color of body for basic InitLibrary configuration"}}, Instance: &BodyBase{}})

BodyBaseType is the types.Type for BodyBase

View Source
var BoxType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.Box", IDName: "box", Doc: "Box is a box body shape", Embeds: []types.Field{{Name: "BodyBase"}}, Fields: []types.Field{{Name: "Size", Doc: "size of box in each dimension (units arbitrary, as long as they are all consistent -- meters is typical)"}}, Instance: &Box{}})

BoxType is the types.Type for Box

View Source
var CapsuleType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.Capsule", IDName: "capsule", Doc: "Capsule is a generalized cylinder body shape, with hemispheres at each end,\nwith separate radii for top and bottom.", Embeds: []types.Field{{Name: "BodyBase"}}, Fields: []types.Field{{Name: "Height", Doc: "height of the cylinder portion of the capsule"}, {Name: "TopRad", Doc: "radius of the top hemisphere"}, {Name: "BotRad", Doc: "radius of the bottom hemisphere"}}, Instance: &Capsule{}})

CapsuleType is the types.Type for Capsule

View Source
var CylinderType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.Cylinder", IDName: "cylinder", Doc: "Cylinder is a generalized cylinder body shape, with separate radii for top and bottom.\nA cone has a zero radius at one end.", Embeds: []types.Field{{Name: "BodyBase"}}, Fields: []types.Field{{Name: "Height", Doc: "height of the cylinder"}, {Name: "TopRad", Doc: "radius of the top -- set to 0 for a cone"}, {Name: "BotRad", Doc: "radius of the bottom"}}, Instance: &Cylinder{}})

CylinderType is the types.Type for Cylinder

View Source
var GroupType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.Group", IDName: "group", Doc: "Group is a container of bodies, joints, or other groups\nit should be used strategically to partition the space\nand its BBox is used to optimize tree-based collision detection.\nUse a group for the top-level World node as well.", Embeds: []types.Field{{Name: "NodeBase"}}, Instance: &Group{}})

GroupType is the types.Type for Group

View Source
var NodeBaseType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.NodeBase", IDName: "node-base", Doc: "NodeBase is the basic node, which has position, rotation, velocity\nand computed bounding boxes, etc.\nThere are only three different kinds of Nodes: Group, Body, and Joint", Embeds: []types.Field{{Name: "NodeBase"}}, Fields: []types.Field{{Name: "Initial", Doc: "initial position, orientation, velocity in *local* coordinates (relative to parent)"}, {Name: "Rel", Doc: "current relative (local) position, orientation, velocity -- only change these values, as abs values are computed therefrom"}, {Name: "Abs", Doc: "current absolute (world) position, orientation, velocity"}, {Name: "BBox", Doc: "bounding box in world coordinates (aggregated for groups)"}}, Instance: &NodeBase{}})

NodeBaseType is the types.Type for NodeBase

View Source
var SphereType = types.AddType(&types.Type{Name: "cogentcore.org/core/xyz/physics.Sphere", IDName: "sphere", Doc: "Sphere is a spherical body shape.", Embeds: []types.Field{{Name: "BodyBase"}}, Fields: []types.Field{{Name: "Radius", Doc: "radius"}}, Instance: &Sphere{}})

SphereType is the types.Type for Sphere

Functions

func AsNode

func AsNode(k tree.Node) (Node, *NodeBase)

AsNode converts Ki to a Node interface and a Node3DBase obj -- nil if not.

Types

type BBox

type BBox struct {

	// bounding box in world coords (Axis-Aligned Bounding Box = AABB)
	BBox math32.Box3

	// velocity-projected bounding box in world coords: extend BBox to include future position of moving bodies -- collision must be made on this basis
	VelBBox math32.Box3

	// bounding sphere in local coords
	BSphere math32.Sphere

	// area
	Area float32

	// volume
	Volume float32
}

BBox contains bounding box and other gross object properties

func (*BBox) IntersectsVelBox

func (bb *BBox) IntersectsVelBox(oth *BBox) bool

IntersectsVelBox returns true if two velocity-projected bounding boxes intersect

func (*BBox) SetBounds

func (bb *BBox) SetBounds(min, max math32.Vector3)

SetBounds sets BBox from min, max and updates other factors based on that

func (*BBox) UpdateFromBBox

func (bb *BBox) UpdateFromBBox()

UpdateFromBBox updates other values from BBox

func (*BBox) VelNilProject

func (bb *BBox) VelNilProject()

VelNilProject is for static items -- just copy the BBox

func (*BBox) VelProject

func (bb *BBox) VelProject(vel math32.Vector3, step float32)

VelProject computes the velocity-projected bounding box for given velocity and step size

func (*BBox) XForm

func (bb *BBox) XForm(q math32.Quat, pos math32.Vector3)

XForm transforms bounds with given quat and position offset to convert to world coords

type Body

type Body interface {
	Node

	// AsBodyBase returns the body as a BodyBase
	AsBodyBase() *BodyBase

	// SetDynamic sets the Dynamic flag for this body, indicating that it moves.
	// It is important to collect all dynamic objects into separate top-level group(s)
	// for more efficiently organizing the collision detection process.
	SetDynamic() *BodyBase
}

Body is the common interface for all body types

type BodyBase

type BodyBase struct {
	NodeBase

	// rigid body properties, including mass, bounce, friction etc
	Rigid Rigid

	// visualization name -- looks up an entry in the scene library that provides the visual representation of this body
	Vis string

	// default color of body for basic InitLibrary configuration
	Color string
}

BodyBase is the base type for all specific Body types

func NewBodyBase

func NewBodyBase(parent tree.Node, name ...string) *BodyBase

NewBodyBase adds a new BodyBase with the given name to the given parent: BodyBase is the base type for all specific Body types

func (*BodyBase) AsBody

func (bb *BodyBase) AsBody() Body

func (*BodyBase) AsBodyBase

func (bb *BodyBase) AsBodyBase() *BodyBase

func (*BodyBase) GroupBBox

func (bb *BodyBase) GroupBBox()

func (*BodyBase) New

func (t *BodyBase) New() tree.Node

New returns a new *BodyBase value

func (*BodyBase) NodeType

func (t *BodyBase) NodeType() *types.Type

NodeType returns the *types.Type of BodyBase

func (*BodyBase) SetColor

func (t *BodyBase) SetColor(v string) *BodyBase

SetColor sets the [BodyBase.Color]: default color of body for basic InitLibrary configuration

func (*BodyBase) SetDynamic

func (bb *BodyBase) SetDynamic() *BodyBase

func (*BodyBase) SetInitial

func (t *BodyBase) SetInitial(v State) *BodyBase

SetInitial sets the [BodyBase.Initial]

func (*BodyBase) SetRel

func (t *BodyBase) SetRel(v State) *BodyBase

SetRel sets the [BodyBase.Rel]

func (*BodyBase) SetRigid

func (t *BodyBase) SetRigid(v Rigid) *BodyBase

SetRigid sets the [BodyBase.Rigid]: rigid body properties, including mass, bounce, friction etc

func (*BodyBase) SetVis

func (t *BodyBase) SetVis(v string) *BodyBase

SetVis sets the [BodyBase.Vis]: visualization name -- looks up an entry in the scene library that provides the visual representation of this body

type BodyPoint

type BodyPoint struct {
	Body  Body
	Point math32.Vector3
}

BodyPoint contains a Body and a Point on that body

type Box

type Box struct {
	BodyBase

	// size of box in each dimension (units arbitrary, as long as they are all consistent -- meters is typical)
	Size math32.Vector3
}

Box is a box body shape

func NewBox

func NewBox(parent tree.Node, name ...string) *Box

NewBox adds a new Box with the given name to the given parent: Box is a box body shape

func (*Box) InitAbs

func (bx *Box) InitAbs(par *NodeBase)

func (*Box) New

func (t *Box) New() tree.Node

New returns a new *Box value

func (*Box) NodeType

func (t *Box) NodeType() *types.Type

NodeType returns the *types.Type of Box

func (*Box) RelToAbs

func (bx *Box) RelToAbs(par *NodeBase)

func (*Box) SetBBox

func (bx *Box) SetBBox()

func (*Box) SetColor

func (t *Box) SetColor(v string) *Box

SetColor sets the [Box.Color]

func (*Box) SetInitial

func (t *Box) SetInitial(v State) *Box

SetInitial sets the [Box.Initial]

func (*Box) SetRel

func (t *Box) SetRel(v State) *Box

SetRel sets the [Box.Rel]

func (*Box) SetRigid

func (t *Box) SetRigid(v Rigid) *Box

SetRigid sets the [Box.Rigid]

func (*Box) SetSize

func (t *Box) SetSize(v math32.Vector3) *Box

SetSize sets the [Box.Size]: size of box in each dimension (units arbitrary, as long as they are all consistent -- meters is typical)

func (*Box) SetVis

func (t *Box) SetVis(v string) *Box

SetVis sets the [Box.Vis]

func (*Box) Step

func (bx *Box) Step(step float32)

type Capsule

type Capsule struct {
	BodyBase

	// height of the cylinder portion of the capsule
	Height float32

	// radius of the top hemisphere
	TopRad float32

	// radius of the bottom hemisphere
	BotRad float32
}

Capsule is a generalized cylinder body shape, with hemispheres at each end, with separate radii for top and bottom.

func NewCapsule

func NewCapsule(parent tree.Node, name ...string) *Capsule

NewCapsule adds a new Capsule with the given name to the given parent: Capsule is a generalized cylinder body shape, with hemispheres at each end, with separate radii for top and bottom.

func (*Capsule) InitAbs

func (cp *Capsule) InitAbs(par *NodeBase)

func (*Capsule) New

func (t *Capsule) New() tree.Node

New returns a new *Capsule value

func (*Capsule) NodeType

func (t *Capsule) NodeType() *types.Type

NodeType returns the *types.Type of Capsule

func (*Capsule) RelToAbs

func (cp *Capsule) RelToAbs(par *NodeBase)

func (*Capsule) SetBBox

func (cp *Capsule) SetBBox()

func (*Capsule) SetBotRad

func (t *Capsule) SetBotRad(v float32) *Capsule

SetBotRad sets the [Capsule.BotRad]: radius of the bottom hemisphere

func (*Capsule) SetColor

func (t *Capsule) SetColor(v string) *Capsule

SetColor sets the [Capsule.Color]

func (*Capsule) SetHeight

func (t *Capsule) SetHeight(v float32) *Capsule

SetHeight sets the [Capsule.Height]: height of the cylinder portion of the capsule

func (*Capsule) SetInitial

func (t *Capsule) SetInitial(v State) *Capsule

SetInitial sets the [Capsule.Initial]

func (*Capsule) SetRel

func (t *Capsule) SetRel(v State) *Capsule

SetRel sets the [Capsule.Rel]

func (*Capsule) SetRigid

func (t *Capsule) SetRigid(v Rigid) *Capsule

SetRigid sets the [Capsule.Rigid]

func (*Capsule) SetTopRad

func (t *Capsule) SetTopRad(v float32) *Capsule

SetTopRad sets the [Capsule.TopRad]: radius of the top hemisphere

func (*Capsule) SetVis

func (t *Capsule) SetVis(v string) *Capsule

SetVis sets the [Capsule.Vis]

func (*Capsule) Step

func (cp *Capsule) Step(step float32)

type Contact

type Contact struct {

	// one body
	A Body

	// the other body
	B Body

	// normal pointing from center of B to center of A
	NormB math32.Vector3

	// point on spherical shell of B where A is contacting
	PtB math32.Vector3

	// distance from PtB along NormB to contact point on spherical shell of A
	Dist float32
}

Contact is one pairwise point of contact between two bodies. Contacts are represented in spherical terms relative to the spherical BBox of A and B.

func (*Contact) UpdtDist

func (c *Contact) UpdtDist()

UpdtDist updates the distance information for the contact

type Contacts

type Contacts []*Contact

Contacts is a slice list of contacts

func BodyVelBBoxIntersects

func BodyVelBBoxIntersects(a, b Node) Contacts

BodyVelBBoxIntersects returns the list of potential contact nodes between a and b (could be the same or different groups) that have intersecting velocity-projected bounding boxes. In general a should be dynamic bodies and b either dynamic or static. This is the broad first-pass filtering.

func (*Contacts) New

func (cs *Contacts) New(a, b Body) *Contact

New adds a new contact to the list

type Cylinder

type Cylinder struct {
	BodyBase

	// height of the cylinder
	Height float32

	// radius of the top -- set to 0 for a cone
	TopRad float32

	// radius of the bottom
	BotRad float32
}

Cylinder is a generalized cylinder body shape, with separate radii for top and bottom. A cone has a zero radius at one end.

func NewCylinder

func NewCylinder(parent tree.Node, name ...string) *Cylinder

NewCylinder adds a new Cylinder with the given name to the given parent: Cylinder is a generalized cylinder body shape, with separate radii for top and bottom. A cone has a zero radius at one end.

func (*Cylinder) InitAbs

func (cy *Cylinder) InitAbs(par *NodeBase)

func (*Cylinder) New

func (t *Cylinder) New() tree.Node

New returns a new *Cylinder value

func (*Cylinder) NodeType

func (t *Cylinder) NodeType() *types.Type

NodeType returns the *types.Type of Cylinder

func (*Cylinder) RelToAbs

func (cy *Cylinder) RelToAbs(par *NodeBase)

func (*Cylinder) SetBBox

func (cy *Cylinder) SetBBox()

func (*Cylinder) SetBotRad

func (t *Cylinder) SetBotRad(v float32) *Cylinder

SetBotRad sets the [Cylinder.BotRad]: radius of the bottom

func (*Cylinder) SetColor

func (t *Cylinder) SetColor(v string) *Cylinder

SetColor sets the [Cylinder.Color]

func (*Cylinder) SetHeight

func (t *Cylinder) SetHeight(v float32) *Cylinder

SetHeight sets the [Cylinder.Height]: height of the cylinder

func (*Cylinder) SetInitial

func (t *Cylinder) SetInitial(v State) *Cylinder

SetInitial sets the [Cylinder.Initial]

func (*Cylinder) SetRel

func (t *Cylinder) SetRel(v State) *Cylinder

SetRel sets the [Cylinder.Rel]

func (*Cylinder) SetRigid

func (t *Cylinder) SetRigid(v Rigid) *Cylinder

SetRigid sets the [Cylinder.Rigid]

func (*Cylinder) SetTopRad

func (t *Cylinder) SetTopRad(v float32) *Cylinder

SetTopRad sets the [Cylinder.TopRad]: radius of the top -- set to 0 for a cone

func (*Cylinder) SetVis

func (t *Cylinder) SetVis(v string) *Cylinder

SetVis sets the [Cylinder.Vis]

func (*Cylinder) Step

func (cy *Cylinder) Step(step float32)

type Group

type Group struct {
	NodeBase
}

Group is a container of bodies, joints, or other groups it should be used strategically to partition the space and its BBox is used to optimize tree-based collision detection. Use a group for the top-level World node as well.

func NewGroup

func NewGroup(parent tree.Node, name ...string) *Group

NewGroup adds a new Group with the given name to the given parent: Group is a container of bodies, joints, or other groups it should be used strategically to partition the space and its BBox is used to optimize tree-based collision detection. Use a group for the top-level World node as well.

func (*Group) GroupBBox

func (gp *Group) GroupBBox()

func (*Group) InitAbs

func (gp *Group) InitAbs(par *NodeBase)

func (*Group) New

func (t *Group) New() tree.Node

New returns a new *Group value

func (*Group) NodeType

func (t *Group) NodeType() *types.Type

NodeType returns the *types.Type of Group

func (*Group) RayBodyIntersections

func (gp *Group) RayBodyIntersections(ray math32.Ray) []*BodyPoint

RayBodyIntersections returns a list of bodies whose bounding box intersects with the given ray, with the point of intersection

func (*Group) RelToAbs

func (gp *Group) RelToAbs(par *NodeBase)

func (*Group) SetInitial

func (t *Group) SetInitial(v State) *Group

SetInitial sets the [Group.Initial]

func (*Group) SetRel

func (t *Group) SetRel(v State) *Group

SetRel sets the [Group.Rel]

func (*Group) Step

func (gp *Group) Step(step float32)

func (*Group) WorldCollide

func (gp *Group) WorldCollide(dynTop bool) []Contacts

WorldCollide does first pass filtering step of collision detection based on separate dynamic vs. dynamic and dynamic vs. static groups. If dynTop is true, then each Dynamic group is separate at the top level -- otherwise they are organized at the next group level. Contacts are organized by dynamic group, when non-nil, for easier processing.

func (*Group) WorldDynGroupBBox

func (gp *Group) WorldDynGroupBBox()

WorldDynGroupBBox does a GroupBBox on all dynamic nodes

func (*Group) WorldInit

func (gp *Group) WorldInit()

WorldInit does the full tree InitAbs and GroupBBox updates

func (*Group) WorldRelToAbs

func (gp *Group) WorldRelToAbs()

WorldRelToAbs does a full RelToAbs update for all Dynamic groups, for Scripted mode updates with manual updating of Rel values.

func (*Group) WorldStep

func (gp *Group) WorldStep(step float32)

WorldStep does a full Step update for all Dynamic nodes, for either physics or scripted mode, based on current velocities.

type Node

type Node interface {
	tree.Node

	// AsNodeBase returns a generic NodeBase for our node -- gives generic
	// access to all the base-level data structures without needing interface methods.
	AsNodeBase() *NodeBase

	// AsBody returns a generic Body interface for our node -- nil if not a Body
	AsBody() Body

	// IsDynamic returns true if node has Dynamic flag set -- otherwise static
	// Groups that contain dynamic objects set their dynamic flags.
	IsDynamic() bool

	// GroupBBox sets bounding boxes for groups based on groups or bodies.
	// called in a FuncDownMeLast traversal.
	GroupBBox()

	// InitAbs sets current Abs physical state parameters from Initial values
	// which are local, relative to parent -- is passed the parent (nil = top).
	// Body nodes should also set their bounding boxes.
	// Called in a FuncDownMeFirst traversal.
	InitAbs(par *NodeBase)

	// RelToAbs updates current world Abs physical state parameters
	// based on Rel values added to updated Abs values at higher levels.
	// Abs.LinVel is updated from the resulting change from prior position.
	// This is useful for manual updating of relative positions (scripted movement).
	// It is passed the parent (nil = top).
	// Body nodes should also update their bounding boxes.
	// Called in a FuncDownMeFirst traversal.
	RelToAbs(par *NodeBase)

	// Step computes one update of the world Abs physical state parameters,
	// using *current* velocities -- add forces prior to calling.
	// Use this for physics-based state updates.
	// Body nodes should also update their bounding boxes.
	Step(step float32)
}

Node is the common interface for all nodes

type NodeBase

type NodeBase struct {
	tree.NodeBase

	// initial position, orientation, velocity in *local* coordinates (relative to parent)
	Initial State `view:"inline"`

	// current relative (local) position, orientation, velocity -- only change these values, as abs values are computed therefrom
	Rel State `view:"inline"`

	// current absolute (world) position, orientation, velocity
	Abs State `set:"-" edit:"-" view:"inline"`

	// bounding box in world coordinates (aggregated for groups)
	BBox BBox `set:"-"`
}

NodeBase is the basic node, which has position, rotation, velocity and computed bounding boxes, etc. There are only three different kinds of Nodes: Group, Body, and Joint

func NewNodeBase

func NewNodeBase(parent tree.Node, name ...string) *NodeBase

NewNodeBase adds a new NodeBase with the given name to the given parent: NodeBase is the basic node, which has position, rotation, velocity and computed bounding boxes, etc. There are only three different kinds of Nodes: Group, Body, and Joint

func (*NodeBase) AsBody

func (nb *NodeBase) AsBody() Body

func (*NodeBase) AsNodeBase

func (nb *NodeBase) AsNodeBase() *NodeBase

func (*NodeBase) InitAbsBase

func (nb *NodeBase) InitAbsBase(par *NodeBase)

InitAbsBase is the base-level version of InitAbs -- most nodes call this. InitAbs sets current Abs physical state parameters from Initial values which are local, relative to parent -- is passed the parent (nil = top). Body nodes should also set their bounding boxes. Called in a FuncDownMeFirst traversal.

func (*NodeBase) IsDynamic

func (nb *NodeBase) IsDynamic() bool

func (*NodeBase) New

func (t *NodeBase) New() tree.Node

New returns a new *NodeBase value

func (*NodeBase) NodeType

func (t *NodeBase) NodeType() *types.Type

NodeType returns the *types.Type of NodeBase

func (*NodeBase) RelToAbsBase

func (nb *NodeBase) RelToAbsBase(par *NodeBase)

RelToAbsBase is the base-level version of RelToAbs -- most nodes call this. note: Group WorldRelToAbs ensures only called on Dynamic nodes. RelToAbs updates current world Abs physical state parameters based on Rel values added to updated Abs values at higher levels. Abs.LinVel is updated from the resulting change from prior position. This is useful for manual updating of relative positions (scripted movement). It is passed the parent (nil = top). Body nodes should also update their bounding boxes. Called in a FuncDownMeFirst traversal.

func (*NodeBase) SetInitAngVel

func (nb *NodeBase) SetInitAngVel(vel math32.Vector3) *NodeBase

SetInitAngVel sets the initial angular velocity

func (*NodeBase) SetInitLinVel

func (nb *NodeBase) SetInitLinVel(vel math32.Vector3) *NodeBase

SetInitLinVel sets the initial linear velocity

func (*NodeBase) SetInitPos

func (nb *NodeBase) SetInitPos(pos math32.Vector3) *NodeBase

SetInitPos sets the initial position

func (*NodeBase) SetInitQuat

func (nb *NodeBase) SetInitQuat(quat math32.Quat) *NodeBase

SetInitQuat sets the initial rotation as a Quaternion

func (*NodeBase) SetInitial

func (t *NodeBase) SetInitial(v State) *NodeBase

SetInitial sets the [NodeBase.Initial]: initial position, orientation, velocity in *local* coordinates (relative to parent)

func (*NodeBase) SetRel

func (t *NodeBase) SetRel(v State) *NodeBase

SetRel sets the [NodeBase.Rel]: current relative (local) position, orientation, velocity -- only change these values, as abs values are computed therefrom

func (*NodeBase) StepBase

func (nb *NodeBase) StepBase(step float32)

StepBase is base-level version of Step -- most nodes call this. note: Group WorldRelToAbs ensures only called on Dynamic nodes. Computes one update of the world Abs physical state parameters, using *current* velocities -- add forces prior to calling. Use this for physics-based state updates. Body nodes should also update their bounding boxes.

type NodeFlags

type NodeFlags tree.Flags //enums:bitflag

NodeFlags define node bitflags -- uses ki Flags field (64 bit capacity)

const (
	// Dynamic means that this node can move -- if not so marked, it is
	// a Static node.  Any top-level group that is not Dynamic is immediately
	// pruned from further consideration, so top-level groups should be
	// separated into Dynamic and Static nodes at the start.
	Dynamic NodeFlags = NodeFlags(tree.FlagsN) + iota
)
const NodeFlagsN NodeFlags = 2

NodeFlagsN is the highest valid value for type NodeFlags, plus one.

func NodeFlagsValues

func NodeFlagsValues() []NodeFlags

NodeFlagsValues returns all possible values for the type NodeFlags.

func (NodeFlags) BitIndexString

func (i NodeFlags) BitIndexString() string

BitIndexString returns the string representation of this NodeFlags value if it is a bit index value (typically an enum constant), and not an actual bit flag value.

func (NodeFlags) Desc

func (i NodeFlags) Desc() string

Desc returns the description of the NodeFlags value.

func (NodeFlags) HasFlag

func (i NodeFlags) HasFlag(f enums.BitFlag) bool

HasFlag returns whether these bit flags have the given bit flag set.

func (NodeFlags) Int64

func (i NodeFlags) Int64() int64

Int64 returns the NodeFlags value as an int64.

func (NodeFlags) MarshalText

func (i NodeFlags) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*NodeFlags) SetFlag

func (i *NodeFlags) SetFlag(on bool, f ...enums.BitFlag)

SetFlag sets the value of the given flags in these flags to the given value.

func (*NodeFlags) SetInt64

func (i *NodeFlags) SetInt64(in int64)

SetInt64 sets the NodeFlags value from an int64.

func (*NodeFlags) SetString

func (i *NodeFlags) SetString(s string) error

SetString sets the NodeFlags value from its string representation, and returns an error if the string is invalid.

func (*NodeFlags) SetStringOr

func (i *NodeFlags) SetStringOr(s string) error

SetStringOr sets the NodeFlags value from its string representation while preserving any bit flags already set, and returns an error if the string is invalid.

func (NodeFlags) String

func (i NodeFlags) String() string

String returns the string representation of this NodeFlags value.

func (*NodeFlags) UnmarshalText

func (i *NodeFlags) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (NodeFlags) Values

func (i NodeFlags) Values() []enums.Enum

Values returns all possible values for the type NodeFlags.

type Rigid

type Rigid struct {

	// 1/mass -- 0 for no mass
	InvMass float32

	// COR or coefficient of restitution -- how elastic is the collision i.e., final velocity / initial velocity
	Bounce float32 `min:"0" max:"1"`

	// friction coefficient -- how much friction is generated by transverse motion
	Friction float32

	// record of computed force vector from last iteration
	Force math32.Vector3

	// Last calculated rotational inertia matrix in local coords
	RotInertia math32.Matrix3
}

Rigid contains the full specification of a given object's basic physics properties including position, orientation, velocity. These

func (*Rigid) Defaults

func (ps *Rigid) Defaults()

Defaults sets defaults only if current values are nil

type Sphere

type Sphere struct {
	BodyBase

	// radius
	Radius float32
}

Sphere is a spherical body shape.

func NewSphere

func NewSphere(parent tree.Node, name ...string) *Sphere

NewSphere adds a new Sphere with the given name to the given parent: Sphere is a spherical body shape.

func (*Sphere) InitAbs

func (sp *Sphere) InitAbs(par *NodeBase)

func (*Sphere) New

func (t *Sphere) New() tree.Node

New returns a new *Sphere value

func (*Sphere) NodeType

func (t *Sphere) NodeType() *types.Type

NodeType returns the *types.Type of Sphere

func (*Sphere) RelToAbs

func (sp *Sphere) RelToAbs(par *NodeBase)

func (*Sphere) SetBBox

func (sp *Sphere) SetBBox()

func (*Sphere) SetColor

func (t *Sphere) SetColor(v string) *Sphere

SetColor sets the [Sphere.Color]

func (*Sphere) SetInitial

func (t *Sphere) SetInitial(v State) *Sphere

SetInitial sets the [Sphere.Initial]

func (*Sphere) SetRadius

func (t *Sphere) SetRadius(v float32) *Sphere

SetRadius sets the [Sphere.Radius]: radius

func (*Sphere) SetRel

func (t *Sphere) SetRel(v State) *Sphere

SetRel sets the [Sphere.Rel]

func (*Sphere) SetRigid

func (t *Sphere) SetRigid(v Rigid) *Sphere

SetRigid sets the [Sphere.Rigid]

func (*Sphere) SetVis

func (t *Sphere) SetVis(v string) *Sphere

SetVis sets the [Sphere.Vis]

func (*Sphere) Step

func (sp *Sphere) Step(step float32)

type State

type State struct {

	// position of center of mass of object
	Pos math32.Vector3

	// rotation specified as a Quat
	Quat math32.Quat

	// linear velocity
	LinVel math32.Vector3

	// angular velocity
	AngVel math32.Vector3
}

State contains the basic physical state including position, orientation, velocity. These are only the values that can be either relative or absolute -- other physical state values such as Mass should go in Rigid.

func (*State) Defaults

func (ps *State) Defaults()

Defaults sets defaults only if current values are nil

func (*State) EulerRotation

func (ps *State) EulerRotation() math32.Vector3

EulerRotation returns the current rotation in Euler angles (degrees).

func (*State) EulerRotationRad

func (ps *State) EulerRotationRad() math32.Vector3

EulerRotationRad returns the current rotation in Euler angles (radians).

func (*State) FromRel

func (ps *State) FromRel(rel, par *State)

FromRel sets state from relative values compared to a parent state

func (*State) Move

func (ps *State) Move(delta math32.Vector3)

Move moves (translates) Pos by given amount, and sets the LinVel to the given delta -- this can be useful for Scripted motion to track movement.

func (*State) MoveOnAxis

func (ps *State) MoveOnAxis(x, y, z, dist float32)

MoveOnAxis moves (translates) the specified distance on the specified local axis, relative to the current rotation orientation. The axis is normalized prior to aplying the distance factor. Sets the LinVel to motion vector.

func (*State) MoveOnAxisAbs

func (ps *State) MoveOnAxisAbs(x, y, z, dist float32)

MoveOnAxisAbs moves (translates) the specified distance on the specified local axis, in absolute X,Y,Z coordinates (does not apply the Quat rotation factor. The axis is normalized prior to aplying the distance factor. Sets the LinVel to motion vector.

func (*State) RotateEuler

func (ps *State) RotateEuler(x, y, z float32)

RotateEuler rotates by given Euler angles (in degrees) relative to existing rotation.

func (*State) RotateEulerRad

func (ps *State) RotateEulerRad(x, y, z, angle float32)

RotateEulerRad rotates by given Euler angles (in radians) relative to existing rotation.

func (*State) RotateOnAxis

func (ps *State) RotateOnAxis(x, y, z, angle float32)

RotateOnAxis rotates around the specified local axis the specified angle in degrees.

func (*State) RotateOnAxisRad

func (ps *State) RotateOnAxisRad(x, y, z, angle float32)

RotateOnAxisRad rotates around the specified local axis the specified angle in radians.

func (*State) SetAxisRotation

func (ps *State) SetAxisRotation(x, y, z, angle float32)

SetAxisRotation sets rotation from local axis and angle in degrees.

func (*State) SetAxisRotationRad

func (ps *State) SetAxisRotationRad(x, y, z, angle float32)

SetAxisRotationRad sets rotation from local axis and angle in radians.

func (*State) SetEulerRotation

func (ps *State) SetEulerRotation(x, y, z float32)

SetEulerRotation sets the rotation in Euler angles (degrees).

func (*State) SetEulerRotationRad

func (ps *State) SetEulerRotationRad(x, y, z float32)

SetEulerRotationRad sets the rotation in Euler angles (radians).

func (*State) StepByAngVel

func (ps *State) StepByAngVel(step float32)

StepByAngVel steps the Quat rotation from angular velocity

func (*State) StepByLinVel

func (ps *State) StepByLinVel(step float32)

StepByLinVel steps the Pos from the linear velocity

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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