body.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package tamias
  2. type BodyVelocityFunc func (body Body, gravity Vect, damping, dt Float)
  3. type BodyPositionFunc func (body Body, dt Float)
  4. type DataPointer * interface{}
  5. /*
  6. var (
  7. BodyUpdateVelocityDefault BodyVelocityFunc = Body.UpdateVelocity
  8. BodyUpdatePositionDefault BodyPositionFunc = Body.UpdatePosition
  9. )
  10. */
  11. type Body struct {
  12. // *** Integration Functions.ntoehu
  13. // Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)
  14. velocityFunc BodyVelocityFunc;
  15. // Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)
  16. positionFunc BodyPositionFunc;
  17. // *** Mass Properties
  18. // Mass and it's inverse.
  19. // Always use cpBodySetMass() whenever changing the mass as these values must agree.
  20. m, m_inv Float;
  21. // Moment of inertia and it's inverse.
  22. // Always use cpBodySetMoment() whenever changing the moment as these values must agree.
  23. i, i_inv Float;
  24. // *** Positional Properties
  25. // Linear components of motion (position, velocity, and force)
  26. p, v, f Vect;
  27. // Angular components of motion (angle, angular velocity, and torque)
  28. // Always use cpBodySetAngle() to set the angle of the body as a and rot must agree.
  29. a, w, t Float;
  30. // Cached unit length vector representing the angle of the body.
  31. // Used for fast vector rotation using cpvrotate().
  32. rot Vect;
  33. // *** User Definable Fields
  34. // User defined data pointer.
  35. data DataPointer;
  36. // Maximum velocities this body can move at after integrating velocity
  37. v_limit, w_limit Float;
  38. // *** Internally Used Fields
  39. // Velocity bias values used when solving penetrations and correcting constraints.
  40. v_bias Vect;
  41. w_bias Float;
  42. // int active;
  43. }
  44. func (body * Body) Mass() (Float) {
  45. return body.m
  46. }
  47. func (body * Body) SetMass(m Float) (Float) {
  48. body.m = m
  49. body.m_inv = Float(1.0) / m
  50. return body.m
  51. }
  52. func (body * Body) Moment() (Float) {
  53. return body.i
  54. }
  55. func (body * Body) SetMoment(i Float) (Float) {
  56. body.i = i
  57. body.i_inv = Float(1.0) / i
  58. return body.i
  59. }
  60. func (body * Body) Pos() (Vect) {
  61. return body.p
  62. }
  63. func (body * Body) Vel() (Vect) {
  64. return body.v
  65. }
  66. func (body * Body) Force() (Vect) {
  67. return body.f
  68. }
  69. func (body * Body) Angle() (Float) {
  70. return body.a
  71. }
  72. func (body * Body) SetAngle(a Float) (Float) {
  73. body.a = a
  74. body.rot = a.VectForAngle()
  75. return body.a
  76. }
  77. func (body * Body) AngVel() (Float) {
  78. return body.w
  79. }
  80. func (body * Body) Torque() (Float) {
  81. return body.t
  82. }
  83. func (body * Body) Rot() (Vect) {
  84. return body.rot
  85. }
  86. func (body * Body) VelLimit() (Float) {
  87. return body.v_limit
  88. }
  89. func (body * Body) AngVelLimit() (Float) {
  90. return body.w_limit
  91. }
  92. func (body * Body) SetVelLimit(v Float) (Float) {
  93. body.v_limit = v
  94. return body.v_limit
  95. }
  96. func (body * Body) SetAngVelLimit(v Float) (Float) {
  97. body.w_limit = v
  98. return body.w_limit
  99. }
  100. // Convert body local to world coordinates
  101. func (body *Body) Local2World(v Vect) (Vect) {
  102. return body.p.Add(v.Rotate(body.rot))
  103. }
  104. // Convert world to body local coordinates
  105. func (body *Body) World2Local(v Vect) (Vect) {
  106. return v.Sub(body.p).Unrotate(body.rot)
  107. }
  108. // Apply an impulse (in world coordinates) to the body at a point relative to
  109. // the center of gravity (also in world coordinates).
  110. func (body *Body) ApplyImpulse(j, r Vect) {
  111. body.v = body.v.Add(j.Mult(body.m_inv))
  112. body.w += body.i_inv * r.Cross(j)
  113. }
  114. // Not intended for external use. Used by cpArbiter.c and cpConstraint.c.
  115. func (body *Body) ApplyBiasImpulse(j, r Vect) {
  116. body.v_bias = body.v_bias.Add(j.Mult(body.m_inv))
  117. body.w_bias += body.i_inv * r.Cross(j)
  118. }
  119. func BodyAlloc() (* Body) {
  120. return &Body{}
  121. }
  122. func (body *Body) Init(m Float, i Float) (*Body) {
  123. /* Compiler doesn't seem to support these yet,
  124. or maybe I misunderstood the syntax?
  125. body.velocityFunc = Body.UpdateVelocity
  126. body.positionFunc = Body.UpdatePosition
  127. */
  128. body.SetMass(m)
  129. body.SetMoment(i)
  130. body.p = VZERO
  131. body.v = VZERO
  132. body.f = VZERO
  133. body.SetAngle(Float(0.0))
  134. body.w = Float(0.0)
  135. body.t = Float(0.0)
  136. body.v_bias = VZERO
  137. body.w_bias = Float(0.0)
  138. body.data = nil
  139. body.v_limit = INFINITY
  140. body.w_limit = INFINITY
  141. // body.active = 1;
  142. return body
  143. }
  144. func BodyNew(m, i Float) (*Body) {
  145. return BodyAlloc().Init(m, i)
  146. }
  147. func (body * Body) Destroy() {
  148. }
  149. func (body * Body) Free() {
  150. if body != nil {
  151. body.Destroy()
  152. body = nil
  153. }
  154. }
  155. func (body * Body) Slew(pos Vect, dt Float) {
  156. delta := pos.Sub(body.p)
  157. body.v = delta.Mult(Float(1.0) / dt)
  158. }
  159. func (body * Body) UpdateVelocity(gravity Vect, damping, dt Float) {
  160. vdamp := body.v.Mult(damping)
  161. vforc := gravity.Add(body.f.Mult(body.m_inv)).Mult(dt)
  162. body.v = vdamp.Add(vforc).Clamp(body.v_limit)
  163. w_lim := body.w_limit
  164. waid := body.w*damping + body.t*body.i_inv*dt
  165. body.w = waid.Clamp(-w_lim, w_lim)
  166. }
  167. func (body * Body) UpdatePosition(dt Float) {
  168. body.p = body.p.Add(body.v.Add(body.v_bias).Mult(dt))
  169. body.SetAngle(body.a + (body.w + body.w_bias)*dt)
  170. body.v_bias = VZERO;
  171. body.w_bias = Float(0.0)
  172. }
  173. func (body * Body) ResetForces() {
  174. body.f = VZERO
  175. body.t = Float(0.0)
  176. }
  177. func (body * Body) ApplyForce(force, r Vect) {
  178. body.f = body.f.Add(force)
  179. body.t += r.Cross(force)
  180. }
  181. func ApplyDampedSpring(a, b *Body, anchr1, anchr2 Vect, rlen, k, dmp, dt Float) {
  182. // Calculate the world space anchor coordinates.
  183. r1 := anchr1.Rotate(a.rot)
  184. r2 := anchr2.Rotate(b.rot)
  185. delta := b.p.Add(r2).Sub(a.p.Add(r1))
  186. dist := delta.Length()
  187. n := VZERO
  188. if (dist > 0.0) {
  189. n = delta.Mult(Float(1.0)/dist)
  190. }
  191. f_spring := (dist - rlen)*k;
  192. // Calculate the world relative velocities of the anchor points.
  193. // This really should be in the impulse solver and can produce problems when using large damping values.
  194. v1 := a.v.Add(r1.Perp().Mult(a.w))
  195. v2 := b.v.Add(r2.Perp().Mult(b.w))
  196. vrn := v2.Sub(v1).Dot(n)
  197. f_damp := vrn * dmp.Min(Float(1.0) / (dt * (a.m_inv + b.m_inv)))
  198. // Apply!
  199. f := n.Mult(f_spring + f_damp)
  200. a.ApplyForce(f , r1);
  201. b.ApplyForce(f.Neg() , r2);
  202. }
  203. //int
  204. //cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max)
  205. //{
  206. // cpFloat ke = body->m*cpvdot(body->v, body->v);
  207. // cpFloat re = body->i*body->w*body->w;
  208. //
  209. // if(ke + re > body->m*dvsq)
  210. // body->active = 1;
  211. // else if(body->active)
  212. // body->active = (body->active + 1)%(max + 1);
  213. // else {
  214. // body->v = cpvzero;
  215. // body->v_bias = cpvzero;
  216. // body->w = 0.0f;
  217. // body->w_bias = 0.0f;
  218. // }
  219. //
  220. // return body->active;
  221. //}