AnimationProcedural.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "AnimationProcedural.h"
  2. #include "AnimationService.h"
  3. dword AnimationProcedural::filesCounter[4] = {0, 0, 0, 0};
  4. AnimationProcedural::AnimationProcedural(AnimationScene & s, const IAnimationScene::Bone * skeleton, dword count, const char * _cppFile, long _cppLine) : scene(s)
  5. {
  6. Assert(skeleton);
  7. Assert(count > 0);
  8. Assert(count <= 256);
  9. refCounter = 1;
  10. bonesCount = count;
  11. //Создаём имя анимации
  12. string name = "*ProceduralFile";
  13. for(long i = 0, add = 1; i < ARRSIZE(filesCounter); i++)
  14. {
  15. name += '_';
  16. name += filesCounter[i];
  17. if(add)
  18. {
  19. add = (filesCounter[i] == 0xffffffff);
  20. filesCounter[i]++;
  21. }
  22. }
  23. //Вычисляем требуемый размер массива
  24. dword size = count*(sizeof(Matrix) + sizeof(BoneDesc)) + name.Len() + 0x20;
  25. for(dword i = 0; i < count; i++)
  26. {
  27. size += string::Len(skeleton[i].name) + 1;
  28. }
  29. buffer = NEW byte[size];
  30. memcpy(buffer, name.c_str(), name.Len() + 1);
  31. matrices = (Matrix *)(((__int64)buffer + name.Len() + 16) & ~0xf);
  32. bones = (BoneDesc *)(matrices + count);
  33. char * names = (char *)(bones + count);
  34. for(dword i = 0; i < count; i++)
  35. {
  36. matrices[i] = skeleton[i].mtx;
  37. BoneDesc & bone = bones[i];
  38. bone.parent = skeleton[i].parentIndex;
  39. bone.longName.name = names;
  40. bone.shortName.name = names;
  41. for(const char * src = skeleton[i].name; *src; *names++ = *src++)
  42. {
  43. if(*src == '|')
  44. {
  45. bone.shortName.name = names + 1;
  46. }
  47. }
  48. *names++ = 0;
  49. bones[i].longName.hash = string::HashNoCase(bones[i].longName.name);
  50. bones[i].shortName.hash = string::HashNoCase(bones[i].shortName.name);
  51. }
  52. Assert((byte *)names - buffer < (long)size);
  53. cppFile = _cppFile;
  54. cppLine = _cppLine;
  55. }
  56. AnimationProcedural::~AnimationProcedural()
  57. {
  58. AssertCoreThread
  59. delete buffer;
  60. matrices = null;
  61. bones = null;
  62. bonesCount = 0;
  63. buffer = null;
  64. scene.Delete(this);
  65. }
  66. //Получить имя анимации
  67. const char * AnimationProcedural::GetName()
  68. {
  69. return (const char *)buffer;
  70. }
  71. //Копировать интерфейс
  72. IAnimationTransform * AnimationProcedural::Clone()
  73. {
  74. Assert(refCounter > 0);
  75. refCounter++;
  76. return this;
  77. }
  78. //Удалить интерфейс
  79. void AnimationProcedural::Release()
  80. {
  81. Assert(refCounter > 0);
  82. refCounter--;
  83. if(refCounter <= 0)
  84. {
  85. delete this;
  86. }
  87. }
  88. //Удалить интерфейс принудительно
  89. void AnimationProcedural::ForceRelease()
  90. {
  91. api->Trace("Animation -> Don't release procedural animation (cpp: %s, %u)", cppFile, cppLine);
  92. refCounter = 1;
  93. Release();
  94. }
  95. //Получить количество костей в анимации
  96. long AnimationProcedural::GetNumBones()
  97. {
  98. return bonesCount;
  99. }
  100. //Получить имя кости
  101. const char * AnimationProcedural::GetBoneName(long index)
  102. {
  103. Assert(index >= 0 && index < bonesCount);
  104. return bones[index].longName.name;
  105. }
  106. //Получить индекс родительской кости
  107. long AnimationProcedural::GetBoneParent(long index)
  108. {
  109. Assert(index >= 0 && index < bonesCount);
  110. return bones[index].parent;
  111. }
  112. //Найти по имени кость
  113. long AnimationProcedural::FindBone(const char * boneName, bool shortName)
  114. {
  115. if(!boneName || !boneName[0]) return -1;
  116. dword hash = string::HashNoCase(boneName);
  117. for(long i = 0; i < bonesCount; i++)
  118. {
  119. Name & name = shortName ? bones[i].shortName : bones[i].longName;
  120. if(name.hash == hash)
  121. {
  122. if(string::IsEqual(name.name, boneName))
  123. {
  124. return i;
  125. }
  126. }
  127. }
  128. return -1;
  129. }
  130. //Найти по имени кость (короткое имя)
  131. long AnimationProcedural::FindBoneUseHash(const char * boneName, dword hash)
  132. {
  133. for(long i = 0; i < bonesCount; i++)
  134. {
  135. if(bones[i].longName.hash == hash)
  136. {
  137. if(string::IsEqual(bones[i].longName.name, boneName))
  138. {
  139. return i;
  140. }
  141. }
  142. }
  143. return -1;
  144. }
  145. //Получить матрицу кости с учётом иерархии
  146. const Matrix & AnimationProcedural::GetBoneMatrix(long index)
  147. {
  148. Assert(index >= 0 && index < bonesCount);
  149. return matrices[index];
  150. }
  151. //Получить массив матриц с учётом иерархии
  152. const Matrix * AnimationProcedural::GetBoneMatrices()
  153. {
  154. return matrices;
  155. }
  156. //Установить пользовательскую матрицу кости
  157. void AnimationProcedural::SetBoneMatrix(long index, const Matrix & mtx)
  158. {
  159. Assert(index >= 0 && index < bonesCount);
  160. matrices[index] = mtx;
  161. }
  162. //Установить нулевую матрицу кости
  163. void AnimationProcedural::CollapseBone(long index)
  164. {
  165. Assert(index >= 0 && index < bonesCount);
  166. matrices[index].SetZero();
  167. }