lock.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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 constraint
  6. import (
  7. "github.com/g3n/engine/physics/equation"
  8. "github.com/g3n/engine/math32"
  9. )
  10. // Lock constraint.
  11. // Removes all degrees of freedom between the bodies.
  12. type Lock struct {
  13. PointToPoint
  14. rotEq1 *equation.Rotational
  15. rotEq2 *equation.Rotational
  16. rotEq3 *equation.Rotational
  17. xA *math32.Vector3
  18. xB *math32.Vector3
  19. yA *math32.Vector3
  20. yB *math32.Vector3
  21. zA *math32.Vector3
  22. zB *math32.Vector3
  23. }
  24. // NewLock creates and returns a pointer to a new Lock constraint object.
  25. func NewLock(bodyA, bodyB IBody, maxForce float32) *Lock {
  26. lc := new(Lock)
  27. // Set pivot point in between
  28. posA := bodyA.Position()
  29. posB := bodyB.Position()
  30. halfWay := math32.NewVec3().AddVectors(&posA, &posB)
  31. halfWay.MultiplyScalar(0.5)
  32. pivotB := bodyB.PointToLocal(halfWay)
  33. pivotA := bodyA.PointToLocal(halfWay)
  34. // The point-to-point constraint will keep a point shared between the bodies
  35. lc.initialize(bodyA, bodyB, &pivotA, &pivotB, maxForce)
  36. // Store initial rotation of the bodies as unit vectors in the local body spaces
  37. UnitX := math32.NewVector3(1,0,0)
  38. localA := bodyA.VectorToLocal(UnitX)
  39. localB := bodyB.VectorToLocal(UnitX)
  40. lc.xA = &localA
  41. lc.xB = &localB
  42. lc.yA = &localA
  43. lc.yB = &localB
  44. lc.zA = &localA
  45. lc.zB = &localB
  46. // ...and the following rotational equations will keep all rotational DOF's in place
  47. lc.rotEq1 = equation.NewRotational(bodyA, bodyB, maxForce)
  48. lc.rotEq2 = equation.NewRotational(bodyA, bodyB, maxForce)
  49. lc.rotEq3 = equation.NewRotational(bodyA, bodyB, maxForce)
  50. lc.equations = append(lc.equations, &lc.rotEq1.Equation)
  51. lc.equations = append(lc.equations, &lc.rotEq2.Equation)
  52. lc.equations = append(lc.equations, &lc.rotEq3.Equation)
  53. return lc
  54. }
  55. // Update updates the equations with data.
  56. func (lc *Lock) Update() {
  57. lc.PointToPoint.Update()
  58. // These vector pairs must be orthogonal
  59. xAw := lc.bodyA.VectorToWorld(lc.xA)
  60. yBw := lc.bodyA.VectorToWorld(lc.yB)
  61. yAw := lc.bodyA.VectorToWorld(lc.yA)
  62. zBw := lc.bodyB.VectorToWorld(lc.zB)
  63. zAw := lc.bodyA.VectorToWorld(lc.zA)
  64. xBw := lc.bodyB.VectorToWorld(lc.xB)
  65. lc.rotEq1.SetAxisA(&xAw)
  66. lc.rotEq1.SetAxisB(&yBw)
  67. lc.rotEq2.SetAxisA(&yAw)
  68. lc.rotEq2.SetAxisB(&zBw)
  69. lc.rotEq3.SetAxisA(&zAw)
  70. lc.rotEq3.SetAxisB(&xBw)
  71. }