lock.go 2.4 KB

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