SkinNode.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #include "anki/scene/SkinNode.h"
  2. #include "anki/resource/Skin.h"
  3. #include "anki/resource/Skeleton.h"
  4. #include "anki/resource/SkelAnim.h"
  5. #include "anki/resource/MeshLoader.h"
  6. #include <boost/lexical_cast.hpp>
  7. namespace anki {
  8. #define BUFFER_OFFSET(i) ((char *)NULL + (i))
  9. //==============================================================================
  10. // SkinMesh =
  11. //==============================================================================
  12. //==============================================================================
  13. const Vbo* SkinMesh::getVbo(VboId id) const
  14. {
  15. switch(id)
  16. {
  17. case VBO_POSITIONS:
  18. return &tfVbos[VBO_TF_POSITIONS];
  19. case VBO_NORMALS:
  20. return &tfVbos[VBO_TF_NORMALS];
  21. case VBO_TANGENTS:
  22. return &tfVbos[VBO_TF_TANGENTS];
  23. default:
  24. return mesh->getVbo(id);
  25. }
  26. }
  27. //==============================================================================
  28. SkinMesh::SkinMesh(const MeshBase* mesh_)
  29. : mesh(mesh_)
  30. {
  31. // Positions
  32. if(mesh->getVbo(VBO_POSITIONS))
  33. {
  34. tfVbos[VBO_TF_POSITIONS].create(
  35. GL_ARRAY_BUFFER,
  36. mesh->getVbo(VBO_POSITIONS)->getSizeInBytes(),
  37. NULL,
  38. GL_STATIC_DRAW);
  39. }
  40. // Normals
  41. if(mesh->getVbo(VBO_NORMALS))
  42. {
  43. tfVbos[VBO_TF_NORMALS].create(
  44. GL_ARRAY_BUFFER,
  45. mesh->getVbo(VBO_NORMALS)->getSizeInBytes(),
  46. NULL,
  47. GL_STATIC_DRAW);
  48. }
  49. // Tangents
  50. if(mesh->getVbo(VBO_TANGENTS))
  51. {
  52. tfVbos[VBO_TF_TANGENTS].create(
  53. GL_ARRAY_BUFFER,
  54. mesh->getVbo(VBO_TANGENTS)->getSizeInBytes(),
  55. NULL,
  56. GL_STATIC_DRAW);
  57. }
  58. }
  59. //==============================================================================
  60. // SkinModelPatch =
  61. //==============================================================================
  62. //==============================================================================
  63. SkinModelPatch::SkinModelPatch(const ModelPatch* mpatch_)
  64. : mpatch(mpatch_)
  65. {
  66. skinMesh.reset(new SkinMesh(&mpatch->getMeshBase()));
  67. create();
  68. // Create the VAO
  69. //
  70. const MeshBase& mesh = mpatch->getMeshBase();
  71. tfVao.create();
  72. const Vbo* vbo;
  73. // Positions
  74. vbo = mesh.getVbo(MeshBase::VBO_POSITIONS);
  75. if(vbo)
  76. {
  77. tfVao.attachArrayBufferVbo(*vbo,
  78. POSITION_LOC,
  79. 3,
  80. GL_FLOAT,
  81. false,
  82. 0,
  83. NULL);
  84. }
  85. // Normals
  86. vbo = mesh.getVbo(MeshBase::VBO_NORMALS);
  87. if(vbo)
  88. {
  89. tfVao.attachArrayBufferVbo(*vbo,
  90. NORMAL_LOC,
  91. 3,
  92. GL_FLOAT,
  93. false,
  94. 0,
  95. NULL);
  96. }
  97. // Tangents
  98. vbo = mesh.getVbo(MeshBase::VBO_TANGENTS);
  99. if(vbo)
  100. {
  101. tfVao.attachArrayBufferVbo(*vbo,
  102. TANGENT_LOC,
  103. 4,
  104. GL_FLOAT,
  105. false,
  106. 0,
  107. NULL);
  108. }
  109. vbo = mesh.getVbo(Mesh::VBO_WEIGHTS);
  110. ANKI_ASSERT(vbo);
  111. tfVao.attachArrayBufferVbo(*vbo,
  112. VERT_WEIGHT_BONES_NUM_LOC,
  113. 1,
  114. GL_FLOAT,
  115. GL_FALSE,
  116. sizeof(MeshLoader::VertexWeight),
  117. BUFFER_OFFSET(0));
  118. tfVao.attachArrayBufferVbo(*vbo,
  119. VERT_WEIGHT_BONE_IDS_LOC,
  120. 4,
  121. GL_FLOAT,
  122. GL_FALSE,
  123. sizeof(MeshLoader::VertexWeight),
  124. BUFFER_OFFSET(4));
  125. tfVao.attachArrayBufferVbo(*vbo,
  126. VERT_WEIGHT_WEIGHTS_LOC,
  127. 4,
  128. GL_FLOAT,
  129. GL_FALSE,
  130. sizeof(MeshLoader::VertexWeight),
  131. BUFFER_OFFSET(20));
  132. }
  133. //==============================================================================
  134. // SkinPatchNode =
  135. //==============================================================================
  136. //==============================================================================
  137. SkinPatchNode::SkinPatchNode(const ModelPatch* modelPatch_,
  138. const char* name, Scene* scene,
  139. uint movableFlags, Movable* movParent,
  140. CollisionShape* spatialCs)
  141. : SceneNode(name, scene), Movable(movableFlags, movParent, *this),
  142. Spatial(spatialCs)
  143. {
  144. skinModelPatch.reset(new SkinModelPatch(modelPatch_));
  145. Renderable::init(*this);
  146. }
  147. //==============================================================================
  148. // SkinNode =
  149. //==============================================================================
  150. //==============================================================================
  151. SkinNode::SkinNode(const char* skinFname,
  152. const char* name, Scene* scene, // SceneNode
  153. uint movableFlags, Movable* movParent) // Movable
  154. : SceneNode(name, scene), Movable(movableFlags, movParent, *this)
  155. {
  156. skin.load(skinFname);
  157. uint i = 0;
  158. for(const ModelPatch& patch : skin->getModel().getModelPatches())
  159. {
  160. std::string name = skin.getResourceName()
  161. + boost::lexical_cast<std::string>(i);
  162. patches.push_back(new SkinPatchNode(&patch,
  163. name.c_str(), scene,
  164. Movable::MF_IGNORE_LOCAL_TRANSFORM, this,
  165. &visibilityShapeWSpace));
  166. }
  167. uint bonesNum = skin->getSkeleton().getBones().size();
  168. tails.resize(bonesNum);
  169. heads.resize(bonesNum);
  170. boneRotations.resize(bonesNum);
  171. boneTranslations.resize(bonesNum);
  172. }
  173. //==============================================================================
  174. SkinNode::~SkinNode()
  175. {}
  176. //==============================================================================
  177. void SkinNode::movableUpdate()
  178. {
  179. visibilityShapeWSpace.set(tails);
  180. visibilityShapeWSpace.transform(getWorldTransform());
  181. }
  182. //==============================================================================
  183. void SkinNode::frameUpdate(float prevUpdateTime, float crntTime, int f)
  184. {
  185. SceneNode::frameUpdate(prevUpdateTime, crntTime, f);
  186. frame += step;
  187. if(frame > anim->getFramesNum())
  188. {
  189. frame = 0.0;
  190. }
  191. /* // A nasty optimization that may produse ugly results
  192. if(!isFlagEnabled(SNF_VISIBLE))
  193. {
  194. return;
  195. }*/
  196. interpolate(*anim, frame, boneTranslations,
  197. boneRotations);
  198. updateBoneTransforms(getSkin().getSkeleton(),
  199. boneTranslations, boneRotations);
  200. deformHeadsTails(getSkin().getSkeleton(), boneTranslations,
  201. boneRotations, heads, tails);
  202. }
  203. //==============================================================================
  204. void SkinNode::interpolate(const SkelAnim& animation, float frame,
  205. std::vector<Vec3>& boneTranslations, std::vector<Mat3>& boneRotations)
  206. {
  207. ANKI_ASSERT(frame < animation.getFramesNum());
  208. // calculate the t (used in slerp and lerp) using the keyframs and the
  209. // frame and calc the lPose and rPose witch indicate the pose IDs in witch
  210. // the frame lies between
  211. const std::vector<uint>& keyframes = animation.getKeyframes();
  212. float t = 0.0;
  213. uint lPose = 0, rPose = 0;
  214. for(uint j = 0; j < keyframes.size(); j++)
  215. {
  216. if((float)keyframes[j] == frame)
  217. {
  218. lPose = rPose = j;
  219. t = 0.0;
  220. break;
  221. }
  222. else if((float)keyframes[j] > frame)
  223. {
  224. lPose = j - 1;
  225. rPose = j;
  226. t = (frame - (float)keyframes[lPose])
  227. / float(keyframes[rPose] - keyframes[lPose]);
  228. break;
  229. }
  230. }
  231. // now for all bones update bone's poses
  232. ANKI_ASSERT(boneRotations.size() >= 1);
  233. for(uint i = 0; i < boneRotations.size(); i++)
  234. {
  235. const BoneAnim& banim = animation.getBoneAnimations()[i];
  236. Mat3& localRot = boneRotations[i];
  237. Vec3& localTransl = boneTranslations[i];
  238. // if the bone has animations then slerp and lerp to find the rotation
  239. // and translation
  240. if(banim.getBonePoses().size() != 0)
  241. {
  242. const BonePose& lBpose = banim.getBonePoses()[lPose];
  243. const BonePose& rBpose = banim.getBonePoses()[rPose];
  244. // rotation
  245. const Quat& q0 = lBpose.getRotation();
  246. const Quat& q1 = rBpose.getRotation();
  247. localRot = Mat3(q0.slerp(q1, t));
  248. // translation
  249. const Vec3& v0 = lBpose.getTranslation();
  250. const Vec3& v1 = rBpose.getTranslation();
  251. localTransl = v0.lerp(v1, t);
  252. }
  253. // else put the idents
  254. else
  255. {
  256. localRot = Mat3::getIdentity();
  257. localTransl = Vec3(0.0, 0.0, 0.0);
  258. }
  259. }
  260. }
  261. //==============================================================================
  262. void SkinNode::updateBoneTransforms(const Skeleton& skeleton,
  263. std::vector<Vec3>& boneTranslations, std::vector<Mat3>& boneRotations)
  264. {
  265. boost::array<uint, 128> queue;
  266. uint head = 0, tail = 0;
  267. // put the roots
  268. BOOST_FOREACH(const Bone& bone, skeleton.getBones())
  269. {
  270. if(bone.getParent() == NULL)
  271. {
  272. queue[tail++] = bone.getId(); // queue push
  273. }
  274. }
  275. // loop
  276. while(head != tail) // while queue not empty
  277. {
  278. uint boneId = queue[head++]; // queue pop
  279. const Bone& boned = skeleton.getBones()[boneId];
  280. // bone.final_transform = MA * ANIM * MAi
  281. // where MA is bone matrix at armature space and ANIM the interpolated
  282. // transformation.
  283. Math::combineTransformations(
  284. boneTranslations[boneId], boneRotations[boneId],
  285. boned.getTranslationSkeletonSpaceInverted(),
  286. boned.getRotationSkeletonSpaceInverted(),
  287. boneTranslations[boneId], boneRotations[boneId]);
  288. Math::combineTransformations(
  289. boned.getTranslationSkeletonSpace(),
  290. boned.getRotationSkeletonSpace(),
  291. boneTranslations[boneId], boneRotations[boneId],
  292. boneTranslations[boneId], boneRotations[boneId]);
  293. // and finaly add the parent's transform
  294. if(boned.getParent())
  295. {
  296. // bone.final_final_transform = parent.transf * bone.final_transform
  297. Math::combineTransformations(
  298. boneTranslations[boned.getParent()->getId()],
  299. boneRotations[boned.getParent()->getId()],
  300. boneTranslations[boneId],
  301. boneRotations[boneId],
  302. boneTranslations[boneId],
  303. boneRotations[boneId]);
  304. }
  305. // now add the bone's children
  306. for(uint i = 0; i < boned.getChildsNum(); i++)
  307. {
  308. queue[tail++] = boned.getChild(i).getId();
  309. }
  310. }
  311. }
  312. //==============================================================================
  313. void SkinNode::deformHeadsTails(const Skeleton& skeleton,
  314. const std::vector<Vec3>& boneTranslations,
  315. const std::vector<Mat3>& boneRotations,
  316. std::vector<Vec3>& heads, std::vector<Vec3>& tails)
  317. {
  318. for(uint i = 0; i < skeleton.getBones().size(); i++)
  319. {
  320. const Mat3& rot = boneRotations[i];
  321. const Vec3& transl = boneTranslations[i];
  322. heads[i] = skeleton.getBones()[i].getHead().getTransformed(transl, rot);
  323. tails[i] = skeleton.getBones()[i].getTail().getTransformed(transl, rot);
  324. }
  325. }
  326. } // end namespace