DrawSkeleton.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include "DrawSkeleton.h"
  16. #include "Logger.h"
  17. #include "common/TypeDefine.h"
  18. /**
  19. * Used to bind a skeleton position.
  20. */
  21. #define POSITION_BINDING 0
  22. /**
  23. * Used for skeleton bone colours.
  24. */
  25. #define COLOUR_BINDING 1
  26. /**
  27. * Used to keep track of the skeleton and it's bones positions.
  28. */
  29. float* position;
  30. /**
  31. * The bone index for skeleton currently being drawn.
  32. */
  33. u32 cur_index;
  34. /**
  35. * Indexes for a skeleton and it's bones
  36. */
  37. u16* index_data;
  38. /**
  39. * Mesh for a skeleton and it's bones.
  40. */
  41. Ogre::SubMesh* sub_mesh;
  42. void DrawSkeleton(const Skeleton& skeleton, const Ogre::MeshPtr& mesh){
  43. if (skeleton.size() == 0) return;
  44. sub_mesh = mesh->createSubMesh("Skeleton");
  45. sub_mesh->setMaterialName("Skeleton");
  46. sub_mesh->useSharedVertices = false;
  47. sub_mesh->operationType = Ogre::RenderOperation::OT_LINE_LIST;
  48. // Allocate and prepare vertex data.
  49. sub_mesh->vertexData = new Ogre::VertexData();
  50. sub_mesh->vertexData->vertexStart = 0;
  51. sub_mesh->vertexData->vertexCount
  52. = static_cast<size_t>(skeleton.size() * 2);
  53. sub_mesh->indexData = new Ogre::IndexData();
  54. sub_mesh->indexData->indexStart = 0;
  55. sub_mesh->indexData->indexCount = sub_mesh->vertexData->vertexCount;
  56. sub_mesh->indexData->indexBuffer
  57. = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
  58. Ogre::HardwareIndexBuffer::IT_16BIT,
  59. sub_mesh->indexData->indexCount,
  60. Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY
  61. );
  62. index_data = static_cast<u16*> (
  63. sub_mesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)
  64. );
  65. cur_index = 0;
  66. Ogre::VertexDeclaration* decl = sub_mesh->vertexData->vertexDeclaration;
  67. Ogre::VertexBufferBinding* bind = sub_mesh->vertexData->vertexBufferBinding;
  68. // 1st buffer.
  69. decl->addElement(POSITION_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
  70. Ogre::HardwareVertexBufferSharedPtr vbuf0
  71. = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
  72. decl->getVertexSize(POSITION_BINDING),
  73. sub_mesh->vertexData->vertexCount,
  74. Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY
  75. );
  76. bind->setBinding(POSITION_BINDING, vbuf0);
  77. // 2nd buffer.
  78. decl->addElement(COLOUR_BINDING, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
  79. Ogre::HardwareVertexBufferSharedPtr vbuf1
  80. = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
  81. decl->getVertexSize(COLOUR_BINDING),
  82. sub_mesh->vertexData->vertexCount,
  83. Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  84. // Set vertex buffer binding so buffer 1 is bound to our colour buffer.
  85. bind->setBinding(COLOUR_BINDING, vbuf1);
  86. position = static_cast<float*> (
  87. vbuf0->lock(Ogre::HardwareBuffer::HBL_DISCARD)
  88. );
  89. std::vector<Ogre::RGBA> colours(sub_mesh->vertexData->vertexCount);
  90. DrawBone(skeleton, -1, colours.data());
  91. vbuf0->unlock();
  92. vbuf1->writeData(0, vbuf1->getSizeInBytes(), colours.data(), true);
  93. sub_mesh->indexData->indexBuffer->unlock();
  94. sub_mesh->indexData->optimiseVertexCacheTriList();
  95. }
  96. void DrawBone(const Skeleton& skeleton, int parent_index, Ogre::RGBA* colours){
  97. for (size_t i = 0; i < skeleton.size(); ++ i){
  98. if (skeleton[ i ].parent_id == parent_index){
  99. *position ++ = 0;
  100. *position ++ = 0;
  101. *position ++ = 0;
  102. *position ++ = 0;
  103. *position ++ = 0;
  104. *position ++ = 0;
  105. Ogre::ColourValue colour1 = Ogre::ColourValue(1, 0, 0);
  106. Ogre::ColourValue colour2 = Ogre::ColourValue(1, 1, 0);
  107. Ogre::RenderSystem* rs
  108. = Ogre::Root::getSingleton().getRenderSystem();
  109. rs->convertColourValue(colour1, colours + cur_index + 0);
  110. rs->convertColourValue(colour2, colours + cur_index + 1);
  111. index_data[cur_index + 0] = cur_index + 0;
  112. index_data[cur_index + 1] = cur_index + 1;
  113. Ogre::VertexBoneAssignment vba;
  114. vba.vertexIndex = cur_index + 0;
  115. vba.boneIndex = (parent_index == -1) ? 1 : parent_index * 2 + 3;
  116. vba.weight = 1.0f;
  117. sub_mesh->addBoneAssignment(vba);
  118. vba.vertexIndex = cur_index + 1;
  119. vba.boneIndex = i * 2 + 3;
  120. vba.weight = 1.0f;
  121. sub_mesh->addBoneAssignment(vba);
  122. cur_index += 2;
  123. DrawBone(skeleton, i, colours);
  124. }
  125. }
  126. }