gs.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package physics implements a basic physics engine.
  5. package solver
  6. import (
  7. "github.com/g3n/engine/math32"
  8. )
  9. // GaussSeidel equation solver.
  10. // See https://en.wikipedia.org/wiki/Gauss-Seidel_method.
  11. // The number of solver iterations determines the quality of the solution.
  12. // More iterations yield a better solution but require more computation.
  13. type GaussSeidel struct {
  14. Solver
  15. maxIter int // Number of solver iterations.
  16. tolerance float32 // When the error is less than the tolerance, the system is assumed to be converged.
  17. solveInvCs []float32
  18. solveBs []float32
  19. solveLambda []float32
  20. }
  21. // NewGaussSeidel creates and returns a pointer to a new GaussSeidel constraint equation solver.
  22. func NewGaussSeidel() *GaussSeidel {
  23. gs := new(GaussSeidel)
  24. gs.maxIter = 20
  25. gs.tolerance = 1e-7
  26. gs.VelocityDeltas = make([]math32.Vector3, 0)
  27. gs.AngularVelocityDeltas = make([]math32.Vector3, 0)
  28. gs.solveInvCs = make([]float32, 0)
  29. gs.solveBs = make([]float32, 0)
  30. gs.solveLambda = make([]float32, 0)
  31. return gs
  32. }
  33. func (gs *GaussSeidel) Reset(numBodies int) {
  34. // Reset solution
  35. gs.VelocityDeltas = make([]math32.Vector3, numBodies)
  36. gs.AngularVelocityDeltas = make([]math32.Vector3, numBodies)
  37. gs.Iterations = 0
  38. // Reset internal arrays
  39. gs.solveInvCs = gs.solveInvCs[0:0]
  40. gs.solveBs = gs.solveBs[0:0]
  41. gs.solveLambda = gs.solveLambda[0:0]
  42. }
  43. // Solve
  44. func (gs *GaussSeidel) Solve(dt float32, nBodies int) *Solution {
  45. gs.Reset(nBodies)
  46. iter := 0
  47. nEquations := len(gs.equations)
  48. h := dt
  49. // Things that do not change during iteration can be computed once
  50. for i := 0; i < nEquations; i++ {
  51. eq := gs.equations[i]
  52. gs.solveInvCs = append(gs.solveInvCs, 1.0/eq.ComputeC())
  53. gs.solveBs = append(gs.solveBs, eq.ComputeB(h))
  54. gs.solveLambda = append(gs.solveLambda, 0.0)
  55. }
  56. if nEquations > 0 {
  57. tolSquared := gs.tolerance * gs.tolerance
  58. // Iterate over equations
  59. for iter = 0; iter < gs.maxIter; iter++ {
  60. // Accumulate the total error for each iteration.
  61. deltaLambdaTot := float32(0)
  62. for j := 0; j < nEquations; j++ {
  63. eq := gs.equations[j]
  64. // Compute iteration
  65. lambdaJ := gs.solveLambda[j]
  66. idxBodyA := eq.BodyA().Index()
  67. idxBodyB := eq.BodyB().Index()
  68. vA := gs.VelocityDeltas[idxBodyA]
  69. vB := gs.VelocityDeltas[idxBodyB]
  70. wA := gs.AngularVelocityDeltas[idxBodyA]
  71. wB := gs.AngularVelocityDeltas[idxBodyB]
  72. jeA := eq.JeA()
  73. jeB := eq.JeB()
  74. GWlambda := jeA.MultiplyVectors(&vA, &wA) + jeB.MultiplyVectors(&vB, &wB)
  75. deltaLambda := gs.solveInvCs[j] * (gs.solveBs[j] - GWlambda - eq.Eps()*lambdaJ)
  76. // Clamp if we are outside the min/max interval
  77. if (lambdaJ + deltaLambda) < eq.MinForce() {
  78. deltaLambda = eq.MinForce() - lambdaJ
  79. } else if (lambdaJ + deltaLambda) > eq.MaxForce() {
  80. deltaLambda = eq.MaxForce() - lambdaJ
  81. }
  82. gs.solveLambda[j] += deltaLambda
  83. deltaLambdaTot += math32.Abs(deltaLambda)
  84. // Add to velocity deltas
  85. spatA := jeA.Spatial()
  86. spatB := jeB.Spatial()
  87. gs.VelocityDeltas[idxBodyA].Add(spatA.MultiplyScalar(eq.BodyA().InvMassEff() * deltaLambda))
  88. gs.VelocityDeltas[idxBodyB].Add(spatB.MultiplyScalar(eq.BodyB().InvMassEff() * deltaLambda))
  89. // Add to angular velocity deltas
  90. rotA := jeA.Rotational()
  91. rotB := jeB.Rotational()
  92. gs.AngularVelocityDeltas[idxBodyA].Add(rotA.ApplyMatrix3(eq.BodyA().InvRotInertiaWorldEff()).MultiplyScalar(deltaLambda))
  93. gs.AngularVelocityDeltas[idxBodyB].Add(rotB.ApplyMatrix3(eq.BodyB().InvRotInertiaWorldEff()).MultiplyScalar(deltaLambda))
  94. }
  95. // If the total error is small enough - stop iterating
  96. if deltaLambdaTot*deltaLambdaTot < tolSquared {
  97. break
  98. }
  99. }
  100. // Set the .multiplier property of each equation
  101. for i := range gs.equations {
  102. gs.equations[i].SetMultiplier(gs.solveLambda[i] / h)
  103. }
  104. iter += 1
  105. }
  106. gs.Iterations = iter
  107. return &gs.Solution
  108. }