Skip to content

Commit

Permalink
Physics improvements (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
mokiat authored Jan 25, 2024
1 parent bd029b3 commit cf08f19
Show file tree
Hide file tree
Showing 29 changed files with 1,770 additions and 1,028 deletions.
26 changes: 19 additions & 7 deletions debug/metric/flamegraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import (
)

var (
rootSpan Span
rootRegion *Region
currentRegion *Region
rootSpan Span
recordedIterations int

rootRegion *Region
iterations int

currentRegion *Region
resetRequested bool
)

func init() {
Expand All @@ -21,19 +26,26 @@ func init() {
currentRegion = rootRegion
}

func FrameTree() Span {
return rootSpan
func FrameTree() (Span, int) {
resetRequested = true
return rootSpan, recordedIterations
}

func BeginFrame() {
iterations++
currentRegion = rootRegion
rootRegion.startTime = time.Now()
}

func EndFrame() {
rootRegion.duration = time.Since(rootRegion.startTime)
rootRegion.duration += time.Since(rootRegion.startTime)
updateSpan(&rootSpan, rootRegion)
resetRegion(rootRegion)
recordedIterations = iterations
if resetRequested {
iterations = 0
resetRegion(rootRegion)
resetRequested = false
}
}

type Span struct {
Expand Down
11 changes: 6 additions & 5 deletions debug/metric/metricui/flamegraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,12 @@ func (c *flamegraphComponent) renderSpan(canvas *ui.Canvas, span metric.Span, ra
}

func (c *flamegraphComponent) onRefresh() {
tree := metric.FrameTree()
tree, iterations := metric.FrameTree()
iterations = max(1, iterations)
if focusedNode, ok := c.findSpan(tree, c.path); ok {
tree = focusedNode
}
c.updateTree(&c.tree, &tree)
c.updateTree(&c.tree, &tree, iterations)

treeDepth := c.spanTreeDepth(tree)
c.element.SetIdealSize(ui.Size{
Expand Down Expand Up @@ -189,13 +190,13 @@ func (c *flamegraphComponent) findSpan(node metric.Span, path []string) (metric.
return metric.Span{}, false
}

func (c *flamegraphComponent) updateTree(target, source *metric.Span) {
func (c *flamegraphComponent) updateTree(target, source *metric.Span, iterations int) {
target.Name = source.Name
target.Duration = time.Duration(dprec.Mix(float64(source.Duration), float64(target.Duration), c.aggregationRatio))
target.Duration = time.Duration(dprec.Mix(float64(source.Duration), float64(target.Duration), c.aggregationRatio) / float64(iterations))
if missing := len(source.Children) - len(target.Children); missing > 0 {
target.Children = append(target.Children, make([]metric.Span, missing)...)
}
for i := range source.Children {
c.updateTree(&target.Children[i], &source.Children[i])
c.updateTree(&target.Children[i], &source.Children[i], iterations)
}
}
6 changes: 3 additions & 3 deletions game/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import (
)

type BodyNodeSource struct {
Body *physics.Body
Body physics.Body
}

func (s BodyNodeSource) ApplyTo(node *hierarchy.Node) {
translation := s.Body.VisualPosition()
rotation := s.Body.VisualOrientation()
translation := s.Body.IntermediatePosition()
rotation := s.Body.IntermediateRotation()
scale := dprec.NewVec3(1.0, 1.0, 1.0)
node.SetAbsoluteMatrix(dprec.TRSMat4(translation, rotation, scale))
}
Expand Down
5 changes: 5 additions & 0 deletions game/graphics/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,9 +669,14 @@ func (r *sceneRenderer) Render(framebuffer render.Framebuffer, viewport Viewport
}
r.renderPostprocessingPass(ctx)

uniformSpan := metric.BeginRegion("upload")
r.uniforms.Upload()
uniformSpan.End()

submitSpan := metric.BeginRegion("submit")
r.api.Queue().Invalidate()
r.api.Queue().Submit(r.commandBuffer)
submitSpan.End()
}

func (r *sceneRenderer) evaluateProjectionMatrix(camera *Camera, width, height int) sprec.Mat4 {
Expand Down
4 changes: 2 additions & 2 deletions game/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ type Model struct {
nodes []*hierarchy.Node
armatures []*graphics.Armature
animations []*Animation
bodyInstances []*physics.Body
bodyInstances []physics.Body
pointLightInstances []*graphics.PointLight
spotLightInstances []*graphics.SpotLight
directionalLightInstances []*graphics.DirectionalLight
Expand All @@ -513,7 +513,7 @@ func (m *Model) FindNode(name string) *hierarchy.Node {
return m.root.FindNode(name)
}

func (m *Model) BodyInstances() []*physics.Body {
func (m *Model) BodyInstances() []physics.Body {
return m.bodyInstances
}

Expand Down
102 changes: 102 additions & 0 deletions game/physics/acceleration/gravity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package acceleration

import (
"github.com/mokiat/gomath/dprec"
"github.com/mokiat/lacking/game/physics/solver"
)

// NewGravityDirection creates a new GravityDirection acceleration
// that applies a constant force in a specific direction.
func NewGravityDirection() *GravityDirection {
return &GravityDirection{
direction: dprec.NewVec3(0.0, -1.0, 0.0),
acceleration: 9.8,
}
}

var _ solver.Acceleration = (*GravityDirection)(nil)

// GravityDirection represents the solution for an acceleration that
// applies a constant force in a specific direction.
type GravityDirection struct {
direction dprec.Vec3
acceleration float64
}

// Direction returns the direction of the gravity force.
func (d *GravityDirection) Direction() dprec.Vec3 {
return d.direction
}

// SetDirection changes the direction of the gravity force.
func (d *GravityDirection) SetDirection(direction dprec.Vec3) *GravityDirection {
d.direction = direction
return d
}

// Acceleration returns the acceleration of the gravity force.
func (d *GravityDirection) Acceleration() float64 {
return d.acceleration
}

// SetAcceleration changes the acceleration of the gravity force.
func (d *GravityDirection) SetAcceleration(acceleration float64) *GravityDirection {
d.acceleration = acceleration
return d
}

func (d *GravityDirection) ApplyAcceleration(ctx solver.AccelerationContext) {
ctx.Target.AddLinearAcceleration(
dprec.Vec3Prod(d.direction, d.acceleration),
)
}

// NewGravityPosition creates a new GravityPosition acceleration
// that applies a constant force towards a specific position.
func NewGravityPosition() *GravityPosition {
return &GravityPosition{
position: dprec.ZeroVec3(),
}
}

var _ solver.Acceleration = (*GravityPosition)(nil)

// GravityPosition represents the solution for an acceleration that
// applies a constant force towards a specific position.
type GravityPosition struct {
position dprec.Vec3
acceleration float64

// TODO: Add ability to control distance falloff.
}

// Position returns the position of the gravity force.
func (d *GravityPosition) Position() dprec.Vec3 {
return d.position
}

// SetPosition changes the position of the gravity force.
func (d *GravityPosition) SetPosition(position dprec.Vec3) *GravityPosition {
d.position = position
return d
}

// Acceleration returns the acceleration of the gravity force.
func (d *GravityPosition) Acceleration() float64 {
return d.acceleration
}

// SetAcceleration changes the acceleration of the gravity force.
func (d *GravityPosition) SetAcceleration(acceleration float64) *GravityPosition {
d.acceleration = acceleration
return d
}

func (d *GravityPosition) ApplyAcceleration(ctx solver.AccelerationContext) {
delta := dprec.Vec3Diff(d.position, ctx.Target.Position())
if distance := delta.Length(); distance > solver.Epsilon {
ctx.Target.AddLinearAcceleration(
dprec.ResizedVec3(delta, d.acceleration),
)
}
}
79 changes: 77 additions & 2 deletions game/physics/accelerator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,82 @@
package physics

type Accelerator struct {
import "github.com/mokiat/lacking/game/physics/solver"

var invalidGlobalAcceleratorState = &globalAcceleratorState{}

// GlobalAccelerator represents a force that is applied to all
// bodies in the scene.
type GlobalAccelerator struct {
scene *Scene
reference indexReference
}

// Logic returns the acceleration solver that will be used to
// apply this global accelerator.
func (a GlobalAccelerator) Logic() solver.Acceleration {
state := a.state()
return state.logic
}

// Enabled returns whether this global accelerator will be applied.
func (a GlobalAccelerator) Enabled() bool {
state := a.state()
return state.enabled
}

// SetEnabled changes whether this global accelerator will be applied.
func (a GlobalAccelerator) SetEnabled(enabled bool) {
state := a.state()
state.enabled = enabled
}

// Delete removes this global accelerator.
func (a GlobalAccelerator) Delete() {
deleteGlobalAccelerator(a.scene, a.reference)
}

func (a GlobalAccelerator) state() *globalAcceleratorState {
index := a.reference.Index
state := &a.scene.globalAccelerators[index]
if state.reference != a.reference {
return invalidGlobalAcceleratorState
}
return state
}

type globalAcceleratorState struct {
reference indexReference
logic solver.Acceleration
enabled bool
}

func createGlobalAccelerator(scene *Scene, logic solver.Acceleration) GlobalAccelerator {
var freeIndex uint32
if scene.freeGlobalAcceleratorIndices.IsEmpty() {
freeIndex = uint32(len(scene.globalAccelerators))
scene.globalAccelerators = append(scene.globalAccelerators, globalAcceleratorState{})
} else {
freeIndex = scene.freeGlobalAcceleratorIndices.Pop()
}

reference := newIndexReference(freeIndex, scene.nextRevision())
scene.globalAccelerators[freeIndex] = globalAcceleratorState{
reference: reference,
logic: logic,
enabled: true,
}
return GlobalAccelerator{
scene: scene,
reference: reference,
}
}

type AccelerationContext struct {
func deleteGlobalAccelerator(scene *Scene, reference indexReference) {
index := reference.Index
state := &scene.globalAccelerators[index]
if state.reference == reference {
state.reference = newIndexReference(index, 0)
state.logic = nil
scene.freeGlobalAcceleratorIndices.Push(index)
}
}
26 changes: 20 additions & 6 deletions game/physics/aerodynamics.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,17 @@ func (p AerodynamicShape) Transformed(parent Transform) AerodynamicShape {
// AerodynamicSolver represents a shape that is affected
// by air or liquid motion and inflicts a force on the body.
type AerodynamicSolver interface {
Force(windSpeed dprec.Vec3) dprec.Vec3
Force(windSpeed dprec.Vec3, density float64) dprec.Vec3
}

func NewSurfaceAerodynamicShape(width, height, length float64) *SurfaceAerodynamicShape {
return &SurfaceAerodynamicShape{
width: width,
height: height,
length: length,

dragCoefficient: 0.5,
liftCoefficient: 2.1,
}
}

Expand All @@ -92,16 +95,27 @@ type SurfaceAerodynamicShape struct {
width float64
height float64
length float64

dragCoefficient float64
liftCoefficient float64
}

func (s *SurfaceAerodynamicShape) SetDragCoefficient(coefficient float64) *SurfaceAerodynamicShape {
s.dragCoefficient = coefficient
return s
}

func (s *SurfaceAerodynamicShape) SetLiftCoefficient(coefficient float64) *SurfaceAerodynamicShape {
s.liftCoefficient = coefficient
return s
}

func (s *SurfaceAerodynamicShape) Force(windSpeed dprec.Vec3) dprec.Vec3 {
func (s *SurfaceAerodynamicShape) Force(windSpeed dprec.Vec3, density float64) dprec.Vec3 {
// DRAG
dragX := s.length * s.height * dprec.Vec3Dot(windSpeed, dprec.BasisXVec3())
dragY := s.width * s.length * dprec.Vec3Dot(windSpeed, dprec.BasisYVec3())
dragZ := s.width * s.height * dprec.Vec3Dot(windSpeed, dprec.BasisZVec3())
ro := 1.2
cD := 0.5
result := dprec.Vec3Prod(dprec.NewVec3(dragX, dragY, dragZ), windSpeed.Length()*ro*cD/2.0)
result := dprec.Vec3Prod(dprec.NewVec3(dragX, dragY, dragZ), windSpeed.Length()*density*s.dragCoefficient/2.0)

// LIFT
liftVelocity := -dprec.Vec3Dot(windSpeed, dprec.BasisZVec3())
Expand All @@ -111,7 +125,7 @@ func (s *SurfaceAerodynamicShape) Force(windSpeed dprec.Vec3) dprec.Vec3 {
if dprec.Abs(sn) < stallSN {
result = dprec.Vec3Sum(result, dprec.NewVec3(
0.0,
sn*2.5*liftVelocity*liftVelocity*s.width*s.length,
sn*density*s.liftCoefficient*liftVelocity*liftVelocity*s.width*s.length,
0.0,
))
}
Expand Down
Loading

0 comments on commit cf08f19

Please sign in to comment.