home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 5164 / miletos.7z / ikchain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2011-04-02  |  3.8 KB  |  167 lines

  1. #define __MILETOS_IKCHAIN_CPP__
  2.  
  3. //
  4. // Libmiletos
  5. //
  6. // Copyright (C) Lauris Kaplinski 2010
  7. //
  8.  
  9. #include <malloc.h>
  10.  
  11. #include "xml/base.h"
  12. #include "skeleton.h"
  13. #include "bone.h"
  14.  
  15. #include "ikchain.h"
  16.  
  17. namespace Miletos {
  18.  
  19. //
  20. // IK chain controller for skeletal meshes
  21. //
  22.  
  23. IKChain::IKChain (void)
  24. : Object(0), sid (NULL), first(NULL), last(NULL), end(NULL), endPosition(Elea::Vector3f0), targetPosition(Elea::Vector3f0), enabled(1)
  25. {
  26. }
  27.  
  28. IKChain::~IKChain (void)
  29. {
  30.     if (sid) free (sid);
  31.     if (first) free (first);
  32.     if (last) free (last);
  33.     if (end) free (end);
  34. }
  35.  
  36. static Object *
  37. ikchain_factory (void)
  38. {
  39.     return new IKChain();
  40. }
  41.  
  42. const Object::Type *
  43. IKChain::objectType (void)
  44. {
  45.     return type ();
  46. }
  47.  
  48. const Object::Type *
  49. IKChain::type (void)
  50. {
  51.     static Type *mytype = NULL;
  52.     static const Attribute attrs[] = {
  53.         { "sid", NULL, 0 },
  54.         { "first", NULL, 0 },
  55.         { "last", NULL, 0 },
  56.         { "end", NULL, 0 },
  57.         { "endPosition", NULL, 0 },
  58.         { "targetPosition", NULL, 0 }
  59.     };
  60.     if (!mytype) mytype = new Type(Object::type (), "IKChain", "ikChain", ikchain_factory, sizeof (attrs) / sizeof (attrs[0]), attrs);
  61.     return mytype;
  62. }
  63.  
  64. void
  65. IKChain::build (Thera::Node *pnode, Document *doc, BuildCtx *ctx)
  66. {
  67.     Object::build (pnode, doc, ctx);
  68.     buildAllAttributes (type (), ctx);
  69.     requestUpdate (CHAIN_STRUCTURE_MODIFIED);
  70. }
  71.  
  72. void
  73. IKChain::release (void)
  74. {
  75.     Object::release ();
  76. }
  77.  
  78. void
  79. IKChain::set (const char *attrid, const char *val)
  80. {
  81.     if (!strcmp (attrid, "sid")) {
  82.         if (sid) free (sid);
  83.         sid = (val) ? strdup (val) : NULL;
  84.         requestUpdate (MODIFIED);
  85.     } else if (!strcmp (attrid, "first")) {
  86.         if (first) free (first);
  87.         first = (val) ? strdup (val) : NULL;
  88.         requestUpdate (MODIFIED | CHAIN_STRUCTURE_MODIFIED);
  89.     } else if (!strcmp (attrid, "last")) {
  90.         if (last) free (last);
  91.         last = (val) ? strdup (val) : NULL;
  92.         requestUpdate (MODIFIED | CHAIN_STRUCTURE_MODIFIED);
  93.     } else if (!strcmp (attrid, "end")) {
  94.         if (end) free (end);
  95.         end = (val) ? strdup (val) : NULL;
  96.         requestUpdate (MODIFIED | CHAIN_STRUCTURE_MODIFIED);
  97.     } else if (!strcmp (attrid, "endPosition")) {
  98.         if (!Miletos::XML::parseNumbers (endPosition, 3, val)) endPosition = Elea::Vector3f0;
  99.         requestUpdate (MODIFIED);
  100.     } else if (!strcmp (attrid, "targetPosition")) {
  101.         if (!Miletos::XML::parseNumbers (targetPosition, 3, val)) targetPosition = Elea::Vector3f0;
  102.         requestUpdate (MODIFIED);
  103.     }
  104.     // Object does not implement set
  105. }
  106.  
  107. void
  108. IKChain::write (const char *attrid)
  109. {
  110.     if (!strcmp (attrid, "first")) {
  111.     } else if (!strcmp (attrid, "last")) {
  112.     } else if (!strcmp (attrid, "end")) {
  113.     } else if (!strcmp (attrid, "endPosition")) {
  114.     } else if (!strcmp (attrid, "targetPosition")) {
  115.         char c[128];
  116.         XML::writeNumbers (c, 128, targetPosition, 3);
  117.         node->setAttribute (attrid, c);
  118.     }
  119. }
  120.  
  121. void
  122. IKChain::update (UpdateCtx *ctx, unsigned int flags)
  123. {
  124.     Object::update (ctx, flags);
  125. }
  126.  
  127. void
  128. IKChain::attach (Skeleton *skeleton)
  129. {
  130.     bones.clear ();
  131.     endbone = NULL;
  132.     if (!skeleton || !first || !last || !end) return;
  133.     int boneidx = skeleton->lookupBone (last);
  134.     if (boneidx < 0) return;
  135.     Bone *bone = skeleton->bones[boneidx];
  136.     std::vector<Bone *> lbones;
  137.     while (bone) {
  138.         lbones.push_back (bone);
  139.         if (!strcmp (bone->sid, first)) break;
  140.         bone = (Bone *) bone->parent;
  141.         if (!bone->isType (Bone::type ())) return;
  142.         if (!bone->sid) return;
  143.     }
  144.     boneidx = skeleton->lookupBone (end);
  145.     if (boneidx < 0) return;
  146.     endbone = skeleton->bones[boneidx];
  147.     bones.resize (lbones.size ());
  148.     for (size_t i = 0; i < lbones.size (); i++) {
  149.         bones[i].bone = lbones[lbones.size () - 1 - i];
  150.         Elea::Matrix4x4f p2b = bones[i].bone->b2p.invertNormalized ();
  151.         Elea::Matrix4x4f ab2b = p2b * bones[i].bone->ab2p;
  152.         const int order[] = { Elea::Z, Elea::X, Elea::Y };
  153.         ab2b.getEulerAngles (bones[i].angles, order);
  154.     }
  155. }
  156.  
  157. void
  158. IKChain::setTargetPosition (const Elea::Vector3f *pos)
  159. {
  160.     targetPosition = *pos;
  161.     requestUpdate (MODIFIED);
  162. }
  163.  
  164. } // Namespace Miletos
  165.  
  166.  
  167.