PageRenderTime 28ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/lipsofsuna/model/model-pose.c

https://github.com/deldiablo/GodheadLips
C | 1357 lines | 1019 code | 165 blank | 173 comment | 214 complexity | 47d77e18f0c75b7048152a32b226f717 MD5 | raw file
  1. /* Lips of Suna
  2. * Copyright© 2007-2010 Lips of Suna development team.
  3. *
  4. * Lips of Suna is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as
  6. * published by the Free Software Foundation, either version 3 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * Lips of Suna is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with Lips of Suna. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /**
  18. * \addtogroup LIMdl Model
  19. * @{
  20. * \addtogroup LIMdlPose Pose
  21. * @{
  22. */
  23. #include <lipsofsuna/system.h>
  24. #include "model-pose.h"
  25. static void private_channel_free (
  26. LIMdlPoseChannel* chan);
  27. static void private_clear_node (
  28. LIMdlPose* self,
  29. LIMdlNode* node,
  30. const LIMdlNode* rest);
  31. static void private_clear_pose (
  32. LIMdlPose* self);
  33. static LIMdlPoseChannel* private_create_channel (
  34. LIMdlPose* self,
  35. int channel);
  36. static void private_fade_free (
  37. LIMdlPoseFade* fade);
  38. static void private_fade_remove (
  39. LIMdlPose* self,
  40. LIMdlPoseFade* fade);
  41. static LIMdlPoseChannel* private_find_channel (
  42. const LIMdlPose* self,
  43. int channel);
  44. static int private_init_pose (
  45. LIMdlPose* self,
  46. LIMdlModel* model);
  47. static int private_play_channel (
  48. const LIMdlPose* self,
  49. LIMdlPoseChannel* channel,
  50. float secs);
  51. static void private_transform_node (
  52. LIMdlPose* self,
  53. LIMdlNode* node);
  54. static void private_get_channel_weight (
  55. const LIMdlPose* self,
  56. const LIMdlPoseChannel* channel,
  57. const LIMdlNode* node,
  58. float* scale,
  59. float* transform);
  60. static float private_smooth_fade (
  61. float channel_weight,
  62. float fade_offset,
  63. float fade_length);
  64. static LIMdlAnimation private_empty_anim =
  65. {
  66. 0, "empty", 0.0f, 0.0f, { 0, NULL }, { 0, NULL }
  67. };
  68. /*****************************************************************************/
  69. /**
  70. * \brief Creates a new model pose.
  71. * \return New model pose or NULL.
  72. */
  73. LIMdlPose* limdl_pose_new ()
  74. {
  75. LIMdlPose* self;
  76. /* Allocate self. */
  77. self = lisys_calloc (1, sizeof (LIMdlPose));
  78. if (self == NULL)
  79. return NULL;
  80. /* Allocate channel tree. */
  81. self->channels = lialg_u32dic_new ();
  82. if (self->channels == NULL)
  83. {
  84. limdl_pose_free (self);
  85. return NULL;
  86. }
  87. return self;
  88. }
  89. /**
  90. * \brief Frees the model pose.
  91. * \param self A model pose.
  92. */
  93. void limdl_pose_free (
  94. LIMdlPose* self)
  95. {
  96. private_clear_pose (self);
  97. if (self->channels != NULL)
  98. lialg_u32dic_free (self->channels);
  99. lisys_free (self);
  100. }
  101. void limdl_pose_clear_channel_node_priorities (
  102. LIMdlPose* self,
  103. int channel)
  104. {
  105. LIAlgStrdicIter iter;
  106. LIMdlPoseChannel* chan;
  107. chan = lialg_u32dic_find (self->channels, channel);
  108. if (chan == NULL || chan->weights == NULL)
  109. return;
  110. LIALG_STRDIC_FOREACH (iter, chan->weights)
  111. lisys_free (iter.value);
  112. lialg_strdic_free (chan->weights);
  113. chan->weights = NULL;
  114. }
  115. /**
  116. * \brief Destroys an animation channel.
  117. *
  118. * Channels are destroyed automatically with the pose but it's also possible to
  119. * destroy a channel explicitly with this function.
  120. *
  121. * \param self Model pose.
  122. * \param channel Channel number.
  123. */
  124. void limdl_pose_destroy_channel (
  125. LIMdlPose* self,
  126. int channel)
  127. {
  128. LIMdlPoseChannel* chan;
  129. chan = lialg_u32dic_find (self->channels, channel);
  130. if (chan == NULL)
  131. return;
  132. lialg_u32dic_remove (self->channels, channel);
  133. private_channel_free (chan);
  134. }
  135. /**
  136. * \brief Fades out the channel.
  137. *
  138. * If an animation is playing or paused on the channel, a new fade sequence
  139. * is created and played seamlessly in the background. The channel cleared
  140. * and immediately ready to accept a new animation.
  141. *
  142. * If the channel is empty, no fading takes place, so it is safe to call this
  143. * function every time you set a new animation and want it to blend.
  144. *
  145. * \param self Model pose.
  146. * \param channel Channel number.
  147. * \param secs Fade out time in seconds or LIMDL_POSE_FADE_AUTOMATIC.
  148. */
  149. void limdl_pose_fade_channel (
  150. LIMdlPose* self,
  151. int channel,
  152. float secs)
  153. {
  154. LIMdlPoseFade* fade;
  155. LIMdlPoseChannel* chan;
  156. chan = lialg_u32dic_find (self->channels, channel);
  157. if (chan == NULL)
  158. return;
  159. /* Handle auto rate. */
  160. if (secs == LIMDL_POSE_FADE_AUTOMATIC)
  161. {
  162. if (chan->fade_out < LIMAT_EPSILON)
  163. return;
  164. secs = chan->fade_out;
  165. }
  166. /* Create a fade sequence. */
  167. fade = lisys_calloc (1, sizeof (LIMdlPoseFade));
  168. if (fade == NULL)
  169. {
  170. limdl_pose_destroy_channel (self, channel);
  171. return;
  172. }
  173. private_get_channel_weight (self, chan, NULL, &fade->priority_scale, &fade->priority_transform);
  174. fade->fade_out = secs;
  175. fade->time = chan->time;
  176. fade->time_fade = 0.0f;
  177. fade->current_weight_transform = fade->priority_transform;
  178. fade->current_weight_scale = fade->priority_scale;
  179. fade->animation = limdl_animation_new_copy (chan->animation);
  180. if (fade->animation == NULL)
  181. {
  182. limdl_pose_destroy_channel (self, channel);
  183. lisys_free (fade);
  184. return;
  185. }
  186. /* Link to fade list. */
  187. fade->prev = NULL;
  188. fade->next = self->fades;
  189. if (self->fades != NULL)
  190. self->fades->prev = fade;
  191. self->fades = fade;
  192. /* Destroy the channel. */
  193. limdl_pose_destroy_channel (self, channel);
  194. }
  195. /**
  196. * \brief Finds a node by name.
  197. *
  198. * \param self Model pose.
  199. * \param name Name of the node to find.
  200. * \return Node or NULL.
  201. */
  202. LIMdlNode* limdl_pose_find_node (
  203. const LIMdlPose* self,
  204. const char* name)
  205. {
  206. int i;
  207. LIMdlNode* node;
  208. if (self->model == NULL)
  209. return NULL;
  210. for (i = 0 ; i < self->nodes.count ; i++)
  211. {
  212. node = self->nodes.array[i];
  213. node = limdl_node_find_node (node, name);
  214. if (node != NULL)
  215. return node;
  216. }
  217. return NULL;
  218. }
  219. /**
  220. * \brief Progresses the animation.
  221. *
  222. * \param self Model pose.
  223. * \param secs Number of seconds to progress.
  224. */
  225. void limdl_pose_update (
  226. LIMdlPose* self,
  227. float secs)
  228. {
  229. int i;
  230. LIAlgU32dicIter iter;
  231. LIMatQuaternion quat0;
  232. LIMatQuaternion quat1;
  233. LIMdlPoseFade* fade;
  234. LIMdlPoseFade* fade_next;
  235. LIMdlPoseChannel* chan;
  236. LIMdlPoseGroup* group;
  237. LIMdlNode* node0;
  238. LIMdlNode* node1;
  239. if (self->model == NULL)
  240. return;
  241. /* Update channels. */
  242. LIALG_U32DIC_FOREACH (iter, self->channels)
  243. {
  244. chan = iter.value;
  245. switch (chan->state)
  246. {
  247. case LIMDL_POSE_CHANNEL_STATE_PAUSED:
  248. break;
  249. case LIMDL_POSE_CHANNEL_STATE_PLAYING:
  250. if (!private_play_channel (self, chan, secs))
  251. {
  252. lialg_u32dic_remove (self->channels, iter.key);
  253. private_channel_free (chan);
  254. }
  255. break;
  256. }
  257. }
  258. /* Update fade sequences. */
  259. for (fade = self->fades ; fade != NULL ; fade = fade_next)
  260. {
  261. /* Calculate smooth fading. */
  262. fade->current_weight_scale = private_smooth_fade (
  263. fade->priority_scale, fade->time_fade, fade->fade_out);
  264. fade->current_weight_transform = private_smooth_fade (
  265. fade->priority_transform, fade->time_fade, fade->fade_out);
  266. /* Update time and weights. */
  267. fade_next = fade->next;
  268. fade->time += secs;
  269. fade->time_fade += secs;
  270. /* Remove the fade when its influence reaches zero. */
  271. if (fade->time_fade >= fade->fade_out)
  272. {
  273. private_fade_remove (self, fade);
  274. private_fade_free (fade);
  275. }
  276. }
  277. /* Clear each node. */
  278. for (i = 0 ; i < self->nodes.count ; i++)
  279. {
  280. node0 = self->nodes.array[i];
  281. node1 = self->model->nodes.array[i];
  282. private_clear_node (self, node0, node1);
  283. }
  284. /* Transform each node. */
  285. for (i = 0 ; i < self->nodes.count ; i++)
  286. {
  287. node0 = self->nodes.array[i];
  288. private_transform_node (self, node0);
  289. }
  290. /* Update pose group transformations. */
  291. for (i = 0 ; i < self->groups.count ; i++)
  292. {
  293. group = self->groups.array + i;
  294. if (group->enabled)
  295. {
  296. quat0 = group->rest_node->transform.global.rotation;
  297. quat1 = group->pose_node->transform.global.rotation;
  298. quat0 = limat_quaternion_conjugate (quat0);
  299. group->rotation = limat_quaternion_multiply (quat1, quat0);
  300. group->head_pose = group->pose_node->transform.global.position;
  301. group->scale_pose = group->pose_node->transform.global_scale;
  302. }
  303. else
  304. {
  305. group->rotation = limat_quaternion_identity ();
  306. group->head_pose = limat_vector_init (0.0f, 0.0f, 0.0f);
  307. group->scale_pose = 1.0f;
  308. }
  309. }
  310. }
  311. int limdl_pose_get_channel_additive (
  312. const LIMdlPose* self,
  313. int channel)
  314. {
  315. LIMdlPoseChannel* chan;
  316. chan = private_find_channel (self, channel);
  317. if (chan == NULL)
  318. return 0;
  319. return chan->additive;
  320. }
  321. void limdl_pose_set_channel_additive (
  322. LIMdlPose* self,
  323. int channel,
  324. int value)
  325. {
  326. LIMdlPoseChannel* chan;
  327. chan = private_create_channel (self, channel);
  328. if (chan == NULL)
  329. return;
  330. chan->additive = value;
  331. }
  332. LIMdlAnimation* limdl_pose_get_channel_animation (
  333. const LIMdlPose* self,
  334. int channel)
  335. {
  336. LIMdlPoseChannel* chan;
  337. chan = private_find_channel (self, channel);
  338. if (chan == NULL)
  339. return NULL;
  340. return chan->animation;
  341. }
  342. void limdl_pose_set_channel_animation (
  343. LIMdlPose* self,
  344. int channel,
  345. const char* animation)
  346. {
  347. LIMdlAnimation* anim;
  348. LIMdlPoseChannel* chan;
  349. if (self->model == NULL)
  350. return;
  351. /* Create an animation. */
  352. anim = limdl_model_find_animation (self->model, animation);
  353. if (anim == NULL)
  354. {
  355. limdl_pose_destroy_channel (self, channel);
  356. return;
  357. }
  358. anim = limdl_animation_new_copy (anim);
  359. if (anim == NULL)
  360. return;
  361. /* Create a channel. */
  362. chan = private_create_channel (self, channel);
  363. if (chan == NULL)
  364. {
  365. limdl_animation_free (anim);
  366. return;
  367. }
  368. chan->time = 0.0f;
  369. chan->fade_in = 0.0f;
  370. chan->fade_out = 0.0f;
  371. limdl_animation_free (chan->animation);
  372. chan->animation = anim;
  373. }
  374. int limdl_pose_get_channel_repeat_start (
  375. const LIMdlPose* self,
  376. int channel)
  377. {
  378. LIMdlPoseChannel* chan;
  379. chan = private_find_channel (self, channel);
  380. if (chan == NULL)
  381. return 0;
  382. return chan->repeat_start;
  383. }
  384. void limdl_pose_set_channel_repeat_start (
  385. LIMdlPose* self,
  386. int channel,
  387. int value)
  388. {
  389. LIMdlPoseChannel* chan;
  390. chan = private_create_channel (self, channel);
  391. if (chan == NULL)
  392. return;
  393. chan->repeat_start = value;
  394. }
  395. float limdl_pose_get_channel_fade_in (
  396. LIMdlPose* self,
  397. int channel)
  398. {
  399. LIMdlPoseChannel* chan;
  400. chan = private_find_channel (self, channel);
  401. if (chan == NULL)
  402. return 0.0f;
  403. return chan->fade_in;
  404. }
  405. void limdl_pose_set_channel_fade_in (
  406. LIMdlPose* self,
  407. int channel,
  408. float value)
  409. {
  410. LIMdlPoseChannel* chan;
  411. chan = private_find_channel (self, channel);
  412. if (chan != NULL)
  413. chan->fade_in = value;
  414. }
  415. float limdl_pose_get_channel_fade_out (
  416. LIMdlPose* self,
  417. int channel)
  418. {
  419. LIMdlPoseChannel* chan;
  420. chan = private_find_channel (self, channel);
  421. if (chan == NULL)
  422. return 0.0f;
  423. return chan->fade_out;
  424. }
  425. void limdl_pose_set_channel_fade_out (
  426. LIMdlPose* self,
  427. int channel,
  428. float value)
  429. {
  430. LIMdlPoseChannel* chan;
  431. chan = private_find_channel (self, channel);
  432. if (chan != NULL)
  433. chan->fade_out = value;
  434. }
  435. const char* limdl_pose_get_channel_name (
  436. const LIMdlPose* self,
  437. int channel)
  438. {
  439. LIMdlPoseChannel* chan;
  440. chan = private_find_channel (self, channel);
  441. if (chan == NULL)
  442. return "";
  443. return chan->animation->name;
  444. }
  445. float limdl_pose_get_channel_position (
  446. const LIMdlPose* self,
  447. int channel)
  448. {
  449. LIMdlPoseChannel* chan;
  450. chan = private_find_channel (self, channel);
  451. if (chan == NULL)
  452. return 0.0f;
  453. return chan->time;
  454. }
  455. void limdl_pose_set_channel_position (
  456. LIMdlPose* self,
  457. int channel,
  458. float value)
  459. {
  460. LIMdlPoseChannel* chan;
  461. chan = private_create_channel (self, channel);
  462. if (chan == NULL)
  463. return;
  464. chan->time = value;
  465. if (chan->time > limdl_animation_get_duration (chan->animation))
  466. chan->time = limdl_animation_get_duration (chan->animation);
  467. }
  468. float* limdl_pose_get_channel_priority_node (
  469. const LIMdlPose* self,
  470. int channel,
  471. const char* node)
  472. {
  473. float* ptr;
  474. LIMdlPoseChannel* chan;
  475. chan = private_find_channel (self, channel);
  476. if (chan == NULL || chan->weights == NULL)
  477. return NULL;
  478. ptr = lialg_strdic_find (chan->weights, node);
  479. return ptr;
  480. }
  481. int limdl_pose_set_channel_priority_node (
  482. LIMdlPose* self,
  483. int channel,
  484. const char* node,
  485. float value)
  486. {
  487. float* ptr;
  488. LIMdlPoseChannel* chan;
  489. /* Find the channel. */
  490. chan = private_find_channel (self, channel);
  491. if (chan == NULL)
  492. return 0;
  493. /* Make sure the node weight dictionary exists. */
  494. if (chan->weights == NULL)
  495. {
  496. chan->weights = lialg_strdic_new ();
  497. if (chan->weights == NULL)
  498. return 0;
  499. }
  500. /* Replace or add a node weight. */
  501. ptr = lialg_strdic_find (chan->weights, node);
  502. if (ptr == NULL)
  503. {
  504. ptr = lisys_calloc (1, sizeof (float));
  505. if (ptr == NULL)
  506. return 0;
  507. if (!lialg_strdic_insert (chan->weights, node, ptr))
  508. {
  509. lisys_free (ptr);
  510. return 0;
  511. }
  512. }
  513. *ptr = value;
  514. return 1;
  515. }
  516. LIAlgStrdic* limdl_pose_get_channel_priority_nodes (
  517. const LIMdlPose* self,
  518. int channel)
  519. {
  520. LIMdlPoseChannel* chan;
  521. chan = private_find_channel (self, channel);
  522. if (chan == NULL)
  523. return NULL;
  524. return chan->weights;
  525. }
  526. float limdl_pose_get_channel_priority_scale (
  527. const LIMdlPose* self,
  528. int channel)
  529. {
  530. LIMdlPoseChannel* chan;
  531. chan = private_find_channel (self, channel);
  532. if (chan == NULL)
  533. return 0.0f;
  534. return chan->priority_scale;
  535. }
  536. void limdl_pose_set_channel_priority_scale (
  537. LIMdlPose* self,
  538. int channel,
  539. float value)
  540. {
  541. LIMdlPoseChannel* chan;
  542. chan = private_create_channel (self, channel);
  543. if (chan == NULL)
  544. return;
  545. chan->priority_scale = value;
  546. }
  547. float limdl_pose_get_channel_priority_transform (
  548. const LIMdlPose* self,
  549. int channel)
  550. {
  551. LIMdlPoseChannel* chan;
  552. chan = private_find_channel (self, channel);
  553. if (chan == NULL)
  554. return 0.0f;
  555. return chan->priority_transform;
  556. }
  557. void limdl_pose_set_channel_priority_transform (
  558. LIMdlPose* self,
  559. int channel,
  560. float value)
  561. {
  562. LIMdlPoseChannel* chan;
  563. chan = private_create_channel (self, channel);
  564. if (chan == NULL)
  565. return;
  566. chan->priority_transform = value;
  567. }
  568. int limdl_pose_get_channel_repeats (
  569. const LIMdlPose* self,
  570. int channel)
  571. {
  572. LIMdlPoseChannel* chan;
  573. chan = private_find_channel (self, channel);
  574. if (chan == NULL)
  575. return 0;
  576. return chan->repeats;
  577. }
  578. void limdl_pose_set_channel_repeats (
  579. LIMdlPose* self,
  580. int channel,
  581. int value)
  582. {
  583. LIMdlPoseChannel* chan;
  584. chan = private_create_channel (self, channel);
  585. if (chan == NULL)
  586. return;
  587. chan->repeats = value;
  588. }
  589. /**
  590. * \brief Gets the state of a channel.
  591. *
  592. * \param self Model pose.
  593. * \param channel Channel number.
  594. * \return Current state.
  595. */
  596. LIMdlPoseChannelState limdl_pose_get_channel_state (
  597. const LIMdlPose* self,
  598. int channel)
  599. {
  600. LIMdlPoseChannel* chan;
  601. chan = private_find_channel (self, channel);
  602. if (chan == NULL)
  603. return LIMDL_POSE_CHANNEL_STATE_INVALID;
  604. return chan->state;
  605. }
  606. /**
  607. * \brief Sets the state of a channel.
  608. *
  609. * \param self Model pose.
  610. * \param channel Channel number.
  611. * \param value New state.
  612. */
  613. void limdl_pose_set_channel_state (
  614. LIMdlPose* self,
  615. int channel,
  616. LIMdlPoseChannelState value)
  617. {
  618. LIMdlPoseChannel* chan;
  619. chan = private_create_channel (self, channel);
  620. if (chan == NULL || chan->state == value)
  621. return;
  622. switch (value)
  623. {
  624. case LIMDL_POSE_CHANNEL_STATE_PLAYING:
  625. chan->state = value;
  626. break;
  627. case LIMDL_POSE_CHANNEL_STATE_PAUSED:
  628. chan->state = value;
  629. break;
  630. default:
  631. lisys_assert (0);
  632. break;
  633. }
  634. }
  635. float limdl_pose_get_channel_time_scale (
  636. const LIMdlPose* self,
  637. int channel)
  638. {
  639. LIMdlPoseChannel* chan;
  640. chan = private_find_channel (self, channel);
  641. if (chan == NULL)
  642. return 0;
  643. return chan->time_scale;
  644. }
  645. void limdl_pose_set_channel_time_scale (
  646. LIMdlPose* self,
  647. int channel,
  648. float value)
  649. {
  650. LIMdlPoseChannel* chan;
  651. chan = private_create_channel (self, channel);
  652. if (chan == NULL)
  653. return;
  654. chan->time_scale = value;
  655. }
  656. /**
  657. * \brief Sets the transformation of a node for the given frame.
  658. * \param self Pose.
  659. * \param channel Channel number.
  660. * \param frame Frame number.
  661. * \param node Node name.
  662. * \param scale Scale factor.
  663. * \param transform Node transformation.
  664. * \return Nonzero on success.
  665. */
  666. int limdl_pose_set_channel_transform (
  667. LIMdlPose* self,
  668. int channel,
  669. int frame,
  670. const char* node,
  671. float scale,
  672. const LIMatTransform* transform)
  673. {
  674. LIMdlNode* node_;
  675. LIMdlPoseChannel* chan;
  676. /* Find the node. */
  677. node_ = limdl_pose_find_node (self, node);
  678. if (node_ == NULL)
  679. return 0;
  680. /* Find the channel. */
  681. chan = private_find_channel (self, channel);
  682. if (chan == NULL)
  683. return 0;
  684. /* Make sure the channel and the frame exist. */
  685. if (!limdl_animation_insert_channel (chan->animation, node))
  686. return 0;
  687. if (chan->animation->length <= frame)
  688. {
  689. if (!limdl_animation_set_length (chan->animation, frame + 1))
  690. return 0;
  691. }
  692. /* Set the node transformation of the frame. */
  693. limdl_animation_set_transform (chan->animation, node, frame, scale, transform);
  694. return 1;
  695. }
  696. /**
  697. * \brief Sets the posed model.
  698. *
  699. * \param self Model pose.
  700. * \param model Model to pose.
  701. * \return Nonzero on success.
  702. */
  703. int limdl_pose_set_model (
  704. LIMdlPose* self,
  705. LIMdlModel* model)
  706. {
  707. LIAlgU32dicIter iter;
  708. LIMdlAnimation* anim;
  709. LIMdlPose backup;
  710. LIMdlPoseChannel* chan;
  711. LIMdlPoseFade* fade;
  712. LIMdlPoseFade* fade_next;
  713. /* Backup old data. */
  714. memcpy (&backup, self, sizeof (LIMdlPose));
  715. self->channels = NULL;
  716. self->fades = NULL;
  717. self->model = NULL;
  718. self->groups.count = 0;
  719. self->groups.array = NULL;
  720. self->nodes.count = 0;
  721. self->nodes.array = NULL;
  722. /* Initialize new pose. */
  723. if (model != NULL)
  724. {
  725. if (!private_init_pose (self, model))
  726. {
  727. private_clear_pose (self);
  728. memcpy (self, &backup, sizeof (LIMdlPose));
  729. return 0;
  730. }
  731. }
  732. /* Clear invalid animations. */
  733. self->channels = backup.channels;
  734. backup.channels = NULL;
  735. LIALG_U32DIC_FOREACH (iter, self->channels)
  736. {
  737. chan = iter.value;
  738. if (model != NULL)
  739. {
  740. anim = limdl_model_find_animation (model, chan->animation->name);
  741. if (anim != NULL)
  742. anim = limdl_animation_new_copy (anim);
  743. }
  744. else
  745. anim = NULL;
  746. if (anim != NULL)
  747. {
  748. limdl_animation_free (chan->animation);
  749. chan->animation = anim;
  750. }
  751. else
  752. {
  753. lialg_u32dic_remove (self->channels, iter.key);
  754. private_channel_free (chan);
  755. }
  756. }
  757. /* Clear invalid fades. */
  758. self->fades = backup.fades;
  759. backup.fades = NULL;
  760. for (fade = self->fades ; fade != NULL ; fade = fade_next)
  761. {
  762. fade_next = fade->next;
  763. if (model != NULL)
  764. anim = limdl_model_find_animation (model, fade->animation->name);
  765. else
  766. anim = NULL;
  767. if (anim == NULL)
  768. {
  769. private_fade_remove (self, fade);
  770. private_fade_free (fade);
  771. }
  772. }
  773. /* Clear old data. */
  774. private_clear_pose (&backup);
  775. /* Rebuild pose channels. */
  776. limdl_pose_update (self, 0.0f);
  777. return 1;
  778. }
  779. /*****************************************************************************/
  780. static void private_channel_free (
  781. LIMdlPoseChannel* chan)
  782. {
  783. LIAlgStrdicIter iter;
  784. limdl_animation_free (chan->animation);
  785. if (chan->weights)
  786. {
  787. LIALG_STRDIC_FOREACH (iter, chan->weights)
  788. lisys_free (iter.value);
  789. lialg_strdic_free (chan->weights);
  790. }
  791. lisys_free (chan);
  792. }
  793. static void private_clear_node (
  794. LIMdlPose* self,
  795. LIMdlNode* node,
  796. const LIMdlNode* rest)
  797. {
  798. int i;
  799. LIMdlNode* node0;
  800. LIMdlNode* node1;
  801. node->transform.global = rest->transform.global;
  802. for (i = 0 ; i < node->nodes.count ; i++)
  803. {
  804. node0 = node->nodes.array[i];
  805. node1 = rest->nodes.array[i];
  806. private_clear_node (self, node0, node1);
  807. }
  808. }
  809. static void private_clear_pose (
  810. LIMdlPose* self)
  811. {
  812. int i;
  813. LIAlgU32dicIter iter;
  814. LIMdlPoseFade* fade;
  815. LIMdlPoseFade* fade_next;
  816. /* Free fades. */
  817. for (fade = self->fades ; fade != NULL ; fade = fade_next)
  818. {
  819. fade_next = fade->next;
  820. private_fade_free (fade);
  821. }
  822. self->fades = NULL;
  823. /* Clear channel tree. */
  824. if (self->channels != NULL)
  825. {
  826. LIALG_U32DIC_FOREACH (iter, self->channels)
  827. private_channel_free (iter.value);
  828. lialg_u32dic_clear (self->channels);
  829. }
  830. /* Free nodes. */
  831. if (self->nodes.array != NULL)
  832. {
  833. for (i = 0 ; i < self->nodes.count ; i++)
  834. {
  835. if (self->nodes.array[i] != NULL)
  836. limdl_node_free (self->nodes.array[i]);
  837. }
  838. lisys_free (self->nodes.array);
  839. }
  840. lisys_free (self->groups.array);
  841. }
  842. static LIMdlPoseChannel* private_create_channel (
  843. LIMdlPose* self,
  844. int channel)
  845. {
  846. LIMdlAnimation* anim;
  847. LIMdlPoseChannel* chan;
  848. /* Check for an existing channel. */
  849. chan = private_find_channel (self, channel);
  850. if (chan != NULL)
  851. return chan;
  852. /* Create an empty animation. */
  853. anim = limdl_animation_new_copy (&private_empty_anim);
  854. if (anim == NULL)
  855. return 0;
  856. /* Create a new channel. */
  857. chan = lisys_calloc (1, sizeof (LIMdlPoseChannel));
  858. if (chan == NULL)
  859. {
  860. limdl_animation_free (anim);
  861. return 0;
  862. }
  863. chan->state = LIMDL_POSE_CHANNEL_STATE_PLAYING;
  864. chan->animation = anim;
  865. chan->priority_scale = 0.0f;
  866. chan->priority_transform = 1.0f;
  867. chan->time_scale = 1.0f;
  868. /* Register the channel. */
  869. if (!lialg_u32dic_insert (self->channels, channel, chan))
  870. {
  871. limdl_animation_free (chan->animation);
  872. lisys_free (chan);
  873. return 0;
  874. }
  875. return chan;
  876. }
  877. static void private_fade_free (
  878. LIMdlPoseFade* fade)
  879. {
  880. limdl_animation_free (fade->animation);
  881. lisys_free (fade);
  882. }
  883. static void private_fade_remove (
  884. LIMdlPose* self,
  885. LIMdlPoseFade* fade)
  886. {
  887. if (fade->next != NULL)
  888. fade->next->prev = fade->prev;
  889. if (fade->prev != NULL)
  890. fade->prev->next = fade->next;
  891. else
  892. self->fades = fade->next;
  893. }
  894. static LIMdlPoseChannel* private_find_channel (
  895. const LIMdlPose* self,
  896. int channel)
  897. {
  898. return lialg_u32dic_find (self->channels, channel);
  899. }
  900. static int private_init_pose (
  901. LIMdlPose* self,
  902. LIMdlModel* model)
  903. {
  904. int i;
  905. LIMdlPoseGroup* pose_group;
  906. LIMdlWeightGroup* weight_group;
  907. /* Set model. */
  908. self->model = model;
  909. self->groups.count = model->weight_groups.count;
  910. self->nodes.count = model->nodes.count;
  911. /* Copy nodes. */
  912. if (self->nodes.count)
  913. {
  914. self->nodes.array = lisys_calloc (self->nodes.count, sizeof (LIMdlNode*));
  915. if (self->nodes.array == NULL)
  916. return 0;
  917. for (i = 0 ; i < self->nodes.count ; i++)
  918. {
  919. self->nodes.array[i] = limdl_node_copy (model->nodes.array[i]);
  920. if (self->nodes.array[i] == NULL)
  921. return 0;
  922. }
  923. }
  924. /* Precalculate weight group information. */
  925. if (self->groups.count)
  926. {
  927. self->groups.array = lisys_calloc (self->groups.count, sizeof (LIMdlPoseGroup));
  928. if (self->groups.array == NULL)
  929. return 0;
  930. for (i = 0 ; i < self->groups.count ; i++)
  931. {
  932. weight_group = model->weight_groups.array + i;
  933. pose_group = self->groups.array + i;
  934. pose_group->weight_group = weight_group;
  935. pose_group->rest_node = weight_group->node;
  936. pose_group->pose_node = limdl_pose_find_node (self, weight_group->bone);
  937. pose_group->rotation = limat_quaternion_identity ();
  938. if (pose_group->rest_node != NULL)
  939. pose_group->head_rest = pose_group->rest_node->transform.global.position;
  940. if (pose_group->rest_node != NULL && pose_group->pose_node != NULL)
  941. pose_group->enabled = 1;
  942. }
  943. }
  944. return 1;
  945. }
  946. static int private_play_channel (
  947. const LIMdlPose* self,
  948. LIMdlPoseChannel* channel,
  949. float secs)
  950. {
  951. int cycles;
  952. float duration;
  953. float start;
  954. /* Skip empty. */
  955. duration = limdl_animation_get_duration (channel->animation);
  956. if (duration < LIMAT_EPSILON)
  957. {
  958. channel->time = 0.0f;
  959. if (channel->repeats == -1)
  960. return 1;
  961. return 0;
  962. }
  963. /* Advance time. */
  964. channel->time += channel->time_scale * secs;
  965. /* Handle looping. */
  966. if (channel->time > duration)
  967. {
  968. start = LIMAT_CLAMP (channel->repeat_start, 0.0f, duration);
  969. if (start < duration)
  970. {
  971. cycles = (int) floor ((channel->time - start) / (duration - start));
  972. channel->time = channel->time - (duration - start) * cycles;
  973. channel->repeat += cycles;
  974. }
  975. else
  976. {
  977. channel->time = duration;
  978. channel->repeat++;
  979. }
  980. }
  981. /* Handle ending. */
  982. if (channel->repeats != -1 && channel->repeat >= channel->repeats)
  983. return 0;
  984. return 1;
  985. }
  986. static void private_transform_node (
  987. LIMdlPose* self,
  988. LIMdlNode* node)
  989. {
  990. int i;
  991. int channels;
  992. float scale;
  993. float scale1;
  994. float total_scale;
  995. float total_transform;
  996. float weight;
  997. float weight1;
  998. LIAlgU32dicIter iter;
  999. LIMatQuaternion bonerot;
  1000. LIMatQuaternion rotation;
  1001. LIMatTransform transform;
  1002. LIMatVector bonepos;
  1003. LIMatVector position;
  1004. LIMdlPoseFade* fade;
  1005. LIMdlPoseChannel* chan;
  1006. channels = 0;
  1007. scale = 0.0f;
  1008. total_scale = 0.0f;
  1009. total_transform = 0.0f;
  1010. position = limat_vector_init (0.0f, 0.0f, 0.0f);
  1011. rotation = limat_quaternion_init (0.0f, 0.0f, 0.0f, 1.0f);
  1012. /* Sum channel weights. */
  1013. LIALG_U32DIC_FOREACH (iter, self->channels)
  1014. {
  1015. chan = iter.value;
  1016. if (chan->additive)
  1017. continue;
  1018. if (limdl_animation_get_channel (chan->animation, node->name) != -1)
  1019. {
  1020. private_get_channel_weight (self, chan, node, &weight, &weight1);
  1021. total_scale += weight;
  1022. total_transform += weight1;
  1023. channels++;
  1024. }
  1025. }
  1026. /* Sum fade weights. */
  1027. for (fade = self->fades ; fade != NULL ; fade = fade->next)
  1028. {
  1029. if (limdl_animation_get_channel (fade->animation, node->name) != -1)
  1030. {
  1031. total_transform += fade->current_weight_transform;
  1032. total_scale += fade->current_weight_scale;
  1033. channels++;
  1034. }
  1035. }
  1036. /* Apply valid transformation influences. */
  1037. if (channels && total_transform >= LIMAT_EPSILON)
  1038. {
  1039. /* Apply channel influences. */
  1040. LIALG_U32DIC_FOREACH (iter, self->channels)
  1041. {
  1042. chan = iter.value;
  1043. if (chan->additive)
  1044. continue;
  1045. if (limdl_animation_get_transform (chan->animation, node->name, chan->time, &scale1, &transform))
  1046. {
  1047. bonepos = transform.position;
  1048. bonerot = transform.rotation;
  1049. private_get_channel_weight (self, chan, node, &weight1, &weight);
  1050. rotation = limat_quaternion_nlerp (bonerot, rotation, weight / total_transform);
  1051. position = limat_vector_lerp (bonepos, position, weight / total_transform);
  1052. }
  1053. }
  1054. /* Apply fade influences. */
  1055. for (fade = self->fades ; fade != NULL ; fade = fade->next)
  1056. {
  1057. if (limdl_animation_get_transform (fade->animation, node->name, fade->time, &scale1, &transform))
  1058. {
  1059. bonepos = transform.position;
  1060. bonerot = transform.rotation;
  1061. weight = fade->current_weight_transform;
  1062. rotation = limat_quaternion_nlerp (bonerot, rotation, weight / total_transform);
  1063. position = limat_vector_lerp (bonepos, position, weight / total_transform);
  1064. }
  1065. }
  1066. }
  1067. /* Apply valid scale influences. */
  1068. if (channels && total_scale >= LIMAT_EPSILON)
  1069. {
  1070. /* Apply channel influences. */
  1071. LIALG_U32DIC_FOREACH (iter, self->channels)
  1072. {
  1073. chan = iter.value;
  1074. if (limdl_animation_get_transform (chan->animation, node->name, chan->time, &scale1, &transform))
  1075. {
  1076. private_get_channel_weight (self, chan, node, &weight, &weight1);
  1077. scale += scale1 * weight / total_scale;
  1078. }
  1079. }
  1080. /* Apply fade influences. */
  1081. for (fade = self->fades ; fade != NULL ; fade = fade->next)
  1082. {
  1083. if (limdl_animation_get_transform (fade->animation, node->name, fade->time, &scale1, &transform))
  1084. {
  1085. weight = fade->current_weight_scale;
  1086. scale += scale1 * weight / total_scale;
  1087. }
  1088. }
  1089. }
  1090. else
  1091. scale = 1.0f;
  1092. /* Apply additive transformations and scaling. */
  1093. /* Additive channels aren't normalized against the total weight but applied as
  1094. is on top of other transformations. If the weight of an additive channel is
  1095. 1, the blended transformation of other channels is multiplied by its full
  1096. rotation and scaling. */
  1097. LIALG_U32DIC_FOREACH (iter, self->channels)
  1098. {
  1099. chan = iter.value;
  1100. if (!chan->additive)
  1101. continue;
  1102. if (limdl_animation_get_transform (chan->animation, node->name, chan->time, &scale1, &transform))
  1103. {
  1104. bonepos = transform.position;
  1105. bonerot = transform.rotation;
  1106. private_get_channel_weight (self, chan, node, &weight1, &weight);
  1107. rotation = limat_quaternion_nlerp (bonerot, rotation, weight);
  1108. position = limat_vector_lerp (bonepos, position, weight);
  1109. scale += scale1 * weight1;
  1110. }
  1111. }
  1112. /* Update node transformation. */
  1113. transform = limat_transform_init (position, rotation);
  1114. limdl_node_set_local_transform (node, scale, &transform);
  1115. limdl_node_rebuild (node, 0);
  1116. /* Update child transformations recursively. */
  1117. for (i = 0 ; i < node->nodes.count ; i++)
  1118. private_transform_node (self, node->nodes.array[i]);
  1119. }
  1120. static void private_get_channel_weight (
  1121. const LIMdlPose* self,
  1122. const LIMdlPoseChannel* channel,
  1123. const LIMdlNode* node,
  1124. float* scale,
  1125. float* transform)
  1126. {
  1127. float end;
  1128. float time;
  1129. float duration;
  1130. float weight_scale;
  1131. float weight_transform;
  1132. float* weight_ptr;
  1133. /* Calculate channel offset. */
  1134. duration = limdl_animation_get_duration (channel->animation);
  1135. time = channel->repeat * duration + channel->time;
  1136. end = channel->repeats * duration;
  1137. /* Calculate base weights. */
  1138. weight_scale = channel->priority_scale;
  1139. weight_transform = channel->priority_transform;
  1140. if (node != NULL && channel->weights)
  1141. {
  1142. weight_ptr = lialg_strdic_find (channel->weights, node->name);
  1143. if (weight_ptr != NULL)
  1144. weight_transform = *weight_ptr;
  1145. }
  1146. /* Calculate channel weight. */
  1147. if (!channel->repeat && time < channel->fade_in)
  1148. {
  1149. /* Fade in period. */
  1150. *scale = private_smooth_fade (weight_scale,
  1151. channel->fade_in - time, channel->fade_in);
  1152. *transform = private_smooth_fade (weight_transform,
  1153. channel->fade_in - time, channel->fade_in);
  1154. }
  1155. else if (channel->repeats == -1 || time < end - channel->fade_out)
  1156. {
  1157. /* No fade period. */
  1158. *scale = weight_scale;
  1159. *transform = weight_transform;
  1160. }
  1161. else
  1162. {
  1163. /* Fade out period. */
  1164. *scale = private_smooth_fade (weight_scale,
  1165. time - (end - channel->fade_out), channel->fade_out);
  1166. *transform = private_smooth_fade (weight_transform,
  1167. time - (end - channel->fade_out), channel->fade_out);
  1168. }
  1169. }
  1170. static float private_smooth_fade (
  1171. float channel_weight,
  1172. float fade_offset,
  1173. float fade_length)
  1174. {
  1175. float weight_base;
  1176. float weight_scaled;
  1177. float weight_smoothing;
  1178. /* Calculates smooth fading. */
  1179. /* Linear fading of channels with wildly different weights doesn't
  1180. look nice because the channel with the largest weight dominates.
  1181. This is particularly problematic with cross-fading since there's
  1182. no cross-fading at all without compensating for the difference. */
  1183. /* We reduce the problem by applying smoothstep() to the excess weight.
  1184. This compensates for the weight difference by smoothly bringing the
  1185. weight of the sequence closer to the [0,1] range. */
  1186. weight_base = 1.0f - (fade_offset / fade_length);
  1187. weight_scaled = weight_base * channel_weight;
  1188. weight_smoothing = 1.0f - limat_smoothstep (fade_offset, 0.0f, fade_length);
  1189. return weight_base + (weight_scaled - weight_base) * weight_smoothing;
  1190. }
  1191. /** @} */
  1192. /** @} */