channel.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 animation
  5. import (
  6. "github.com/g3n/engine/core"
  7. "github.com/g3n/engine/math32"
  8. )
  9. // A Channel associates an animation parameter channel to an interpolation sampler
  10. type Channel struct {
  11. keyframes math32.ArrayF32 // Input keys (usually time)
  12. values math32.ArrayF32 // Outputs values for the keys
  13. interpType InterpolationType // Interpolation type
  14. interpAction func(idx int, k float32) // Combined function for interpolation and update
  15. updateInterpAction func() // Function to update interpAction based on interpolation type
  16. inTangent math32.ArrayF32 // Origin tangents for Spline interpolation
  17. outTangent math32.ArrayF32 // End tangents for Spline interpolation
  18. }
  19. // SetBuffers sets the keyframe and value buffers.
  20. func (c *Channel) SetBuffers(keyframes, values math32.ArrayF32) {
  21. c.keyframes = keyframes
  22. c.values = values
  23. }
  24. // Keyframes returns the keyframe buffer.
  25. func (c *Channel) Keyframes() math32.ArrayF32 {
  26. return c.keyframes
  27. }
  28. // Values returns the value buffer.
  29. func (c *Channel) Values() math32.ArrayF32 {
  30. return c.values
  31. }
  32. // SetInterpolationTangents sets the interpolation tangents.
  33. func (c *Channel) SetInterpolationTangents(inTangent, outTangent math32.ArrayF32) {
  34. c.inTangent = inTangent
  35. c.outTangent = outTangent
  36. }
  37. // InterpolationTangents sets the interpolation tangents
  38. func (c *Channel) InterpolationTangents() (inTangent, outTangent math32.ArrayF32) {
  39. return c.inTangent, c.outTangent
  40. }
  41. // SetInterpolationType sets the interpolation type for this channel.
  42. func (c *Channel) SetInterpolationType(it InterpolationType) {
  43. // Don't update function if not needed
  44. if c.interpType == it {
  45. return
  46. }
  47. // Save interpolation type
  48. c.interpType = it
  49. // Call specialized function that updates the interpAction function
  50. c.updateInterpAction()
  51. }
  52. // InterpolationType returns the current interpolation type.
  53. func (c *Channel) InterpolationType() InterpolationType {
  54. return c.interpType
  55. }
  56. // Update finds the keyframe preceding the specified time.
  57. // Then, calls a stored function to interpolate the relevant values and update the target.
  58. func (c *Channel) Update(time float32) {
  59. // Test limits
  60. if (len(c.keyframes) < 2) || (time < c.keyframes[0]) || (time > c.keyframes[len(c.keyframes)-1]) {
  61. return
  62. }
  63. // Find key frame interval
  64. var idx int
  65. for idx = 0; idx < len(c.keyframes)-1; idx++ {
  66. if time >= c.keyframes[idx] && time < c.keyframes[idx+1] {
  67. break
  68. }
  69. }
  70. // Check if last keyframe
  71. if idx >= len(c.keyframes)-1 {
  72. return
  73. }
  74. // Interpolate and update
  75. relativeDelta := (time-c.keyframes[idx])/(c.keyframes[idx+1]-c.keyframes[idx])
  76. c.interpAction(idx, relativeDelta)
  77. }
  78. // IChannel is the interface for all channel types.
  79. type IChannel interface {
  80. Update(time float32)
  81. SetBuffers(keyframes, values math32.ArrayF32)
  82. Keyframes() math32.ArrayF32
  83. Values() math32.ArrayF32
  84. SetInterpolationType(it InterpolationType)
  85. }
  86. // NodeChannel is the IChannel for all node transforms.
  87. type NodeChannel struct {
  88. Channel
  89. target core.INode
  90. }
  91. // PositionChannel is the animation channel for a node's position.
  92. type PositionChannel NodeChannel
  93. func NewPositionChannel(node core.INode) *PositionChannel {
  94. pc := new(PositionChannel)
  95. pc.target = node
  96. pc.updateInterpAction = func() {
  97. // Get node
  98. node := pc.target.GetNode()
  99. // Update interpolation function
  100. switch pc.interpType {
  101. case STEP:
  102. pc.interpAction = func(idx int, k float32) {
  103. var v math32.Vector3
  104. pc.values.GetVector3(idx*3, &v)
  105. node.SetPositionVec(&v)
  106. }
  107. case LINEAR:
  108. pc.interpAction = func(idx int, k float32) {
  109. var v1, v2 math32.Vector3
  110. pc.values.GetVector3(idx*3, &v1)
  111. pc.values.GetVector3((idx+1)*3, &v2)
  112. v1.Lerp(&v2, k)
  113. node.SetPositionVec(&v1)
  114. }
  115. case CUBICSPLINE: // TODO
  116. pc.interpAction = func(idx int, k float32) {
  117. var v1, v2 math32.Vector3
  118. pc.values.GetVector3(idx*3, &v1)
  119. pc.values.GetVector3((idx+1)*3, &v2)
  120. v1.Lerp(&v2, k)
  121. node.SetPositionVec(&v1)
  122. }
  123. }
  124. }
  125. pc.SetInterpolationType(LINEAR)
  126. return pc
  127. }
  128. // RotationChannel is the animation channel for a node's rotation.
  129. type RotationChannel NodeChannel
  130. func NewRotationChannel(node core.INode) *RotationChannel {
  131. rc := new(RotationChannel)
  132. rc.target = node
  133. rc.updateInterpAction = func() {
  134. // Get node
  135. node := rc.target.GetNode()
  136. // Update interpolation function
  137. switch rc.interpType {
  138. case STEP:
  139. rc.interpAction = func(idx int, k float32) {
  140. var q math32.Vector4
  141. rc.values.GetVector4(idx*4, &q)
  142. node.SetQuaternionVec(&q)
  143. }
  144. case LINEAR:
  145. rc.interpAction = func(idx int, k float32) {
  146. var q1, q2 math32.Vector4
  147. rc.values.GetVector4(idx*4, &q1)
  148. rc.values.GetVector4((idx+1)*4, &q2)
  149. q1.Lerp(&q2, k)
  150. quat1 := math32.NewQuaternion(q1.X, q1.Y, q1.Z, q1.W)
  151. // TODO spherical linear interpolation (slerp) not working as expected for some reason (doing a lerp for now)
  152. //quat2 := math32.NewQuaternion(q2.X, q2.Y, q2.Z, q2.W)
  153. //quat1.Slerp(quat2, k)
  154. node.SetQuaternionQuat(quat1)
  155. }
  156. case CUBICSPLINE: // TODO
  157. rc.interpAction = func(idx int, k float32) {
  158. var q1, q2 math32.Vector4
  159. rc.values.GetVector4(idx*4, &q1)
  160. rc.values.GetVector4((idx+1)*4, &q2)
  161. q1.Lerp(&q2, k)
  162. quat1 := math32.NewQuaternion(q1.X, q1.Y, q1.Z, q1.W)
  163. // TODO spherical linear interpolation (slerp) not working for some reason
  164. //quat2 := math32.NewQuaternion(q2.X, q2.Y, q2.Z, q2.W)
  165. //quat1.Slerp(quat2, k)
  166. node.SetQuaternionQuat(quat1)
  167. }
  168. }
  169. }
  170. rc.SetInterpolationType(LINEAR)
  171. return rc
  172. }
  173. // ScaleChannel is the animation channel for a node's scale.
  174. type ScaleChannel NodeChannel
  175. func NewScaleChannel(node core.INode) *ScaleChannel {
  176. sc := new(ScaleChannel)
  177. sc.target = node
  178. sc.updateInterpAction = func() {
  179. // Get node
  180. node := sc.target.GetNode()
  181. // Update interpolation function
  182. switch sc.interpType {
  183. case STEP:
  184. sc.interpAction = func(idx int, k float32) {
  185. var v math32.Vector3
  186. sc.values.GetVector3(idx*3, &v)
  187. node.SetScaleVec(&v)
  188. }
  189. case LINEAR:
  190. sc.interpAction = func(idx int, k float32) {
  191. var v1, v2 math32.Vector3
  192. sc.values.GetVector3(idx*3, &v1)
  193. sc.values.GetVector3((idx+1)*3, &v2)
  194. v1.Lerp(&v2, k)
  195. node.SetScaleVec(&v1)
  196. }
  197. case CUBICSPLINE: // TODO
  198. sc.interpAction = func(idx int, k float32) {
  199. var v1, v2 math32.Vector3
  200. sc.values.GetVector3(idx*3, &v1)
  201. sc.values.GetVector3((idx+1)*3, &v2)
  202. v1.Lerp(&v2, k)
  203. node.SetScaleVec(&v1)
  204. }
  205. }
  206. }
  207. sc.SetInterpolationType(LINEAR)
  208. return sc
  209. }
  210. // InterpolationType specifies the interpolation type.
  211. type InterpolationType string
  212. // The various interpolation types.
  213. const (
  214. STEP = InterpolationType("STEP") // The animated values remain constant to the output of the first keyframe, until the next keyframe.
  215. LINEAR = InterpolationType("LINEAR") // The animated values are linearly interpolated between keyframes. Spherical linear interpolation (slerp) is used to interpolate quaternions.
  216. CUBICSPLINE = InterpolationType("CUBICSPLINE") // TODO
  217. )