channel.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 keyframe 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. // Interpolate and update
  72. relativeDelta := (time-c.keyframes[idx])/(c.keyframes[idx+1]-c.keyframes[idx])
  73. c.interpAction(idx, relativeDelta)
  74. }
  75. // IChannel is the interface for all channel types.
  76. type IChannel interface {
  77. Update(time float32)
  78. SetBuffers(keyframes, values math32.ArrayF32)
  79. Keyframes() math32.ArrayF32
  80. Values() math32.ArrayF32
  81. SetInterpolationType(it InterpolationType)
  82. }
  83. // NodeChannel is the IChannel for all node transforms.
  84. type NodeChannel struct {
  85. Channel
  86. target core.INode
  87. }
  88. // PositionChannel is the animation channel for a node's position.
  89. type PositionChannel NodeChannel
  90. func NewPositionChannel(node core.INode) *PositionChannel {
  91. pc := new(PositionChannel)
  92. pc.target = node
  93. pc.updateInterpAction = func() {
  94. // Get node
  95. node := pc.target.GetNode()
  96. // Update interpolation function
  97. switch pc.interpType {
  98. case STEP:
  99. pc.interpAction = func(idx int, k float32) {
  100. var v math32.Vector3
  101. pc.values.GetVector3(idx*3, &v)
  102. node.SetPositionVec(&v)
  103. }
  104. case LINEAR:
  105. pc.interpAction = func(idx int, k float32) {
  106. var v1, v2 math32.Vector3
  107. pc.values.GetVector3(idx*3, &v1)
  108. pc.values.GetVector3((idx+1)*3, &v2)
  109. v1.Lerp(&v2, k)
  110. node.SetPositionVec(&v1)
  111. }
  112. case CUBICSPLINE: // TODO
  113. pc.interpAction = func(idx int, k float32) {
  114. var v1, v2 math32.Vector3
  115. pc.values.GetVector3(idx*3, &v1)
  116. pc.values.GetVector3((idx+1)*3, &v2)
  117. v1.Lerp(&v2, k)
  118. node.SetPositionVec(&v1)
  119. }
  120. }
  121. }
  122. pc.SetInterpolationType(LINEAR)
  123. return pc
  124. }
  125. // RotationChannel is the animation channel for a node's rotation.
  126. type RotationChannel NodeChannel
  127. func NewRotationChannel(node core.INode) *RotationChannel {
  128. rc := new(RotationChannel)
  129. rc.target = node
  130. rc.updateInterpAction = func() {
  131. // Get node
  132. node := rc.target.GetNode()
  133. // Update interpolation function
  134. switch rc.interpType {
  135. case STEP:
  136. rc.interpAction = func(idx int, k float32) {
  137. var q math32.Vector4
  138. rc.values.GetVector4(idx*4, &q)
  139. node.SetQuaternionVec(&q)
  140. }
  141. case LINEAR:
  142. rc.interpAction = func(idx int, k float32) {
  143. var q1, q2 math32.Vector4
  144. rc.values.GetVector4(idx*4, &q1)
  145. rc.values.GetVector4((idx+1)*4, &q2)
  146. quat1 := math32.NewQuaternion(q1.X, q1.Y, q1.Z, q1.W)
  147. quat2 := math32.NewQuaternion(q2.X, q2.Y, q2.Z, q2.W)
  148. quat1.Slerp(quat2, k)
  149. node.SetQuaternionQuat(quat1)
  150. }
  151. case CUBICSPLINE: // TODO
  152. rc.interpAction = func(idx int, k float32) {
  153. var q1, q2 math32.Vector4
  154. rc.values.GetVector4(idx*4, &q1)
  155. rc.values.GetVector4((idx+1)*4, &q2)
  156. quat1 := math32.NewQuaternion(q1.X, q1.Y, q1.Z, q1.W)
  157. quat2 := math32.NewQuaternion(q2.X, q2.Y, q2.Z, q2.W)
  158. quat1.Slerp(quat2, k)
  159. node.SetQuaternionQuat(quat1)
  160. }
  161. }
  162. }
  163. rc.SetInterpolationType(LINEAR)
  164. return rc
  165. }
  166. // ScaleChannel is the animation channel for a node's scale.
  167. type ScaleChannel NodeChannel
  168. func NewScaleChannel(node core.INode) *ScaleChannel {
  169. sc := new(ScaleChannel)
  170. sc.target = node
  171. sc.updateInterpAction = func() {
  172. // Get node
  173. node := sc.target.GetNode()
  174. // Update interpolation function
  175. switch sc.interpType {
  176. case STEP:
  177. sc.interpAction = func(idx int, k float32) {
  178. var v math32.Vector3
  179. sc.values.GetVector3(idx*3, &v)
  180. node.SetScaleVec(&v)
  181. }
  182. case LINEAR:
  183. sc.interpAction = func(idx int, k float32) {
  184. var v1, v2 math32.Vector3
  185. sc.values.GetVector3(idx*3, &v1)
  186. sc.values.GetVector3((idx+1)*3, &v2)
  187. v1.Lerp(&v2, k)
  188. node.SetScaleVec(&v1)
  189. }
  190. case CUBICSPLINE: // TODO
  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. }
  199. }
  200. sc.SetInterpolationType(LINEAR)
  201. return sc
  202. }
  203. // MorphChannel is the IChannel for morph geometries.
  204. type MorphChannel struct {
  205. Channel
  206. target *geometry.MorphGeometry
  207. }
  208. func NewMorphChannel(mg *geometry.MorphGeometry) *MorphChannel {
  209. mc := new(MorphChannel)
  210. mc.target = mg
  211. numWeights := len(mg.Weights())
  212. mc.updateInterpAction = func() {
  213. // Update interpolation function
  214. switch mc.interpType {
  215. case STEP:
  216. mc.interpAction = func(idx int, k float32) {
  217. start := idx*numWeights
  218. weights := mc.values[start:start+numWeights]
  219. mg.SetWeights(weights)
  220. }
  221. case LINEAR:
  222. mc.interpAction = func(idx int, k float32) {
  223. start1 := idx*numWeights
  224. start2 := (idx+1)*numWeights
  225. weights1 := mc.values[start1:start1+numWeights]
  226. weights2 := mc.values[start2:start2+numWeights]
  227. weightsNew := make([]float32, numWeights)
  228. for i := range weights1 {
  229. weightsNew[i] = weights1[i] + (weights2[i]-weights1[i])*k
  230. }
  231. mg.SetWeights(weightsNew)
  232. }
  233. case CUBICSPLINE: // TODO
  234. mc.interpAction = func(idx int, k float32) {
  235. start1 := idx*numWeights
  236. start2 := (idx+1)*numWeights
  237. weights1 := mc.values[start1:start1+numWeights]
  238. weights2 := mc.values[start2:start2+numWeights]
  239. weightsNew := make([]float32, numWeights)
  240. for i := range weights1 {
  241. weightsNew[i] = weights1[i] + (weights2[i]-weights1[i])*k
  242. }
  243. mg.SetWeights(weightsNew)
  244. }
  245. }
  246. }
  247. mc.SetInterpolationType(LINEAR)
  248. return mc
  249. }
  250. // InterpolationType specifies the interpolation type.
  251. type InterpolationType string
  252. // The various interpolation types.
  253. const (
  254. STEP = InterpolationType("STEP") // The animated values remain constant to the output of the first keyframe, until the next keyframe.
  255. LINEAR = InterpolationType("LINEAR") // The animated values are linearly interpolated between keyframes. Spherical linear interpolation (slerp) is used to interpolate quaternions.
  256. CUBICSPLINE = InterpolationType("CUBICSPLINE") // TODO
  257. )