diff options
Diffstat (limited to 'src/sims/dynamics/World.scala')
-rw-r--r-- | src/sims/dynamics/World.scala | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/sims/dynamics/World.scala b/src/sims/dynamics/World.scala new file mode 100644 index 0000000..d7ac8ae --- /dev/null +++ b/src/sims/dynamics/World.scala @@ -0,0 +1,163 @@ +/* + * Simple Mechanics Simulator (SiMS) + * copyright (c) 2009 Jakob Odersky + * made available under the MIT License +*/ + +package sims.dynamics + +import sims.geometry._ +import sims.collision._ +import sims.dynamics.joints._ +import scala.collection.mutable._ + +/**Eine Welt enthaelt und Simuliert ein System aus Koerpern und Verbindungen.*/ +class World { + + /**Zeitschritt in dem diese Welt die Simulation vorranschreiten laesst.*/ + var timeStep: Double = 1.0 / 60 + + /**Anzahl der Constraint-Korrekturen pro Zeitschritt.*/ + var iterations: Int = 10 + + /**Schwerkraft die in dieser Welt herrscht.*/ + var gravity = Vector2D(0, -9.81) + + /**Alle Koerper die diese Welt simuliert.*/ + val bodies = new ArrayBuffer[Body] + + /**Alle Verbindungen die diese Welt simuliert.*/ + val joints = new ArrayBuffer[Joint] + + /**Ueberwachungsfunktionen fuer Koerper. + * <p> + * Das erste Element des Tuples ist die Ueberschrift und das zweite Element, der Wert.*/ + val monitors = new ArrayBuffer[(String, Body => String)] + + /**Kollisionsdetektor dieser Welt.*/ + val detector: Detector = new GridDetector(this) + + /**Warnung wenn Koerper schneller als Lichtgeschwindigkeit.*/ + var overCWarning = false + + /**Kollisionerkennung.*/ + var enableCollisionDetection = true + + /**Positionskorrekturen.*/ + var enablePositionCorrection = true + + /**Die minimale, nicht als null geltende Geschwindigkeit.*/ + var minLinearVelocity: Double = 0.0001 + + /**Die minimale, nicht als null geltende Winkelgeschwindigkeit.*/ + var minAngularVelocity: Double = 0.0001 + + /**Ergibt alle Formen aus allen Koerpern in dieser Welt.*/ + def shapes = for (b <- bodies; s <- b.shapes) yield s + + /**Fuegt dieser Welt einen Koerper hinzu.*/ + def +=(body: Body) = bodies += body + + /**Fuegt dieser Welt eine Verbindung hinzu.*/ + def +=(joint: Joint): Unit = joints += joint + + /**Fuegt dieser Welt ein vorangefertigtes System vaus Koerpern und Verbindungen hinzu.*/ + def +=(p: prefabs.Prefab): Unit = { + for (b <- p.bodies) this += b + for (j <- p.joints) this += j + } + + def ++=(bs: Seq[Body]) = for(b <- bs) this += b + + /**Entfernt den gegebenen Koerper aus dieser Welt.*/ + def -=(body: Body): Unit = bodies -= body + + /**Entfernt die gegebene Verbindung aus dieser Welt.*/ + def -=(joint: Joint): Unit = joints -= joint + + /**Entfernt das gegebene System aus Koerpern und Verbindungen aus dieser Welt.*/ + def -=(p: prefabs.Prefab): Unit = { + for (b <- p.bodies) this -= b + for (j <- p.joints) this -= j + } + + def --=(bs: Seq[Body]) = for(b <- bs) this -= b + + /**Entfernt alle Koerper, Verbindungen und Ueberwachungsfunktionen dieser Welt.*/ + def clear() = {joints.clear(); bodies.clear(); monitors.clear()} + + /**Aktuelle Zeit in Sekunden dieser Welt. Nach jedem Zeitschritt wird die Zeit erhoeht.*/ + var time: Double = 0.0 + + /**Simuliert einen von <code>timeStep</code> angegebenen Zeitschritt. + * Ihre Aufgabe ist es die Koerper dieser Welt so zu simulieren wie diese sich in einer Welt mit den gegebenen + * Bedingungen verhalten wuerden. + * <p> + * Der Zeitschritt wird in folgenden Phasen ausgefuehrt: + * <ol> + * <li>Kraefte wirken auf die Koerper (z.B Schwerkraft, andere Kraftfaehige Objekte).</li> + * <li>Beschleunigungen werden integriert.</li> + * <li>Geschwindigkeiten werden korrigiert.</li> + * <li>Geschwindigkeiten werden integriert.</li> + * <li>Positionen werden korrigiert.</li> + * <li>Die Methode <code>postStep()</code> wird ausgefuehrt.</li> + * </ol>*/ + def step() = { + time += timeStep + + //Kraftobjekte + for (j <- joints) j match {case f: ForceJoint => f.applyForce; case _ => ()} + + //integriert v + for (b <- bodies) { + val m = b.mass + b.applyForce(gravity * b.mass) + val a = b.force / b.mass + val alpha = b.torque / b.I + b.linearVelocity = b.linearVelocity + a * timeStep + b.angularVelocity = b.angularVelocity + alpha * timeStep + } + + //korrigiert v + for (i <- 0 until iterations){ + for(c <- joints) c.correctVelocity(timeStep) + if (enableCollisionDetection) for (c <- detector.collisions) c.correctVelocity(timeStep) + } + + //integriert pos + for (b <- bodies) { + //warning when body gets faster than speed of light + if (b.linearVelocity.length >= 300000000) overCWarning = true + if (b.linearVelocity.length < minLinearVelocity) b.linearVelocity = Vector2D.Null + if (b.angularVelocity.abs < minAngularVelocity) b.angularVelocity = 0.0 + b.pos = b.pos + b.linearVelocity * timeStep + b.rotation = b.rotation + b.angularVelocity * timeStep + b.force = Vector2D.Null + b.torque = 0.0 + } + + //korrigiert pos + if (enablePositionCorrection) for (i <- 0 until iterations){ + for (c <- joints) c.correctPosition(timeStep) + if (enableCollisionDetection) for (c <- detector.collisions) c.correctPosition(timeStep) + } + + postStep() + } + + /**Wird nach jedem Zeitschritt ausgefuehrt.*/ + def postStep() = {} + + /**Ergibt Informationen ueber diese Welt.*/ + def info = { + "Bodies = " + bodies.length + "\n" + + "Shapes = " + shapes.length + "\n" + + "Joints = " + joints.length + "\n" + + "Collisions = " + detector.collisions.length + "\n" + + "Monitors = " + monitors.length + "\n" + + "Gravity = " + gravity + "m/s^2\n" + + "Timestep = " + timeStep + "s\n" + + "Time = " + time + "s\n" + + "Iterations = " + iterations + } +} |