/include/Object/Body/Body_skinned.cpp

http://narutortsproject.googlecode.com/ · C++ · 251 lines · 192 code · 45 blank · 14 comment · 48 complexity · 4fd0a0334b570410fba182f4c9d1f29a MD5 · raw file

  1. #include "Body_skinned.h"
  2. #include <stdio.h>
  3. #include "../../Graphick/OpenGL/OpenGlSL.h"
  4. #include "../../tools/tools.h"
  5. Body_skinned::Body_skinned()
  6. {
  7. m_body_type = TYPE_SKINNED;
  8. m_hw_skinning_prepared = false;
  9. m_bone_matrix = 0;
  10. };
  11. Body_skinned::~Body_skinned()
  12. {
  13. if (m_bone_matrix)
  14. delete [] m_bone_matrix;
  15. }
  16. void Body_skinned::InitSkin()
  17. {
  18. if (!m_mesh)
  19. return;
  20. //Allocate and copy vertex
  21. m_mesh->m_base_vertex.Create(m_mesh->m_vertex.m_point_count);
  22. memcpy(m_mesh->m_base_vertex.m_point, m_mesh->m_vertex.m_point, m_mesh->m_vertex.m_point_count*sizeof(Tpoint3f));
  23. if (m_mesh->m_normal.m_point_count > 0)
  24. {
  25. m_mesh->m_base_normal.Create(m_mesh->m_normal.m_point_count);
  26. memcpy(m_mesh->m_base_normal.m_point, m_mesh->m_normal.m_point, m_mesh->m_normal.m_point_count*sizeof(Tpoint3f));
  27. };
  28. };
  29. Bone* Body_skinned::AddBone(int weight_count, Body_base * body)
  30. {
  31. Bone* bone = m_bone.add();
  32. bone->Initialize(weight_count, body);
  33. m_hw_skinning_prepared = false; //ReInit
  34. return bone;
  35. };
  36. Bone* Body_skinned::GetBone(int i)
  37. {
  38. if (i < 0 || i >= m_bone.count)
  39. return 0;
  40. return (m_bone.item[i]);
  41. };
  42. void Body_skinned::InitializeHwSkinning()
  43. {
  44. //HW skinning preparing
  45. m_mesh->m_skin_attrib_bone_index.Create(m_mesh->m_vertex.m_point_count);
  46. m_mesh->m_skin_attrib_bone_weight.Create(m_mesh->m_vertex.m_point_count);
  47. char* weight_count = new char[m_mesh->m_vertex.m_point_count];
  48. for (int i = 0; i < m_mesh->m_vertex.m_point_count; i ++)
  49. {
  50. weight_count[i] = 0;
  51. m_mesh->m_skin_attrib_bone_index.m_point[i].r = 255;
  52. m_mesh->m_skin_attrib_bone_index.m_point[i].g = 255;
  53. m_mesh->m_skin_attrib_bone_index.m_point[i].b = 255;
  54. m_mesh->m_skin_attrib_bone_index.m_point[i].a = 255;
  55. m_mesh->m_skin_attrib_bone_weight.m_point[i].a = 0.0f;
  56. m_mesh->m_skin_attrib_bone_weight.m_point[i].b = 0.0f;
  57. m_mesh->m_skin_attrib_bone_weight.m_point[i].c = 0.0f;
  58. m_mesh->m_skin_attrib_bone_weight.m_point[i].d = 0.0f;
  59. }
  60. //
  61. for (int i = 0; i < m_bone.count; i ++)
  62. {
  63. Bone* bone = m_bone.item[i];
  64. if (bone->m_weight_count == 0)
  65. continue;
  66. for (int n = 0; n < bone->m_weight_count; n ++)
  67. {
  68. int vertex_id = bone->m_index[n];
  69. float weight = bone->m_weight[n];
  70. if (weight_count[vertex_id] >= 4)
  71. {
  72. printf(" --- To many weight per vertex ---\n");
  73. } else
  74. {
  75. if (weight_count[vertex_id] == 0)
  76. {
  77. m_mesh->m_skin_attrib_bone_index.m_point[vertex_id].r = i;
  78. m_mesh->m_skin_attrib_bone_weight.m_point[vertex_id].a = weight;
  79. }
  80. if (weight_count[vertex_id] == 1)
  81. {
  82. m_mesh->m_skin_attrib_bone_index.m_point[vertex_id].g = i;
  83. m_mesh->m_skin_attrib_bone_weight.m_point[vertex_id].b = weight;
  84. }
  85. if (weight_count[vertex_id] == 2)
  86. {
  87. m_mesh->m_skin_attrib_bone_index.m_point[vertex_id].b = i;
  88. m_mesh->m_skin_attrib_bone_weight.m_point[vertex_id].c = weight;
  89. }
  90. if (weight_count[vertex_id] == 3)
  91. {
  92. m_mesh->m_skin_attrib_bone_index.m_point[vertex_id].a = i;
  93. m_mesh->m_skin_attrib_bone_weight.m_point[vertex_id].d = weight;
  94. }
  95. weight_count[vertex_id] ++;
  96. }
  97. }
  98. };
  99. delete [] weight_count;
  100. if (m_bone_matrix)
  101. delete m_bone_matrix;
  102. m_bone_matrix = new Tmatrix[m_bone.count];
  103. m_hw_skinning_prepared = true;
  104. };
  105. void Body_skinned::Control(double time)
  106. {
  107. if (!m_enable)
  108. return;
  109. if (!m_mesh || m_mesh->m_base_vertex.m_point_count <= 0)
  110. return;
  111. if (!m_hw_skinning_prepared)
  112. InitializeHwSkinning();
  113. m_control_counter ++;
  114. if (m_out_of_view)
  115. return;
  116. if (m_out_lod == 1 && m_control_counter % 4 == 0)
  117. return;
  118. if (m_out_lod == 2 && m_control_counter % 2 == 0)
  119. return;
  120. //if (m_control_counter % 3 == 0)
  121. // return;
  122. //!!!!! need to implement zero bone !!!!
  123. //Faster is calculate initial_skin point array and removed zero initialization
  124. //Prepare to animation
  125. //memcpy(m_mesh->m_vertex.m_point, m_mesh->m_base_vertex.m_point, m_mesh->m_vertex.m_point_count*sizeof(Tpoint3f));
  126. bool hw_skinning = true;
  127. Tpoint3f* vertex = m_mesh->m_vertex.m_point;
  128. Tpoint3f* vertex_base = m_mesh->m_base_vertex.m_point;
  129. if (!hw_skinning)
  130. memset(vertex, 0, sizeof(Tpoint3f)*m_mesh->m_base_vertex.m_point_count);
  131. Tpoint3f* normal = 0;
  132. Tpoint3f* normal_base = 0;
  133. if (!hw_skinning)
  134. if (m_mesh->m_normal.m_point_count > 0 && m_mesh->m_base_normal.m_point_count > 0)
  135. {
  136. normal = m_mesh->m_normal.m_point;
  137. normal_base = m_mesh->m_base_normal.m_point;
  138. memset(normal, 0, sizeof(Tpoint3f)*m_mesh->m_base_normal.m_point_count);
  139. }
  140. //Apply bone animation
  141. for (int i = 0; i < m_bone.count; i ++)
  142. {
  143. Bone* bone = m_bone.item[i];
  144. if (bone->m_weight_count == 0)
  145. continue;
  146. //Get current deformation bone matrix
  147. Tmatrix body_matrix;
  148. bone->m_node_boby->GetMatrix(body_matrix);
  149. Tmatrix r_matrix;
  150. r_matrix.intialize();
  151. MultMatrixf(r_matrix.matrix.elements_16, m_inv_matrix.matrix.elements_16);
  152. MultMatrixf(r_matrix.matrix.elements_16, body_matrix.matrix.elements_16);
  153. MultMatrixf(r_matrix.matrix.elements_16, bone->m_init_matrix_inv.matrix.elements_16);
  154. MultMatrixf(r_matrix.matrix.elements_16, m_matrix.matrix.elements_16);
  155. if (hw_skinning)
  156. memcpy(m_bone_matrix + i, &r_matrix, sizeof(Tmatrix)); //copy matrix to buffer
  157. float* mt = r_matrix.matrix.elements_16;
  158. //Apply transformation
  159. if (!hw_skinning)
  160. for (int n = 0; n < bone->m_weight_count; n ++)
  161. {
  162. int id = bone->m_index[n];
  163. float x = vertex_base[id].x;
  164. float y = vertex_base[id].y;
  165. float z = vertex_base[id].z;
  166. float weight = bone->m_weight[n];
  167. //float iweight = 1.0f - weight;
  168. vertex[id].x += weight*(mt[0]*x + mt[4]*y + mt[8 ]*z + mt[12]);
  169. vertex[id].y += weight*(mt[1]*x + mt[5]*y + mt[9 ]*z + mt[13]);
  170. vertex[id].z += weight*(mt[2]*x + mt[6]*y + mt[10]*z + mt[14]);
  171. if (normal)
  172. {
  173. x = normal_base[id].x;
  174. y = normal_base[id].y;
  175. z = normal_base[id].z;
  176. normal[id].x += weight*(mt[0]*x + mt[4]*y + mt[8 ]*z);
  177. normal[id].y += weight*(mt[1]*x + mt[5]*y + mt[9 ]*z);
  178. normal[id].z += weight*(mt[2]*x + mt[6]*y + mt[10]*z);
  179. }
  180. };
  181. };
  182. //if (m_control_counter % 5 == 0)
  183. m_mesh->CaclulateBbox();
  184. };
  185. void Body_skinned::ReplaceBone(long long old_id, Body_base * body)
  186. {
  187. for (int i = 0; i < m_bone.count; i ++)
  188. {
  189. if (m_bone.item[i]->m_node_boby->GetId() == old_id)
  190. {
  191. m_bone.item[i]->m_node_boby = body;
  192. };
  193. };
  194. };
  195. void Body_skinned::Paint()
  196. {
  197. if (m_gr_shader)
  198. {
  199. m_gr_shader->Enable();
  200. m_gr_shader->SetBoneMatrixArray(m_bone_matrix, m_bone.count);
  201. m_gr_shader->Disable();
  202. m_mesh->m_skin_attrib_bone_index_location = ((GlslShader*)m_gr_shader)->m_location_bone_index;
  203. m_mesh->m_skin_attrib_bone_weight_location = ((GlslShader*)m_gr_shader)->m_location_bone_weight;
  204. }
  205. Body_base::Paint();
  206. };