aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/sims/dynamics/World.scala
blob: e02f38ad6ca66db557e98af2c032f98bf1562642 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*    _____ _ __  ________    ___                                      *\
**   / ___/(_)  |/  / ___/   |__ \  Simple Mechanics Simulator 2       **
**   \__ \/ / /|_/ /\__ \    __/ /  copyright (c) 2011 Jakob Odersky   **
**  ___/ / / /  / /___/ /   / __/                                      **
** /____/_/_/  /_//____/   /____/                                      **
\*                                                                     */

package sims.dynamics

import scala.collection.mutable.ArrayBuffer
import sims.collision._
import sims.collision.broadphase.SAP
import sims.collision.narrowphase.SAT
import sims.math.Vector2D

class World {
	
	val detector = SAP[sims.dynamics.Shape] narrowedBy
                  new sims.collision.narrowphase.gjk.GJK2[sims.dynamics.Shape]
								 //SAT[sims.dynamics.Shape]
	
	var collisionDetection = true
	
	private val _bodies = new ArrayBuffer[Body]
	def bodies: Seq[Body] = _bodies
	
	def +=(b: Body): Unit = {
		_bodies += b
		detector ++= b.shapes
	}
	def -=(b: Body): Unit = {
		_bodies -= b
		detector --= b.shapes
	}
	
	def shapes: Seq[sims.dynamics.Shape] = for (b <- bodies; s <- b.shapes) yield s
	
	private val _joints = new ArrayBuffer[Joint]
	def joints: Seq[Joint] = _joints
	
	def +=(j: Joint): Unit = _joints += j
	def -=(j: Joint): Unit = _joints -= j
	
	def clear() = {
		detector.clear()
		for (b <- bodies) _bodies -= b
		for (j <- joints) _joints -= j
	}
	
	
	var h = 1.0 / 60
	
	var iterations = 10
	
	var errorReduction = 0.2
	
	var gravity = sims.math.Vector2D(0, -9.8)
	
	def preStep() = {}
	
	def step() = {
		
		preStep()
		
		for (b <- _bodies) {
			b applyForce gravity * b.mass
			b.linearVelocity += (b.force / b.mass) * h
			b.angularVelocity += (b.torque / b.inertia) * h
		}
		
		for (j <- joints) {
			j.preSolve()
		}
		for (i <- 0 until iterations)
			for (j <- joints) j.correctVelocity(h, errorReduction)
		
		if (collisionDetection) {
			import Collision._
			val physicalCollisions: Seq[Collision] = detector.collisions.map(_.toPhysical)
			for (c <- physicalCollisions) c.preSolve()
			for (i <- 0 until iterations)
				for (c <- physicalCollisions) c.correctVelocity(h, errorReduction)
			
		}
		
		
		for (b <- _bodies) {
			b.position += b.linearVelocity * h
			b.rotation += b.angularVelocity * h
			b.force = Vector2D.Null
		}
		
		postStep()
	}
	
	def postStep(): Unit = {
		detector.invalidate()
	}
	
	
}