• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PredatorCZ / RevilLib / 162

17 Jun 2025 03:12PM UTC coverage: 11.187% (-0.06%) from 11.245%
162

push

github

PredatorCZ
smaller bugfixes

2 of 28 new or added lines in 4 files covered. (7.14%)

428 existing lines in 3 files now uncovered.

757 of 6767 relevant lines covered (11.19%)

6698.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/reng/motion_43.cpp
1
/*  Revil Format Library
2
    Copyright(C) 2017-2020 Lukas Cone
3

4
    This program is free software : you can redistribute it and / or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation, either version 3 of the License, or
7
    (at your option) any later version.
8

9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12
    GNU General Public License for more details.
13

14
    You should have received a copy of the GNU General Public License
15
    along with this program.If not, see <https://www.gnu.org/licenses/>.
16
*/
17

18
#include "motion_43.hpp"
19

20
template <> void ProcessClass(REMotionBone &item, ProcessFlags flags) {
×
21
  es::FixupPointers(flags.base, *flags.ptrStore, item.boneName,
×
22
                    item.parentBoneNamePtr, item.firstChildBoneNamePtr,
×
23
                    item.lastChildBoneNamePtr);
×
24
}
25

26
template <> void ProcessClass(RETrackCurve43 &item, ProcessFlags flags) {
×
27
  es::FixupPointers(flags.base, *flags.ptrStore, item.frames,
×
28
                    item.controlPoints, item.minMaxBounds);
×
29
}
30

31
template <> void ProcessClass(REMotionTrack43 &item, ProcessFlags flags) {
×
32
  if (!es::FixupPointers(flags.base, *flags.ptrStore, item.curves)) {
×
33
    return;
34
  }
35

36
  uint32 numUsedCurves = 0;
37

38
  for (uint32 t = 0; t < 3; t++) {
×
39
    if (item.usedCurves[static_cast<REMotionTrack43::TrackType>(t)]) {
×
40
      ProcessClass(item.curves[numUsedCurves++], flags);
×
41
    }
42
  }
43
}
44

45
template <> void ProcessClass(REMotion43 &item, ProcessFlags flags) {
×
46
  flags.base = reinterpret_cast<char *>(&item);
47
  if (!es::FixupPointers(flags.base, *flags.ptrStore, item.bones, item.tracks,
×
48
                         item.unkOffset02, item.animationName)) {
×
49
    return;
50
  }
51

52
  if (item.bones) {
×
53
    item.bones->ptr.Fixup(flags.base);
54
  }
55

56
  for (size_t b = 0; b < item.numBones; b++) {
×
57
    ProcessClass(item.bones->ptr[b], flags);
×
58
  }
59

60
  for (size_t b = 0; b < item.numTracks; b++) {
×
61
    ProcessClass(item.tracks[b], flags);
×
62
  }
63
}
64

65
// https://en.wikipedia.org/wiki/Slerp
66
static Vector4A16 slerp(const Vector4A16 &v0, const Vector4A16 &_v1, float t) {
67
  Vector4A16 v1 = _v1;
×
68
  float dot = v0.Dot(v1);
69

70
  // If the dot product is negative, slerp won't take
71
  // the shorter path. Fix by reversing one quaternion.
72
  if (dot < 0.0f) {
×
73
    v1 *= -1;
74
    dot *= -1;
×
75
  }
76

77
  static const float DOT_THRESHOLD = 0.9995f;
78
  if (dot > DOT_THRESHOLD) {
×
79
    // If the inputs are too close for comfort, linearly interpolate
80
    // and normalize the result.
81

82
    Vector4A16 result = v0 + (v1 - v0) * t;
83
    return result.Normalize();
×
84
  }
85

86
  const float theta00 = acos(dot);   // theta00 = angle between input vectors
×
87
  const float theta01 = theta00 * t; // theta01 = angle between v0 and result
×
88
  const float theta02 = sin(theta01);
×
89
  const float theta03 = 1.0f / sin(theta00);
×
90
  const float s0 = cos(theta01) - dot * theta02 * theta03;
×
91
  const float s1 = theta02 * theta03;
×
92

93
  return (v0 * s0) + (v1 * s1);
×
94
}
95

96
void REMotionTrackWorker::GetValue(Vector4A16 &output, float time) const {
×
97
  // bugfix, some codecs will partialy apply elements, ensure we have identity
NEW
98
  output = Vector4A16{};
×
99

UNCOV
100
  if (!controller) {
×
101
    return;
102
  }
103

104
  if (time <= 0.0f || numFrames == 1) {
×
105
    controller->Evaluate(0, output);
×
106
    return;
×
107
  }
108

109
  float frameDelta = time * 60.f;
×
110
  auto span = controller->GetSpan(frameDelta);
×
111

112
  if (span.offset >= numFrames) {
×
113
    controller->Evaluate(numFrames - 1, output);
×
114
    return;
×
115
  }
116

117
  const float fFrameBegin = static_cast<float>(span.first);
×
118
  const float fFrameEnd = static_cast<float>(span.second);
×
119

120
  if (span.first == span.second) {
×
121
    frameDelta = 0.f;
122
  } else {
123
    frameDelta = (fFrameBegin - frameDelta) / (fFrameBegin - fFrameEnd);
×
124
  }
125

126
  controller->Evaluate(span.offset - 1, output);
×
127

128
  if (frameDelta > FLT_EPSILON) {
×
129
    Vector4A16 nextValue;
130
    controller->Evaluate(span.offset, nextValue);
×
131

132
    if (cType == TrackType_e::Rotation) {
×
133
      output = slerp(output, nextValue, frameDelta);
×
134
    } else {
135
      output = output + (nextValue - output) * frameDelta;
136
    }
137
  }
138
}
139

140
void REMotion43Asset::Build() {
×
141
  const uint32 numTracks = Get().numTracks;
×
142

143
  for (uint32 t = 0; t < numTracks; t++) {
×
144
    auto tck = Get().tracks.operator->() + t;
×
145
    size_t curCurve = 0;
146

147
    if (tck->usedCurves[REMotionTrack43::TrackType_Position]) {
×
148
      REMotionTrackWorker wk;
149
      auto data = &tck->curves[curCurve++];
150
      wk.controller = data->GetController();
×
151
      wk.cType = REMotionTrackWorker::Position;
×
152
      wk.boneHash = tck->boneHash;
×
153
      wk.numFrames = data->numFrames;
×
154
      storage.emplace_back(std::move(wk));
×
155
    }
156

157
    if (tck->usedCurves[REMotionTrack43::TrackType_Rotation]) {
×
158
      REMotionTrackWorker wk;
159
      auto data = &tck->curves[curCurve++];
×
160
      wk.controller = data->GetController();
×
161
      wk.cType = REMotionTrackWorker::Rotation;
×
162
      wk.boneHash = tck->boneHash;
×
163
      wk.numFrames = data->numFrames;
×
164
      storage.emplace_back(std::move(wk));
×
165
    }
166

167
    if (tck->usedCurves[REMotionTrack43::TrackType_Scale]) {
×
168
      REMotionTrackWorker wk;
169
      auto data = &tck->curves[curCurve++];
×
170
      wk.controller = data->GetController();
×
171
      wk.cType = REMotionTrackWorker::Scale;
×
172
      wk.boneHash = tck->boneHash;
×
173
      wk.numFrames = data->numFrames;
×
174
      storage.emplace_back(std::move(wk));
×
175
    }
176
  }
177
}
178

179
void REMotion43Asset::Fixup(std::vector<void *> &ptrStore) {
×
180
  ProcessFlags flags;
181
  flags.ptrStore = &ptrStore;
×
182
  ProcessClass(Get(), flags);
×
183
  Build();
×
184
}
185

186
namespace revil {
187
template <> ES_EXPORT uni::Element<const uni::Motion> REAsset::As<>() const {
×
188
  auto val = i->AsMotion();
×
189
  return {static_cast<const uni::Motion *>(val.release()), false};
×
190
}
191

192
template <> ES_EXPORT uni::MotionsConst REAsset::As<>() const {
×
193
  auto val = i->AsMotions();
×
194
  return {static_cast<typename uni::MotionsConst::pointer>(val.release()),
195
          false};
×
196
}
197
} // namespace revil
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc