/src/lipsofsuna/model/model-animation.c

https://github.com/deldiablo/GodheadLips · C · 465 lines · 300 code · 48 blank · 117 comment · 61 complexity · 0fb08edc08190ca3bb27f009bf124bdd 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 LIMdlAnimation Animation
  21. * @{
  22. */
  23. #include "lipsofsuna/system.h"
  24. #include "model-animation.h"
  25. #define TIMESCALE 0.02f
  26. static void private_frame_transform (
  27. LIMdlAnimation* self,
  28. int chan,
  29. int frame,
  30. float* scale,
  31. LIMatTransform* value);
  32. /*****************************************************************************/
  33. /**
  34. * \brief Copies the animation.
  35. * \param self Animation.
  36. * \param anim Animation.
  37. * \return Nonzero on success.
  38. */
  39. int limdl_animation_init_copy (
  40. LIMdlAnimation* self,
  41. LIMdlAnimation* anim)
  42. {
  43. int i;
  44. /* Allocate self. */
  45. self->length = anim->length;
  46. self->blendin = anim->blendin;
  47. self->blendout = anim->blendout;
  48. if (anim->name != NULL)
  49. self->name = lisys_string_dup (anim->name);
  50. /* Copy channels. */
  51. if (anim->channels.count)
  52. {
  53. self->channels.array = lisys_calloc (anim->channels.count, sizeof (char*));
  54. if (self->channels.array == NULL)
  55. return 0;
  56. self->channels.count = anim->channels.count;
  57. for (i = 0 ; i < self->channels.count ; i++)
  58. {
  59. self->channels.array[i] = lisys_string_dup (anim->channels.array[i]);
  60. if (self->channels.array[i] == NULL)
  61. return 0;
  62. }
  63. }
  64. /* Copy frames. */
  65. if (anim->buffer.count)
  66. {
  67. self->buffer.array = lisys_calloc (anim->buffer.count, sizeof (LIMdlFrame));
  68. if (self->buffer.array == NULL)
  69. return 0;
  70. self->buffer.count = anim->buffer.count;
  71. memcpy (self->buffer.array, anim->buffer.array,
  72. self->buffer.count * sizeof (LIMdlFrame));
  73. }
  74. return 1;
  75. }
  76. /**
  77. * \brief Creates a soft copy of the animation.
  78. * \param anim Animation.
  79. * \return New animation or NULL.
  80. */
  81. LIMdlAnimation* limdl_animation_new_copy (
  82. LIMdlAnimation* anim)
  83. {
  84. LIMdlAnimation* self;
  85. /* Allocate self. */
  86. self = lisys_calloc (1, sizeof (LIMdlAnimation));
  87. if (self == NULL)
  88. return NULL;
  89. if (!limdl_animation_init_copy (self, anim))
  90. {
  91. limdl_animation_free (self);
  92. return NULL;
  93. }
  94. return self;
  95. }
  96. /**
  97. * \brief Frees the animation.
  98. * \param self Animation.
  99. */
  100. void limdl_animation_free (
  101. LIMdlAnimation* self)
  102. {
  103. limdl_animation_clear (self);
  104. lisys_free (self);
  105. }
  106. /**
  107. * \brief Adds a channel to the animation.
  108. *
  109. * If the channel exists already, nothing is done.
  110. *
  111. * \param self Animation.
  112. * \param name Node name.
  113. * \return Nonzero on success.
  114. */
  115. int limdl_animation_insert_channel (
  116. LIMdlAnimation* self,
  117. const char* name)
  118. {
  119. int chan;
  120. int frame;
  121. char* str;
  122. char** tmp;
  123. LIMdlFrame* dstframe;
  124. LIMdlFrame* srcframe;
  125. LIMdlFrame* buffer = NULL;
  126. /* Check for existence. */
  127. if (limdl_animation_get_channel (self, name) != -1)
  128. return 1;
  129. /* Duplicate the name. */
  130. str = lisys_string_dup (name);
  131. if (str == NULL)
  132. return 0;
  133. /* Rebuild the transformation buffer. */
  134. if (self->length)
  135. {
  136. buffer = lisys_calloc ((self->channels.count + 1) * self->length, sizeof (LIMdlFrame));
  137. if (buffer == NULL)
  138. {
  139. lisys_free (str);
  140. return 0;
  141. }
  142. for (frame = 0 ; frame < self->length ; frame++)
  143. {
  144. for (chan = 0 ; chan < self->channels.count ; chan++)
  145. {
  146. srcframe = self->buffer.array + self->channels.count * frame + chan;
  147. dstframe = buffer + (self->channels.count + 1) * frame + chan;
  148. dstframe->scale = srcframe->scale;
  149. dstframe->transform = srcframe->transform;
  150. }
  151. dstframe = buffer + (self->channels.count + 1) * frame + chan;
  152. dstframe->scale = 1.0f;
  153. dstframe->transform = limat_transform_identity ();
  154. }
  155. }
  156. /* Allocate a new channel. */
  157. tmp = lisys_realloc (self->channels.array, (self->channels.count + 1) * sizeof (char*));
  158. if (tmp == NULL)
  159. {
  160. lisys_free (buffer);
  161. lisys_free (str);
  162. return 0;
  163. }
  164. self->channels.array = tmp;
  165. self->channels.array[self->channels.count] = str;
  166. self->channels.count++;
  167. /* Use the new transformation buffer. */
  168. if (self->length)
  169. {
  170. lisys_free (self->buffer.array);
  171. self->buffer.array = buffer;
  172. self->buffer.count = self->channels.count * self->length;
  173. }
  174. return 1;
  175. }
  176. /**
  177. * \brief Clears the name and channels of the animation.
  178. * \param self Animation.
  179. */
  180. void limdl_animation_clear (
  181. LIMdlAnimation* self)
  182. {
  183. int i;
  184. if (self->channels.array != NULL)
  185. {
  186. for (i = 0 ; i < self->channels.count ; i++)
  187. lisys_free (self->channels.array[i]);
  188. lisys_free (self->channels.array);
  189. }
  190. lisys_free (self->buffer.array);
  191. lisys_free (self->name);
  192. }
  193. /**
  194. * \brief Reads the animation from a stream.
  195. * \param self Animation.
  196. * \param reader Stream reader.
  197. * \return Nonzero on success.
  198. */
  199. int limdl_animation_read (
  200. LIMdlAnimation* self,
  201. LIArcReader* reader)
  202. {
  203. int i;
  204. uint32_t count0;
  205. uint32_t count1;
  206. LIMatTransform* transform;
  207. /* Read the header. */
  208. if (!liarc_reader_get_text (reader, "", &self->name) ||
  209. !liarc_reader_get_uint32 (reader, &count0) ||
  210. !liarc_reader_get_uint32 (reader, &count1))
  211. return 0;
  212. /* Allocate channels. */
  213. self->channels.count = count0;
  214. if (count0)
  215. {
  216. self->channels.array = lisys_calloc (count0, sizeof (char*));
  217. if (self->channels.array == NULL)
  218. return 0;
  219. }
  220. /* Read channels. */
  221. for (i = 0 ; i < self->channels.count ; i++)
  222. {
  223. if (!liarc_reader_get_text (reader, "", self->channels.array + i))
  224. return 0;
  225. }
  226. /* Allocate frames. */
  227. self->length = count1;
  228. self->buffer.count = count0 * count1;
  229. if (self->buffer.count)
  230. {
  231. self->buffer.array = lisys_calloc (self->buffer.count, sizeof (LIMdlFrame));
  232. if (self->buffer.array == NULL)
  233. return 0;
  234. }
  235. /* Read frames. */
  236. for (i = 0 ; i < self->buffer.count ; i++)
  237. {
  238. self->buffer.array[i].scale = 1.0f;
  239. transform = &self->buffer.array[i].transform;
  240. if (!liarc_reader_get_float (reader, &transform->position.x) ||
  241. !liarc_reader_get_float (reader, &transform->position.y) ||
  242. !liarc_reader_get_float (reader, &transform->position.z) ||
  243. !liarc_reader_get_float (reader, &transform->rotation.x) ||
  244. !liarc_reader_get_float (reader, &transform->rotation.y) ||
  245. !liarc_reader_get_float (reader, &transform->rotation.z) ||
  246. !liarc_reader_get_float (reader, &transform->rotation.w))
  247. return 0;
  248. }
  249. return 1;
  250. }
  251. /**
  252. * \brief Gets the index of a channel.
  253. *
  254. * \param self Animation.
  255. * \param name Channel name.
  256. * \return Channel index or -1.
  257. */
  258. int limdl_animation_get_channel (
  259. LIMdlAnimation* self,
  260. const char* name)
  261. {
  262. int i;
  263. for (i = 0 ; i < self->channels.count ; i++)
  264. {
  265. if (!strcmp (self->channels.array[i], name))
  266. return i;
  267. }
  268. return -1;
  269. }
  270. /**
  271. * \brief Gets the duration of the animation in seconds.
  272. *
  273. * The return value is guaranteed to be greater than zero. If the animation
  274. * has one or less frames, the return value is one second.
  275. *
  276. * \param self Animation.
  277. * \return Duration in seconds.
  278. */
  279. float limdl_animation_get_duration (
  280. const LIMdlAnimation* self)
  281. {
  282. if (self->length > 1)
  283. return (self->length - 1) * TIMESCALE;
  284. return 1.0f;
  285. }
  286. /**
  287. * \brief Sets the number of frames in the animation.
  288. * \param self Animation.
  289. * \param value Frame count.
  290. * \return Nonzero on success.
  291. */
  292. int limdl_animation_set_length (
  293. LIMdlAnimation* self,
  294. int value)
  295. {
  296. int i;
  297. LIMdlFrame* tmp;
  298. if (value == self->length)
  299. return 1;
  300. if (!self->channels.count)
  301. {
  302. self->length = value;
  303. return 1;
  304. }
  305. if (!value)
  306. {
  307. /* Set to empty. */
  308. lisys_free (self->buffer.array);
  309. self->buffer.array = NULL;
  310. }
  311. else if (value < self->length)
  312. {
  313. /* Shrink. */
  314. tmp = lisys_realloc (self->buffer.array, self->channels.count * value * sizeof (LIMdlFrame));
  315. if (tmp != NULL)
  316. self->buffer.array = tmp;
  317. }
  318. else
  319. {
  320. /* Expand. */
  321. tmp = lisys_realloc (self->buffer.array, self->channels.count * value * sizeof (LIMdlFrame));
  322. if (tmp == NULL)
  323. return 0;
  324. self->buffer.array = tmp;
  325. for (i = self->channels.count * self->length ; i < self->channels.count * value ; i++)
  326. {
  327. self->buffer.array[i].scale = 1.0f;
  328. self->buffer.array[i].transform = limat_transform_identity ();
  329. }
  330. }
  331. self->length = value;
  332. self->buffer.count = self->channels.count * self->length;
  333. return 1;
  334. }
  335. /**
  336. * \brief Sets the node transformation.
  337. * \param self Animation.
  338. * \param name Channel name.
  339. * \param frame Frame number.
  340. * \param scale Scale factor.
  341. * \param value Node transformation.
  342. * \return Nonzero on success.
  343. */
  344. int limdl_animation_set_transform (
  345. LIMdlAnimation* self,
  346. const char* name,
  347. int frame,
  348. float scale,
  349. const LIMatTransform* value)
  350. {
  351. int chan;
  352. lisys_assert (frame >= 0);
  353. lisys_assert (frame < self->length);
  354. chan = limdl_animation_get_channel (self, name);
  355. if (chan == -1)
  356. return 0;
  357. self->buffer.array[self->channels.count * frame + chan].scale = scale;
  358. self->buffer.array[self->channels.count * frame + chan].transform = *value;
  359. return 1;
  360. }
  361. /**
  362. * \brief Gets the node transformation.
  363. * \param self Animation.
  364. * \param name Channel name.
  365. * \param secs Animation position.
  366. * \param scale Return location for the scale factor.
  367. * \param value Return location for the transformation.
  368. * \return Nonzero on success.
  369. */
  370. int limdl_animation_get_transform (
  371. LIMdlAnimation* self,
  372. const char* name,
  373. float secs,
  374. float* scale,
  375. LIMatTransform* value)
  376. {
  377. int chan;
  378. int frame;
  379. float s0;
  380. float s1;
  381. float blend;
  382. float frames;
  383. LIMatTransform t0;
  384. LIMatTransform t1;
  385. chan = limdl_animation_get_channel (self, name);
  386. if (chan == -1)
  387. return 0;
  388. frames = secs / TIMESCALE;
  389. frame = (int) frames;
  390. if (frame <= 0)
  391. private_frame_transform (self, chan, 0, scale, value);
  392. else if (frame >= self->length - 1)
  393. private_frame_transform (self, chan, self->length - 1, scale, value);
  394. else
  395. {
  396. blend = frames - frame;
  397. private_frame_transform (self, chan, frame, &s0, &t0);
  398. private_frame_transform (self, chan, frame + 1, &s1, &t1);
  399. *scale = (1.0f - blend) * s0 + blend * s1;
  400. value->position = limat_vector_lerp (t1.position, t0.position, blend);
  401. value->rotation = limat_quaternion_nlerp (t1.rotation, t0.rotation, blend);
  402. }
  403. return 1;
  404. }
  405. /*****************************************************************************/
  406. static void private_frame_transform (
  407. LIMdlAnimation* self,
  408. int chan,
  409. int frame,
  410. float* scale,
  411. LIMatTransform* value)
  412. {
  413. *scale = self->buffer.array[self->channels.count * frame + chan].scale;
  414. *value = self->buffer.array[self->channels.count * frame + chan].transform;
  415. }
  416. /** @} */
  417. /** @} */