animation.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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 collada
  5. import (
  6. "fmt"
  7. "github.com/g3n/engine/core"
  8. "github.com/g3n/engine/math32"
  9. "strings"
  10. )
  11. // AnimationTarget contains all animation channels for an specific target node
  12. type AnimationTarget struct {
  13. target core.INode
  14. matrix math32.Matrix4 // original node transformation matrix
  15. start float32 // initial input offset value
  16. last float32 // last input value
  17. minInput float32 // minimum input value for all channels
  18. maxInput float32 // maximum input value for all channels
  19. loop bool // animation loop flag
  20. rot math32.Vector3 // rotation in XYZ Euler angles
  21. channels []*ChannelInstance
  22. }
  23. // A ChannelInstance associates an animation parameter channel to an interpolation sampler
  24. type ChannelInstance struct {
  25. sampler *SamplerInstance
  26. action ActionFunc
  27. }
  28. // SamplerInstance specifies the input key frames, output values for these key frames
  29. // and interpolation information. It can be shared by more than one animation
  30. type SamplerInstance struct {
  31. Input []float32 // Input keys (usually time)
  32. Output []float32 // Outputs values for the keys
  33. Interp []string // Names of interpolation functions for each key frame
  34. InTangent []float32 // Origin tangents for Bezier interpolation
  35. OutTangent []float32 // End tangents for Bezier interpolation
  36. }
  37. // ActionFunc is the type for all functions that execute an specific parameter animation
  38. type ActionFunc func(at *AnimationTarget, v float32)
  39. // Reset resets the animation from the beginning
  40. func (at *AnimationTarget) Reset() {
  41. at.last = at.start
  42. at.target.GetNode().SetMatrix(&at.matrix)
  43. }
  44. // SetLoop sets the state of the animation loop flag
  45. func (at *AnimationTarget) SetLoop(loop bool) {
  46. at.loop = loop
  47. }
  48. // SetStart sets the initial offset value
  49. func (at *AnimationTarget) SetStart(v float32) {
  50. at.start = v
  51. }
  52. // Update interpolates the specified input value for each animation target channel
  53. // and executes its corresponding action function. Returns true if the input value
  54. // is inside the key frames ranges or false otherwise.
  55. func (at *AnimationTarget) Update(delta float32) bool {
  56. // Checks if input is less than minimum
  57. at.last = at.last + delta
  58. if at.last < at.minInput {
  59. return false
  60. }
  61. // Checks if input is greater than maximum
  62. if at.last > at.maxInput {
  63. if at.loop {
  64. at.Reset()
  65. } else {
  66. return false
  67. }
  68. }
  69. for i := 0; i < len(at.channels); i++ {
  70. ch := at.channels[i]
  71. // Get interpolated value
  72. v, ok := ch.sampler.Interpolate(at.last)
  73. if !ok {
  74. return false
  75. }
  76. // Call action func
  77. ch.action(at, v)
  78. // Sets final rotation
  79. at.target.GetNode().SetRotation(at.rot.X, at.rot.Y, at.rot.Z)
  80. }
  81. return true
  82. }
  83. // NewAnimationTargets creates and returns a map of all animation targets
  84. // contained in the decoded Collada document and for the previously decoded scene.
  85. // The map is indexed by the node loaderID.
  86. func (d *Decoder) NewAnimationTargets(scene core.INode) (map[string]*AnimationTarget, error) {
  87. if d.dom.LibraryAnimations == nil {
  88. return nil, fmt.Errorf("No animations found")
  89. }
  90. // Maps target node to its animation target instance
  91. targetsMap := make(map[string]*AnimationTarget)
  92. // For each Collada animation element
  93. for _, ca := range d.dom.LibraryAnimations.Animation {
  94. // For each Collada channel for this animation
  95. for _, cc := range ca.Channel {
  96. // Separates the channel target in target id and target action
  97. parts := strings.Split(cc.Target, "/")
  98. if len(parts) < 2 {
  99. return nil, fmt.Errorf("Channel target invalid")
  100. }
  101. targetID := parts[0]
  102. targetAction := parts[1]
  103. // Get the target node object referenced by the target id from the specified scene.
  104. target := scene.GetNode().FindLoaderID(targetID)
  105. if target == nil {
  106. return nil, fmt.Errorf("Target node id:%s not found", targetID)
  107. }
  108. // Get reference to the AnimationTarget for this target in the local map
  109. // If not found creates the animation target and inserts in the map
  110. at := targetsMap[targetID]
  111. if at == nil {
  112. at = new(AnimationTarget)
  113. at.target = target
  114. at.matrix = target.GetNode().Matrix()
  115. targetsMap[targetID] = at
  116. }
  117. // Creates the sampler instance specified from the channel source
  118. si, err := NewSamplerInstance(ca, cc.Source)
  119. if err != nil {
  120. return nil, err
  121. }
  122. // Sets the action function from the target action
  123. var af ActionFunc
  124. switch targetAction {
  125. case "location.X":
  126. af = actionPositionX
  127. case "location.Y":
  128. af = actionPositionY
  129. case "location.Z":
  130. af = actionPositionZ
  131. case "rotationX.ANGLE":
  132. af = actionRotationX
  133. case "rotationY.ANGLE":
  134. af = actionRotationY
  135. case "rotationZ.ANGLE":
  136. af = actionRotationZ
  137. case "scale.X":
  138. af = actionScaleX
  139. case "scale.Y":
  140. af = actionScaleY
  141. case "scale.Z":
  142. af = actionScaleZ
  143. default:
  144. return nil, fmt.Errorf("Unsupported channel target action:%s", targetAction)
  145. }
  146. // Creates the channel instance for this sampler and target action and adds it
  147. // to the current AnimationTarget
  148. ci := &ChannelInstance{si, af}
  149. at.channels = append(at.channels, ci)
  150. }
  151. }
  152. // Set minimum and maximum input values for each animation target
  153. for _, at := range targetsMap {
  154. at.minInput = math32.Infinity
  155. at.maxInput = -math32.Infinity
  156. for _, ch := range at.channels {
  157. // First key frame input
  158. inp := ch.sampler.Input[0]
  159. if inp < at.minInput {
  160. at.minInput = inp
  161. }
  162. // Last key frame input
  163. inp = ch.sampler.Input[len(ch.sampler.Input)-1]
  164. if inp > at.maxInput {
  165. at.maxInput = inp
  166. }
  167. }
  168. }
  169. return targetsMap, nil
  170. }
  171. func actionPositionX(at *AnimationTarget, v float32) {
  172. at.target.GetNode().SetPositionX(v)
  173. }
  174. func actionPositionY(at *AnimationTarget, v float32) {
  175. at.target.GetNode().SetPositionY(v)
  176. }
  177. func actionPositionZ(at *AnimationTarget, v float32) {
  178. at.target.GetNode().SetPositionZ(v)
  179. }
  180. func actionRotationX(at *AnimationTarget, v float32) {
  181. at.rot.X = math32.DegToRad(v)
  182. }
  183. func actionRotationY(at *AnimationTarget, v float32) {
  184. at.rot.Y = math32.DegToRad(v)
  185. }
  186. func actionRotationZ(at *AnimationTarget, v float32) {
  187. at.rot.Z = math32.DegToRad(v)
  188. }
  189. func actionScaleX(at *AnimationTarget, v float32) {
  190. at.target.GetNode().SetScaleX(v)
  191. }
  192. func actionScaleY(at *AnimationTarget, v float32) {
  193. at.target.GetNode().SetScaleY(v)
  194. }
  195. func actionScaleZ(at *AnimationTarget, v float32) {
  196. at.target.GetNode().SetScaleZ(v)
  197. }
  198. // NewSampler creates and returns a pointer to a new SamplerInstance built
  199. // with data from the specified Collada animation and URI
  200. func NewSamplerInstance(ca *Animation, uri string) (*SamplerInstance, error) {
  201. id := strings.TrimPrefix(uri, "#")
  202. var cs *Sampler
  203. for _, current := range ca.Sampler {
  204. if current.Id == id {
  205. cs = current
  206. break
  207. }
  208. }
  209. if cs == nil {
  210. return nil, fmt.Errorf("Sampler:%s not found", id)
  211. }
  212. // Get sampler inputs
  213. si := new(SamplerInstance)
  214. for _, inp := range cs.Input {
  215. if inp.Semantic == "INPUT" {
  216. data, err := findSourceFloatArray(ca, inp.Source)
  217. if err != nil {
  218. return nil, err
  219. }
  220. si.Input = data
  221. continue
  222. }
  223. if inp.Semantic == "OUTPUT" {
  224. data, err := findSourceFloatArray(ca, inp.Source)
  225. if err != nil {
  226. return nil, err
  227. }
  228. si.Output = data
  229. continue
  230. }
  231. if inp.Semantic == "INTERPOLATION" {
  232. data, err := findSourceNameArray(ca, inp.Source)
  233. if err != nil {
  234. return nil, err
  235. }
  236. si.Interp = data
  237. continue
  238. }
  239. if inp.Semantic == "IN_TANGENT" {
  240. data, err := findSourceFloatArray(ca, inp.Source)
  241. if err != nil {
  242. return nil, err
  243. }
  244. si.InTangent = data
  245. continue
  246. }
  247. if inp.Semantic == "OUT_TANGENT" {
  248. data, err := findSourceFloatArray(ca, inp.Source)
  249. if err != nil {
  250. return nil, err
  251. }
  252. si.OutTangent = data
  253. continue
  254. }
  255. }
  256. return si, nil
  257. }
  258. // Interpolate returns the interpolated output and its validity
  259. // for this sampler for the specified input.
  260. func (si *SamplerInstance) Interpolate(inp float32) (float32, bool) {
  261. // Test limits
  262. if len(si.Input) < 2 {
  263. return 0, false
  264. }
  265. if inp < si.Input[0] {
  266. return 0, false
  267. }
  268. if inp > si.Input[len(si.Input)-1] {
  269. return 0, false
  270. }
  271. // Find key frame interval
  272. var idx int
  273. for idx = 0; idx < len(si.Input)-1; idx++ {
  274. if inp >= si.Input[idx] && inp < si.Input[idx+1] {
  275. break
  276. }
  277. }
  278. // Checks if interval was found
  279. if idx >= len(si.Input)-1 {
  280. return 0, false
  281. }
  282. switch si.Interp[idx] {
  283. case "STEP":
  284. return si.linearInterp(inp, idx), true
  285. case "LINEAR":
  286. return si.linearInterp(inp, idx), true
  287. case "BEZIER":
  288. return si.bezierInterp(inp, idx), true
  289. case "HERMITE":
  290. return si.linearInterp(inp, idx), true
  291. case "CARDINAL":
  292. return si.linearInterp(inp, idx), true
  293. case "BSPLINE":
  294. return si.linearInterp(inp, idx), true
  295. default:
  296. return 0, false
  297. }
  298. return 0, false
  299. }
  300. func (si *SamplerInstance) linearInterp(inp float32, idx int) float32 {
  301. k1 := si.Input[idx]
  302. k2 := si.Input[idx+1]
  303. v1 := si.Output[idx]
  304. v2 := si.Output[idx+1]
  305. return v1 + (v2-v1)*(inp-k1)/(k2-k1)
  306. }
  307. func (si *SamplerInstance) bezierInterp(inp float32, idx int) float32 {
  308. p0 := si.Output[idx]
  309. p1 := si.Output[idx+1]
  310. c0 := si.OutTangent[2*idx+1]
  311. c1 := si.InTangent[2*(idx+1)+1]
  312. k1 := si.Input[idx]
  313. k2 := si.Input[idx+1]
  314. s := (inp - k1) / (k2 - k1)
  315. out := p0*math32.Pow(1-s, 3) + 3*c0*s*math32.Pow(1-s, 2) + 3*c1*s*s*(1-s) + p1*math32.Pow(s, 3)
  316. return out
  317. }
  318. func findSourceNameArray(ca *Animation, uri string) ([]string, error) {
  319. src := findSource(ca, uri)
  320. if src == nil {
  321. return nil, fmt.Errorf("Source:%s not found", uri)
  322. }
  323. na, ok := src.ArrayElement.(*NameArray)
  324. if !ok {
  325. return nil, fmt.Errorf("Source:%s is not NameArray", uri)
  326. }
  327. return na.Data, nil
  328. }
  329. func findSourceFloatArray(ca *Animation, uri string) ([]float32, error) {
  330. src := findSource(ca, uri)
  331. if src == nil {
  332. return nil, fmt.Errorf("Source:%s not found", uri)
  333. }
  334. fa, ok := src.ArrayElement.(*FloatArray)
  335. if !ok {
  336. return nil, fmt.Errorf("Source:%s is not FloatArray", uri)
  337. }
  338. return fa.Data, nil
  339. }
  340. func findSource(ca *Animation, uri string) *Source {
  341. id := strings.TrimPrefix(uri, "#")
  342. for _, src := range ca.Source {
  343. if src.Id == id {
  344. return src
  345. }
  346. }
  347. return nil
  348. }