Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use advanced physics #20

Merged
merged 50 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
f5f2417
wip: enhanced physics
mokiat Apr 7, 2020
e7a5dfd
use fixed steps in physics simulation
mokiat Apr 15, 2020
10653c0
add experimental constraints
mokiat Apr 15, 2020
16666f6
add jacobian-based constraint resolution
mokiat Apr 18, 2020
3e8cc10
add chandelier constraint
mokiat Apr 18, 2020
5fede41
refactor fixed position constraint
mokiat Apr 18, 2020
3558714
fix dual constraint drift formula
mokiat Apr 18, 2020
6ba2de1
refactor rope constraint
mokiat Apr 18, 2020
e14c644
use quaternion for orientation
mokiat Apr 19, 2020
4f58b93
rework debug shaders
mokiat Apr 19, 2020
a9f3cbb
add color and update to vertex array
mokiat Apr 19, 2020
044464f
fixed translation ignores small drifts
mokiat Apr 19, 2020
ab2d052
hinged rod ignores small drifts
mokiat Apr 19, 2020
159fd53
chandelier ignores small drifts
mokiat Apr 19, 2020
98969ab
fix chandelier drift calculation
mokiat Apr 19, 2020
526300e
add copy translation constraint
mokiat Apr 19, 2020
7d5c7a3
redesign copy rotation constraint
mokiat Apr 20, 2020
b248467
wip experimentation
mokiat Apr 20, 2020
05a58af
add dummy friction motion
mokiat Apr 21, 2020
7b3243b
fix rotation constraint offsets
mokiat Apr 22, 2020
2a35633
bump gomath dependency
mokiat Apr 23, 2020
f49bc59
remove old vehicle system
mokiat Apr 24, 2020
75ef833
introduce dedicated physics package
mokiat Apr 25, 2020
ba3e425
move constraint def to new physics package
mokiat Apr 25, 2020
3b1cdcf
wip (breaking): move constraints to physics package
mokiat Apr 25, 2020
6377619
switch to new physics package
mokiat Apr 25, 2020
43466d9
add hackish translation limits
mokiat Apr 25, 2020
746ec2b
add a dash of duct tape to get something working
mokiat Apr 26, 2020
ddb4868
relocate collision package
mokiat Apr 26, 2020
9174f5e
improve playground level
mokiat Apr 28, 2020
ff22190
move asset loading to controller
mokiat Apr 28, 2020
519eb79
wip: enhanced physics
mokiat Apr 30, 2020
ea61662
make more playable
mokiat Apr 30, 2020
631652c
fix match axis constraint
mokiat May 1, 2020
8714f75
improve match axis constraint
mokiat May 1, 2020
4b81621
switch to new shape package
mokiat May 2, 2020
f1d1e50
restore debug lines
mokiat May 2, 2020
22311f4
remove unused spring and damper constraints
mokiat May 2, 2020
df52c38
fix friction impulse
mokiat May 2, 2020
bf2951e
refactor single body jacobian
mokiat May 3, 2020
e4816c4
refactor double body jacobian
mokiat May 3, 2020
f8a24d3
cleanup car system
mokiat May 3, 2020
dcfbcb9
add coilover constraint
mokiat May 4, 2020
0436f53
remove unused constraint options
mokiat May 5, 2020
219ef6b
add physics context
mokiat May 5, 2020
7bb4b46
remove comment
mokiat May 5, 2020
6df539c
cleanup car component
mokiat May 5, 2020
c65e771
default to forest track
mokiat May 6, 2020
6154af5
relocate car system
mokiat May 6, 2020
82af94b
rename tire to wheel
mokiat May 6, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ The following projects and individuals have contributed significantly to the pro

* **[GLFW for Go](https://github.com/go-gl/glfw)** for making it possible to use GLFW and OpenGL in Go.
* **[Bo0mer](https://github.com/Bo0mer)** for the panoramic image that was used to generate the individual `city` skybox images.
* **[Erin Catto](https://github.com/erincatto)** for all the presentations and articles that were used as reference.
106 changes: 106 additions & 0 deletions cmd/rallymka/internal/ecs/car.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package ecs

import (
"time"

"github.com/mokiat/gomath/sprec"
)

const (
// TODO: Move constants as part of car descriptor
carMaxSteeringAngle = 40
carSteeringSpeed = 80
carSteeringRestoreSpeed = 150

carFrontAcceleration = 160
carRearAcceleration = 80
carReverseAccelerationRatio = 0.75

carFrontBrakeRatio = 0.1
carRearBrakeRatio = 0.1
)

func NewCarSystem(ecsManager *Manager) *CarSystem {
return &CarSystem{
ecsManager: ecsManager,
}
}

type CarSystem struct {
ecsManager *Manager
}

func (s *CarSystem) Update(elapsedTime time.Duration, input CarInput) {
elapsedSeconds := float32(elapsedTime.Seconds())

for _, entity := range s.ecsManager.Entities() {
if car := entity.Car; car != nil && entity.HumanInput {
s.updateCarSteering(car, elapsedSeconds, input)
s.updateCarAcceleration(car, elapsedSeconds, input)
}
}
}

func (s *CarSystem) updateCarSteering(car *Car, elapsedSeconds float32, input CarInput) {
actualSteeringAngle := carMaxSteeringAngle / (1.0 + 0.03*car.Chassis.Velocity.Length())
switch {
case input.TurnLeft == input.TurnRight:
if car.SteeringAngle > 0.001 {
if car.SteeringAngle -= sprec.Degrees(elapsedSeconds * carSteeringRestoreSpeed); car.SteeringAngle < 0.0 {
car.SteeringAngle = 0.0
}
}
if car.SteeringAngle < -0.001 {
if car.SteeringAngle += sprec.Degrees(elapsedSeconds * carSteeringRestoreSpeed); car.SteeringAngle > 0.0 {
car.SteeringAngle = 0.0
}
}
case input.TurnLeft:
if car.SteeringAngle += sprec.Degrees(elapsedSeconds * carSteeringSpeed); car.SteeringAngle > sprec.Degrees(actualSteeringAngle) {
car.SteeringAngle = sprec.Degrees(actualSteeringAngle)
}
case input.TurnRight:
if car.SteeringAngle -= sprec.Degrees(elapsedSeconds * carSteeringSpeed); car.SteeringAngle < -sprec.Degrees(actualSteeringAngle) {
car.SteeringAngle = -sprec.Degrees(actualSteeringAngle)
}
}

rotationQuat := sprec.RotationQuat(car.SteeringAngle, sprec.BasisYVec3())
car.FLWheelRotation.FirstBodyAxis = sprec.QuatVec3Rotation(rotationQuat, sprec.BasisXVec3())
car.FRWheelRotation.FirstBodyAxis = sprec.QuatVec3Rotation(rotationQuat, sprec.BasisXVec3())
}

func (s *CarSystem) updateCarAcceleration(car *Car, elapsedSeconds float32, input CarInput) {
// TODO: Remove, just for debugging
if input.Handbrake {
car.Chassis.AngularVelocity = sprec.Vec3Sum(car.Chassis.AngularVelocity, sprec.NewVec3(0.0, 0.0, 0.1))
car.Chassis.Velocity = sprec.Vec3Sum(car.Chassis.Velocity, sprec.NewVec3(0.0, 0.2, 0.0))
}

if input.Forward {
if sprec.Vec3Dot(car.Chassis.Velocity, car.Chassis.Orientation.OrientationZ()) < -5.0 {
car.FLWheel.AngularVelocity = sprec.Vec3Prod(car.FLWheel.AngularVelocity, 1.0-carFrontBrakeRatio)
car.FRWheel.AngularVelocity = sprec.Vec3Prod(car.FRWheel.AngularVelocity, 1.0-carFrontBrakeRatio)
car.BLWheel.AngularVelocity = sprec.Vec3Prod(car.BLWheel.AngularVelocity, 1.0-carRearBrakeRatio)
car.BRWheel.AngularVelocity = sprec.Vec3Prod(car.BRWheel.AngularVelocity, 1.0-carRearBrakeRatio)
} else {
car.FLWheel.AngularVelocity = sprec.Vec3Sum(car.FLWheel.AngularVelocity, sprec.Vec3Prod(car.FLWheel.Orientation.OrientationX(), carFrontAcceleration*elapsedSeconds))
car.FRWheel.AngularVelocity = sprec.Vec3Sum(car.FRWheel.AngularVelocity, sprec.Vec3Prod(car.FRWheel.Orientation.OrientationX(), carFrontAcceleration*elapsedSeconds))
car.BLWheel.AngularVelocity = sprec.Vec3Sum(car.BLWheel.AngularVelocity, sprec.Vec3Prod(car.BLWheel.Orientation.OrientationX(), carRearAcceleration*elapsedSeconds))
car.BRWheel.AngularVelocity = sprec.Vec3Sum(car.BRWheel.AngularVelocity, sprec.Vec3Prod(car.BRWheel.Orientation.OrientationX(), carRearAcceleration*elapsedSeconds))
}
}
if input.Backward {
if sprec.Vec3Dot(car.Chassis.Velocity, car.Chassis.Orientation.OrientationZ()) > 5.0 {
car.FLWheel.AngularVelocity = sprec.Vec3Prod(car.FLWheel.AngularVelocity, 1.0-carFrontBrakeRatio)
car.FRWheel.AngularVelocity = sprec.Vec3Prod(car.FRWheel.AngularVelocity, 1.0-carFrontBrakeRatio)
car.BLWheel.AngularVelocity = sprec.Vec3Prod(car.BLWheel.AngularVelocity, 1.0-carRearBrakeRatio)
car.BRWheel.AngularVelocity = sprec.Vec3Prod(car.BRWheel.AngularVelocity, 1.0-carRearBrakeRatio)
} else {
car.FLWheel.AngularVelocity = sprec.Vec3Sum(car.FLWheel.AngularVelocity, sprec.Vec3Prod(car.FLWheel.Orientation.OrientationX(), -carFrontAcceleration*carReverseAccelerationRatio*elapsedSeconds))
car.FRWheel.AngularVelocity = sprec.Vec3Sum(car.FRWheel.AngularVelocity, sprec.Vec3Prod(car.FRWheel.Orientation.OrientationX(), -carFrontAcceleration*carReverseAccelerationRatio*elapsedSeconds))
car.BLWheel.AngularVelocity = sprec.Vec3Sum(car.BLWheel.AngularVelocity, sprec.Vec3Prod(car.BLWheel.Orientation.OrientationX(), -carRearAcceleration*carReverseAccelerationRatio*elapsedSeconds))
car.BRWheel.AngularVelocity = sprec.Vec3Sum(car.BRWheel.AngularVelocity, sprec.Vec3Prod(car.BRWheel.Orientation.OrientationX(), -carRearAcceleration*carReverseAccelerationRatio*elapsedSeconds))
}
}
}
66 changes: 26 additions & 40 deletions cmd/rallymka/internal/ecs/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ import (
"github.com/mokiat/gomath/sprec"
"github.com/mokiat/rally-mka/cmd/rallymka/internal/stream"
"github.com/mokiat/rally-mka/internal/engine/graphics"
"github.com/mokiat/rally-mka/internal/engine/physics"
)

type Entity struct {
Transform *TransformComponent
RenderMesh *RenderMesh
RenderModel *RenderModel
Physics *PhysicsComponent
Render *RenderComponent
RenderSkybox *RenderSkybox
Vehicle *Vehicle
Wheel *Wheel
Input *Input
Car *Car
CameraStand *CameraStand
HumanInput bool
}

type RenderModel struct {
Model *stream.Model
GeomProgram *graphics.Program
type PhysicsComponent struct {
Body *physics.Body
}

type RenderMesh struct {
Mesh *stream.Mesh
type RenderComponent struct {
GeomProgram *graphics.Program
Model *stream.Model
Mesh *stream.Mesh
Matrix sprec.Mat4
}

type RenderSkybox struct {
Expand All @@ -33,39 +33,25 @@ type RenderSkybox struct {
Mesh *stream.Mesh
}

type Vehicle struct {
SteeringAngle sprec.Angle
Acceleration float32
HandbrakePulled bool

Position sprec.Vec3
Orientation Orientation
Velocity sprec.Vec3
AngularVelocity sprec.Vec3

FLWheel *Entity
FRWheel *Entity
BLWheel *Entity
BRWheel *Entity
type CarInput struct {
Forward bool
Backward bool
TurnLeft bool
TurnRight bool
Handbrake bool
}

type Wheel struct {
SteeringAngle sprec.Angle
RotationAngle sprec.Angle

AnchorPosition sprec.Vec3

IsDriven bool

Length float32
Radius float32

SuspensionLength float32
IsGrounded bool
type Car struct {
SteeringAngle sprec.Angle
Chassis *physics.Body
FLWheelRotation *physics.MatchAxisConstraint
FRWheelRotation *physics.MatchAxisConstraint
FLWheel *physics.Body
FRWheel *physics.Body
BLWheel *physics.Body
BRWheel *physics.Body
}

type Input struct{}

type CameraStand struct {
Target *Entity
AnchorPosition sprec.Vec3
Expand Down
37 changes: 19 additions & 18 deletions cmd/rallymka/internal/ecs/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,32 @@ type Renderer struct {
}

func (r *Renderer) Render(sequence *graphics.Sequence) {
r.renderRenderMeshes(sequence)
r.renderRenderModels(sequence)
r.renderRender(sequence)
r.renderRenderSkyboxes(sequence)
}

func (r *Renderer) renderRenderMeshes(sequence *graphics.Sequence) {
func (r *Renderer) renderRender(sequence *graphics.Sequence) {
for _, entity := range r.ecsManager.Entities() {
transformComp := entity.Transform
renderMeshComp := entity.RenderMesh
if transformComp == nil || renderMeshComp == nil {
render := entity.Render
if render == nil {
continue
}
r.renderMesh(sequence, renderMeshComp.GeomProgram, transformComp.Matrix(), renderMeshComp.Mesh)
}
}

func (r *Renderer) renderRenderModels(sequence *graphics.Sequence) {
for _, entity := range r.ecsManager.Entities() {
transformComp := entity.Transform
renderModelComp := entity.RenderModel
if transformComp == nil || renderModelComp == nil {
continue
if entity.Physics != nil {
body := entity.Physics.Body
render.Matrix = sprec.TransformationMat4(
body.Orientation.OrientationX(),
body.Orientation.OrientationY(),
body.Orientation.OrientationZ(),
body.Position,
)
}
if render.Model != nil {
for _, node := range render.Model.Nodes {
r.renderModelNode(sequence, render.GeomProgram, render.Matrix, node)
}
}
for _, node := range renderModelComp.Model.Nodes {
r.renderModelNode(sequence, renderModelComp.GeomProgram, transformComp.Matrix(), node)
if render.Mesh != nil {
r.renderMesh(sequence, render.GeomProgram, render.Matrix, render.Mesh)
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions cmd/rallymka/internal/ecs/stand.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ func (s *CameraStandSystem) Update() {
}
}

var angleSpeed sprec.Angle = sprec.Degrees(0.0)
var angle sprec.Angle = sprec.Degrees(0)

func (s *CameraStandSystem) updateCameraStand(cameraStand *CameraStand) {
angle += angleSpeed

var targetPosition sprec.Vec3
if cameraStand.Target.Vehicle != nil {
targetPosition = cameraStand.Target.Vehicle.Position
switch {
case cameraStand.Target.Physics != nil:
targetPosition = cameraStand.Target.Physics.Body.Position
case cameraStand.Target.Render != nil:
targetPosition = cameraStand.Target.Render.Matrix.Translation()
}
// we use a camera anchor to achieve the smooth effect of a
// camera following the target
Expand All @@ -45,6 +53,7 @@ func (s *CameraStandSystem) updateCameraStand(cameraStand *CameraStand) {
sprec.UnitVec3(cameraVectorZ),
sprec.ZeroVec3(),
),
sprec.RotationMat4(angle, 0.0, 1.0, 0.0),
sprec.RotationMat4(sprec.Degrees(-25.0), 1.0, 0.0, 0.0),
sprec.TranslationMat4(0.0, 0.0, cameraStand.CameraDistance),
))
Expand Down
60 changes: 0 additions & 60 deletions cmd/rallymka/internal/ecs/transform.go

This file was deleted.

Loading