1 #ifndef __GNUC__
2 #pragma once
3 #endif
4 #ifndef __XR_INFLUENCE_H__
5 #define __XR_INFLUENCE_H__
6
7 #include <algorithm>
8 #include "xr_fixed_vector.h"
9 #include "xr_skeleton.h"
10
11 namespace xray_re {
12
13 template<typename Tb, typename Tw> struct _bone_weight {
14 _bone_weight();
15 _bone_weight(Tb _bone, Tw _weight);
16 bool operator==(const _bone_weight<Tb, Tw>& right) const;
17 bool operator<(const _bone_weight<Tb, Tw>& right) const;
18 Tb bone;
19 Tw weight;
20 };
21
22 typedef _bone_weight<uint32_t, float> fbone_weight;
23
24 // up to 2 influences in SoC, and up to 4 in CS.
25 template<typename Tb, typename Tw> struct _influence: public _svector<_bone_weight<Tb, Tw>, 4> {
26 void set(uint32_t bone0);
27 void set(uint16_t bone0, uint16_t bone1, float weight0);
28 void set_wo_reorder(uint16_t bone0, uint16_t bone1, float weight0);
29 void set(size_t num_bones, const uint16_t* bones, const float* weights);
30 void reorder();
31 };
32
33 typedef _influence<uint32_t, float> finfluence;
34
_bone_weight()35 template<typename Tb, typename Tw> inline _bone_weight<Tb, Tw>::_bone_weight():
36 bone(0), weight(Tw(1)) {}
37
_bone_weight(Tb _bone,Tw _weight)38 template<typename Tb, typename Tw> inline _bone_weight<Tb, Tw>::_bone_weight(Tb _bone, Tw _weight):
39 bone(_bone), weight(_weight) {}
40
41 template<typename Tb, typename Tw> inline
42 bool _bone_weight<Tb, Tw>::operator==(const _bone_weight<Tb, Tw>& right) const
43 {
44 return bone == right.bone && weight == right.weight;
45 }
46
47 template<typename Tb, typename Tw> inline
48 bool _bone_weight<Tb, Tw>::operator<(const _bone_weight<Tb, Tw>& right) const
49 {
50 return bone < right.bone || (bone == right.bone && weight < right.weight);
51 }
52
set(uint32_t bone0)53 template<typename Tb, typename Tw> inline void _influence<Tb, Tw>::set(uint32_t bone0)
54 {
55 this->push_back(_bone_weight<Tb, Tw>(bone0, Tw(1)));
56 }
57
58 template<typename Tb, typename Tw>
set(uint16_t bone0,uint16_t bone1,float weight0)59 void _influence<Tb, Tw>::set(uint16_t bone0, uint16_t bone1, float weight0)
60 {
61 #if 0
62 assert(weight0 >= 0.f && weight0 <= 1.f);
63 assert(bone0 < MAX_BONES && bone1 < MAX_BONES);
64 #endif
65 if (bone0 == bone1) {
66 this->push_back(_bone_weight<Tb, Tw>(bone0, Tw(1)));
67 } else {
68 _bone_weight<Tb, Tw> bw0(bone0, Tw(1.f - weight0));
69 _bone_weight<Tb, Tw> bw1(bone1, Tw(weight0));
70 #if 0
71 xr_assert(weight0 != 0);
72 xr_assert(1.f != weight0);
73 xr_assert(!equivalent<Tw>(weight0, 0));
74 xr_assert(!equivalent<Tw>(1.f - weight0, 0));
75 #endif
76 if (bw0 < bw1) {
77 this->push_back(bw0);
78 this->push_back(bw1);
79 } else {
80 this->push_back(bw1);
81 this->push_back(bw0);
82 }
83 }
84 }
85
86 template<typename Tb, typename Tw>
set_wo_reorder(uint16_t bone0,uint16_t bone1,float weight0)87 void _influence<Tb, Tw>::set_wo_reorder(uint16_t bone0, uint16_t bone1, float weight0)
88 {
89 if (bone0 == bone1) {
90 this->push_back(_bone_weight<Tb, Tw>(bone0, Tw(1)));
91 } else {
92 _bone_weight<Tb, Tw> bw0(bone0, Tw(1.f - weight0));
93 _bone_weight<Tb, Tw> bw1(bone1, Tw(weight0));
94 this->push_back(bw0);
95 this->push_back(bw1);
96 }
97 }
98
99 template<typename Tb, typename Tw>
set(size_t num_bones,const uint16_t * bones,const float * weights)100 void _influence<Tb, Tw>::set(size_t num_bones, const uint16_t* bones, const float* weights)
101 {
102 for (float sum = 0, w; num_bones;) {
103 if (--num_bones == 0) {
104 w = 1.f - sum;
105 } else {
106 w = *weights++;
107 sum += w;
108 }
109 _bone_weight<Tb, Tw> bw(*bones++, w);
110 for (typename _influence<Tb, Tw>::iterator it = _influence<Tb, Tw>::begin(),
111 last = _influence<Tb, Tw>::end(); it != last; ++it) {
112 if (it->bone == bw.bone) {
113 #if 0
114 if (!equivalent<Tw>(w, 0)) {
115 msg("bone%u, w=%f", bw.bone, w);
116 }
117 xr_assert(equivalent<Tw>(w, 0));
118 #endif
119 goto skip;
120 }
121 }
122 this->push_back(bw);
123 skip:;
124 }
125 reorder();
126 }
127
reorder()128 template<typename Tb, typename Tw> void _influence<Tb, Tw>::reorder()
129 {
130 std::sort(_influence<Tb, Tw>::begin(), _influence<Tb, Tw>::end());
131 }
132
133 } // end of namespace xray_re
134
135 #endif
136