MeshSkin.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #include "Base.h"
  2. #include "MeshSkin.h"
  3. #include "Node.h"
  4. #include "StringUtil.h"
  5. #include "Mesh.h"
  6. #include "GPBFile.h"
  7. #include "Animations.h"
  8. #include "Transform.h"
  9. #include "Curve.h"
  10. #include "Matrix.h"
  11. namespace gameplay
  12. {
  13. MeshSkin::MeshSkin(void) :
  14. _vertexInfluenceCount(0)
  15. {
  16. Matrix::setIdentity(_bindShape);
  17. }
  18. MeshSkin::~MeshSkin(void)
  19. {
  20. }
  21. unsigned int MeshSkin::getTypeId(void) const
  22. {
  23. return MESHPART_ID;
  24. }
  25. const char* MeshSkin::getElementName(void) const
  26. {
  27. return "MeshSkin";
  28. }
  29. void MeshSkin::writeBinary(FILE* file)
  30. {
  31. Object::writeBinary(file);
  32. write(_bindShape, 16, file);
  33. write((unsigned int)_joints.size(), file);
  34. for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
  35. {
  36. (*i)->writeBinaryXref(file);
  37. }
  38. write((unsigned int)_bindPoses.size() * 16, file);
  39. for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
  40. {
  41. write(i->m, 16, file);
  42. }
  43. /*
  44. // Write joint bounding spheres
  45. write((unsigned int)_jointBounds.size(), file);
  46. for (unsigned int i = 0; i < _jointBounds.size(); ++i)
  47. {
  48. BoundingVolume& v = _jointBounds[i];
  49. write(v.center.x, file);
  50. write(v.center.y, file);
  51. write(v.center.z, file);
  52. write(v.radius, file);
  53. }
  54. */
  55. }
  56. void MeshSkin::writeText(FILE* file)
  57. {
  58. fprintElementStart(file);
  59. fprintf(file, "<bindShape>");
  60. fprintfMatrix4f(file, _bindShape);
  61. fprintf(file, "</bindShape>");
  62. fprintf(file, "<joints>");
  63. for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
  64. {
  65. fprintf(file, "%s ", i->c_str());
  66. }
  67. fprintf(file, "</joints>\n");
  68. fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size() * 16);
  69. for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
  70. {
  71. for (unsigned int j = 0; j < 16; ++j)
  72. {
  73. fprintf(file, "%f ", i->m[j]);
  74. }
  75. }
  76. fprintf(file, "</bindPoses>\n");
  77. fprintElementEnd(file);
  78. }
  79. void MeshSkin::setBindShape(const float data[])
  80. {
  81. for (int i = 0; i < 16; ++i)
  82. {
  83. _bindShape[i] = data[i];
  84. }
  85. }
  86. void MeshSkin::setVertexInfluenceCount(unsigned int count)
  87. {
  88. _vertexInfluenceCount = count;
  89. }
  90. void MeshSkin::setJointNames(const std::vector<std::string>& list)
  91. {
  92. _jointNames = list;
  93. }
  94. const std::vector<std::string>& MeshSkin::getJointNames()
  95. {
  96. return _jointNames;
  97. }
  98. const std::vector<Node*>& MeshSkin::getJoints() const
  99. {
  100. return _joints;
  101. }
  102. void MeshSkin::setJoints(const std::vector<Node*>& list)
  103. {
  104. _joints = list;
  105. }
  106. void MeshSkin::setBindPoses(std::vector<Matrix>& list)
  107. {
  108. for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); ++i)
  109. {
  110. _bindPoses.push_back(*i);
  111. }
  112. }
  113. bool MeshSkin::hasJoint(const char* id)
  114. {
  115. for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
  116. {
  117. if (equals(*i, id))
  118. {
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. void MeshSkin::computeBounds()
  125. {
  126. // Find the offset of the blend indices and blend weights within the mesh vertices
  127. int blendIndexOffset = -1;
  128. int blendWeightOffset = -1;
  129. for (unsigned int i = 0, count = _mesh->getVertexElementCount(); i < count; ++i)
  130. {
  131. const VertexElement& e = _mesh->getVertexElement(i);
  132. switch (e.usage)
  133. {
  134. case BLENDINDICES:
  135. blendIndexOffset = i;
  136. break;
  137. case BLENDWEIGHTS:
  138. blendWeightOffset = i;
  139. break;
  140. }
  141. }
  142. if (blendIndexOffset == -1 || blendWeightOffset == -1)
  143. {
  144. // Need blend indices and blend weights to calculate skinned bounding volume
  145. return;
  146. }
  147. LOG(2, "Computing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
  148. Node* joint;
  149. // Get the root joint
  150. Node* rootJoint = _joints[0];
  151. Node* parent = rootJoint->getParent();
  152. while (parent)
  153. {
  154. // Is this parent in the list of joints that form the skeleton?
  155. // If not, then it's simply a parent node to the root joint
  156. if (find(_joints.begin(), _joints.end(), parent) != _joints.end())
  157. {
  158. rootJoint = parent;
  159. }
  160. parent = parent->getParent();
  161. }
  162. // If the root joint has a parent node, temporarily detach it so that its transform is
  163. // not included in the bounding volume calculation below
  164. Node* rootJointParent = rootJoint->getParent();
  165. if (rootJointParent)
  166. {
  167. rootJointParent->removeChild(rootJoint);
  168. }
  169. unsigned int jointCount = _joints.size();
  170. unsigned int vertexCount = _mesh->getVertexCount();
  171. LOG(3, " %u joints found.\n", jointCount);
  172. std::vector<AnimationChannel*> channels;
  173. std::vector<Node*> channelTargets;
  174. std::vector<Curve*> curves;
  175. std::vector<Vector3> vertices;
  176. _jointBounds.resize(jointCount);
  177. // Construct a list of all animation channels that target the joints affecting this mesh skin
  178. LOG(3, " Collecting animations...\n");
  179. LOG(3, " 0%%\r");
  180. for (unsigned int i = 0; i < jointCount; ++i)
  181. {
  182. joint = _joints[i];
  183. // Find all animations that target this joint
  184. Animations* animations = GPBFile::getInstance()->getAnimations();
  185. for (unsigned int j = 0, animationCount = animations->getAnimationCount(); j < animationCount; ++j)
  186. {
  187. Animation* animation = animations->getAnimation(j);
  188. for (unsigned int k = 0, channelCount = animation->getAnimationChannelCount(); k < channelCount; ++k)
  189. {
  190. AnimationChannel* channel = animation->getAnimationChannel(k);
  191. if (channel->getTargetId() == joint->getId())
  192. {
  193. if (find(channels.begin(), channels.end(), channel) == channels.end())
  194. {
  195. channels.push_back(channel);
  196. channelTargets.push_back(joint);
  197. }
  198. }
  199. }
  200. }
  201. // Calculate the local bounding volume for this joint
  202. vertices.clear();
  203. BoundingVolume jointBounds;
  204. jointBounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
  205. jointBounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
  206. for (unsigned int j = 0; j < vertexCount; ++j)
  207. {
  208. const Vertex& v = _mesh->getVertex(j);
  209. if ((v.blendIndices.x == i && !ISZERO(v.blendWeights.x)) ||
  210. (v.blendIndices.y == i && !ISZERO(v.blendWeights.y)) ||
  211. (v.blendIndices.z == i && !ISZERO(v.blendWeights.z)) ||
  212. (v.blendIndices.w == i && !ISZERO(v.blendWeights.w)))
  213. {
  214. vertices.push_back(v.position);
  215. // Update box min/max
  216. if (v.position.x < jointBounds.min.x)
  217. jointBounds.min.x = v.position.x;
  218. if (v.position.y < jointBounds.min.y)
  219. jointBounds.min.y = v.position.y;
  220. if (v.position.z < jointBounds.min.z)
  221. jointBounds.min.z = v.position.z;
  222. if (v.position.x > jointBounds.max.x)
  223. jointBounds.max.x = v.position.x;
  224. if (v.position.y > jointBounds.max.y)
  225. jointBounds.max.y = v.position.y;
  226. if (v.position.z > jointBounds.max.z)
  227. jointBounds.max.z = v.position.z;
  228. }
  229. }
  230. if (vertices.size() > 0)
  231. {
  232. // Compute center point
  233. Vector3::add(jointBounds.min, jointBounds.max, &jointBounds.center);
  234. jointBounds.center.scale(0.5f);
  235. // Compute radius
  236. for (unsigned int j = 0, jointVertexCount = vertices.size(); j < jointVertexCount; ++j)
  237. {
  238. float d = jointBounds.center.distanceSquared(vertices[j]);
  239. if (d > jointBounds.radius)
  240. jointBounds.radius = d;
  241. }
  242. jointBounds.radius = sqrt(jointBounds.radius);
  243. }
  244. _jointBounds[i] = jointBounds;
  245. LOG(3, " %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
  246. }
  247. LOG(3, "\n");
  248. unsigned int channelCount = channels.size();
  249. // Create a Curve for each animation channel
  250. float maxDuration = 0.0f;
  251. LOG(3, " Building animation curves...\n");
  252. LOG(3, " 0%%\r");
  253. for (unsigned int i = 0; i < channelCount; ++i)
  254. {
  255. AnimationChannel* channel = channels[i];
  256. const std::vector<float>& keyTimes = channel->getKeyTimes();
  257. unsigned int keyCount = keyTimes.size();
  258. if (keyCount == 0)
  259. continue;
  260. // Create a curve for this animation channel
  261. Curve* curve = NULL;
  262. switch (channel->getTargetAttribute())
  263. {
  264. case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
  265. curve = new Curve(keyCount, 10);
  266. curve->setQuaternionOffset(3);
  267. break;
  268. }
  269. if (curve == NULL)
  270. {
  271. // Unsupported/not implemented curve type
  272. continue;
  273. }
  274. // Copy key values into a temporary array
  275. unsigned int keyValuesCount = channel->getKeyValues().size();
  276. float* keyValues = new float[keyValuesCount];
  277. for (unsigned int j = 0; j < keyValuesCount; ++j)
  278. keyValues[j] = channel->getKeyValues()[j];
  279. // Determine animation duration
  280. float startTime = keyTimes[0];
  281. float duration = keyTimes[keyCount-1] - startTime;
  282. if (duration > maxDuration)
  283. maxDuration = duration;
  284. if (duration > 0.0f)
  285. {
  286. // Set curve points
  287. float* keyValuesPtr = keyValues;
  288. for (unsigned int j = 0; j < keyCount; ++j)
  289. {
  290. // Store time normalized, between 0-1
  291. float t = (keyTimes[j] - startTime) / duration;
  292. // Set the curve point
  293. // TODO: Handle other interpolation types
  294. curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
  295. // Move to the next point on the curve
  296. keyValuesPtr += curve->getComponentCount();
  297. }
  298. curves.push_back(curve);
  299. }
  300. delete[] keyValues;
  301. keyValues = NULL;
  302. LOG(3, " %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
  303. }
  304. LOG(3, "\n");
  305. // Compute a total combined bounding volume for the MeshSkin that contains all possible
  306. // vertex positions for all animations targeting the skin. This rough approximation allows
  307. // us to store a volume that can be used for rough intersection tests (such as for visibility
  308. // determination) efficiently at runtime.
  309. // Backup existing node transforms so we can restore them when we are finished
  310. Matrix* oldTransforms = new Matrix[jointCount];
  311. for (unsigned int i = 0; i < jointCount; ++i)
  312. {
  313. memcpy(oldTransforms[i].m, _joints[i]->getTransformMatrix().m, 16 * sizeof(float));
  314. }
  315. float time = 0.0f;
  316. float srt[10];
  317. Matrix temp;
  318. Matrix* jointTransforms = new Matrix[jointCount];
  319. _mesh->bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
  320. _mesh->bounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
  321. _mesh->bounds.center.set(0, 0, 0);
  322. _mesh->bounds.radius = 0;
  323. Vector3 skinnedPos;
  324. Vector3 tempPos;
  325. LOG(3, " Evaluating joints...\n");
  326. LOG(3, " 0%%\r");
  327. BoundingVolume finalBounds;
  328. while (time <= maxDuration)
  329. {
  330. // Evaluate joint transforms at this time interval
  331. for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
  332. {
  333. Node* joint = channelTargets[i];
  334. Curve* curve = curves[i];
  335. // Evalulate the curve at this time to get the new value
  336. float tn = time / maxDuration;
  337. if (tn > 1.0f)
  338. tn = 1.0f;
  339. curve->evaluate(tn, srt);
  340. // Update the joint's local transform
  341. Matrix::createTranslation(srt[7], srt[8], srt[9], temp.m);
  342. temp.rotate(*((Quaternion*)&srt[3]));
  343. temp.scale(srt[0], srt[1], srt[2]);
  344. joint->setTransformMatrix(temp.m);
  345. }
  346. // Store the final matrix pallette of resovled world space joint matrices
  347. std::vector<Matrix>::const_iterator bindPoseItr = _bindPoses.begin();
  348. for (unsigned int i = 0; i < jointCount; ++i, bindPoseItr++)
  349. {
  350. BoundingVolume bounds = _jointBounds[i];
  351. if (ISZERO(bounds.radius))
  352. continue;
  353. Matrix& m = jointTransforms[i];
  354. Matrix::multiply(_joints[i]->getWorldMatrix().m, bindPoseItr->m, m.m);
  355. Matrix::multiply(m.m, _bindShape, m.m);
  356. // Get a world-space bounding volume for this joint
  357. bounds.transform(m);
  358. if (ISZERO(finalBounds.radius))
  359. finalBounds = bounds;
  360. else
  361. finalBounds.merge(bounds);
  362. }
  363. // Increment time by 1/30th of second (~ 33 ms)
  364. if (time < maxDuration && (time + 33.0f) > maxDuration)
  365. time = maxDuration;
  366. else
  367. time += 33.0f;
  368. LOG(3, " %d%%\r", (int)(time / maxDuration * 100.0f));
  369. }
  370. LOG(3, "\n");
  371. // Update the bounding sphere for the mesh
  372. _mesh->bounds = finalBounds;
  373. // Restore original joint transforms
  374. for (unsigned int i = 0; i < jointCount; ++i)
  375. {
  376. _joints[i]->setTransformMatrix(oldTransforms[i].m);
  377. }
  378. // Cleanup
  379. for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
  380. {
  381. delete curves[i];
  382. }
  383. delete[] oldTransforms;
  384. delete[] jointTransforms;
  385. // Restore removed joints
  386. if (rootJointParent)
  387. {
  388. rootJointParent->addChild(rootJoint);
  389. }
  390. }
  391. }