channel.go 8.5 KB

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