Skip to content

Commit cd7b7c8

Browse files
committed
Implemented support for camera animation with tracking.
1 parent 130761e commit cd7b7c8

File tree

5 files changed

+94
-7
lines changed

5 files changed

+94
-7
lines changed

cmake/cppcheck-suppression-list.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// suppress Key related errors
1+
s// suppress Key related errors
22
noExplicitConstructor:*/include/vsg/core/ref_ptr.h
33
noExplicitConstructor:*/include/vsg/core/Inherit.h:31
44
noExplicitConstructor:*/include/vsg/core/Allocator.h:138
@@ -192,6 +192,7 @@ duplInheritedMember:*/src/vsg/nodes/Node.cpp
192192
shadowFunction:*/include/vsg/maths/transform.h
193193
shadowFunction:*/src/io/Path.cpp
194194
shadowFunction:*/src/vsg/animation/CameraAnimation.cpp
195+
shadowFunction:*/src/vsg/animation/CameraSampler.cpp
195196
shadowFunction:*/src/vsg/animation/TransformSampler.cpp
196197
shadowFunction:*/src/vsg/io/tile.cpp
197198
shadowFunction:*/src/vsg/io/FileSystem.cpp

include/vsg/animation/CameraAnimation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ namespace vsg
2424
class VSG_DECLSPEC CameraAnimation : public Inherit<Visitor, CameraAnimation>
2525
{
2626
public:
27-
explicit CameraAnimation(ref_ptr<Object> in_object, const Path& in_filename = "saved_animation.vsgt", ref_ptr<Options> in_options = {});
27+
CameraAnimation();
2828
CameraAnimation(ref_ptr<Object> in_object, ref_ptr<Animation> in_animation, const Path& in_filename = "saved_animation.vsgt", ref_ptr<Options> in_options = {});
29+
explicit CameraAnimation(ref_ptr<Object> in_object, const Path& in_filename = "saved_animation.vsgt", ref_ptr<Options> in_options = {});
2930

3031
/// object to track/modify
3132
ref_ptr<Object> object;

include/vsg/animation/CameraSampler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
1919
namespace vsg
2020
{
2121

22+
using time_path = time_value<RefObjectPath>;
23+
2224
class VSG_DECLSPEC CameraKeyframes : public Inherit<Object, CameraKeyframes>
2325
{
2426
public:
@@ -27,6 +29,9 @@ namespace vsg
2729
/// name of node
2830
std::string name;
2931

32+
// object tracking key frames
33+
std::vector<time_path> tracking;
34+
3035
/// position key frames
3136
std::vector<time_dvec3> origins;
3237

src/vsg/animation/CameraAnimation.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
2323

2424
using namespace vsg;
2525

26+
CameraAnimation::CameraAnimation()
27+
{
28+
}
29+
2630
CameraAnimation::CameraAnimation(ref_ptr<Object> in_object, const Path& in_filename, ref_ptr<Options> in_options) :
2731
object(in_object),
2832
filename(in_filename),
@@ -105,8 +109,11 @@ CameraAnimation::CameraAnimation(ref_ptr<Object> in_object, ref_ptr<Animation> i
105109

106110
void CameraAnimation::apply(Camera& camera)
107111
{
112+
info("CameraAnimation::apply(Camera& camera) ", cameraSampler);
113+
108114
if (cameraSampler)
109115
{
116+
110117
auto& keyframes = cameraSampler->keyframes;
111118
if (!keyframes) keyframes = CameraKeyframes::create();
112119

src/vsg/animation/CameraSampler.cpp

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ void CameraKeyframes::read(Input& input)
3636

3737
input.read("name", name);
3838

39+
// read tracking key frames
40+
uint32_t num_tracking = input.readValue<uint32_t>("tracking");
41+
tracking.resize(num_tracking);
42+
for (auto& track : tracking)
43+
{
44+
input.matchPropertyName("track");
45+
input.read(1, &track.time);
46+
input.readObjects("path", track.value);
47+
}
48+
3949
// read position key frames
4050
uint32_t num_positions = input.readValue<uint32_t>("positions");
4151
positions.resize(num_positions);
@@ -83,6 +93,17 @@ void CameraKeyframes::write(Output& output) const
8393

8494
output.write("name", name);
8595

96+
// write position key frames
97+
output.writeValue<uint32_t>("tracking", tracking.size());
98+
for (const auto& track : tracking)
99+
{
100+
output.writePropertyName("track");
101+
output.write(1, &track.time);
102+
output.writeEndOfLine();
103+
104+
output.writeObjects("path", track.value);
105+
}
106+
86107
// write position key frames
87108
output.writeValue<uint32_t>("positions", positions.size());
88109
for (const auto& position : positions)
@@ -176,6 +197,55 @@ void CameraSampler::update(double time)
176197
sample(time, keyframes->rotations, rotation);
177198
sample(time, keyframes->fieldOfViews, fieldOfView);
178199
sample(time, keyframes->nearFars, nearFar);
200+
201+
auto find_values = [](const RefObjectPath& path, dvec3& in_origin, dvec3& in_position, dquat& in_rotation) -> void
202+
{
203+
ComputeTransform ct;
204+
for(auto& obj : path) obj->accept(ct);
205+
206+
in_origin = ct.origin;
207+
208+
dvec3 scale;
209+
vsg::decompose(ct.matrix, in_position, in_rotation, scale);
210+
};
211+
212+
auto& tracking = keyframes->tracking;
213+
if (tracking.size() == 1)
214+
{
215+
find_values(tracking.front().value, origin, position, rotation);
216+
}
217+
else if (!tracking.empty())
218+
{
219+
auto pos_itr = std::lower_bound(tracking.begin(), tracking.end(), time, [](const time_path& elem, double t) -> bool { return elem.time < t; });
220+
if (pos_itr == tracking.begin())
221+
{
222+
find_values(tracking.front().value, origin, position, rotation);
223+
}
224+
else if (pos_itr == tracking.end())
225+
{
226+
find_values(tracking.back().value, origin, position, rotation);
227+
}
228+
else
229+
{
230+
auto before_pos_itr = pos_itr - 1;
231+
double delta_time = (pos_itr->time - before_pos_itr->time);
232+
double r = delta_time != 0.0 ? (time - before_pos_itr->time) / delta_time : 0.5;
233+
234+
dvec3 origin_before, position_before;
235+
dquat rotation_before;
236+
find_values(before_pos_itr->value, origin_before, position_before, rotation_before);
237+
238+
dvec3 origin_after, position_after;
239+
dquat rotation_after;
240+
find_values(pos_itr->value, origin_after, position_after, rotation_after);
241+
242+
// convert origin input values and ratio to long double to minimize the intermediate rounding errors.
243+
origin = mix(ldvec3(origin_before), ldvec3(origin_after), static_cast<long double>(r));
244+
245+
position = mix(position_before, position_after, r);
246+
rotation = mix(rotation_before, rotation_after, r);
247+
}
248+
}
179249
}
180250

181251
if (object) object->accept(*this);
@@ -186,6 +256,7 @@ double CameraSampler::maxTime() const
186256
double maxTime = 0.0;
187257
if (keyframes)
188258
{
259+
if (!keyframes->tracking.empty()) maxTime = std::max(maxTime, keyframes->tracking.back().time);
189260
if (!keyframes->origins.empty()) maxTime = std::max(maxTime, keyframes->origins.back().time);
190261
if (!keyframes->positions.empty()) maxTime = std::max(maxTime, keyframes->positions.back().time);
191262
if (!keyframes->rotations.empty()) maxTime = std::max(maxTime, keyframes->rotations.back().time);
@@ -210,8 +281,9 @@ void CameraSampler::apply(LookAt& lookAt)
210281
{
211282
if (keyframes)
212283
{
213-
if (!keyframes->origins.empty()) lookAt.origin = origin;
214-
if (!keyframes->positions.empty() || !keyframes->rotations.empty())
284+
bool has_tracking = !keyframes->tracking.empty();
285+
if (!keyframes->origins.empty() || has_tracking) lookAt.origin = origin;
286+
if (!keyframes->positions.empty() || !keyframes->rotations.empty() || has_tracking)
215287
{
216288
lookAt.set(transform());
217289
}
@@ -222,9 +294,10 @@ void CameraSampler::apply(LookDirection& lookDirection)
222294
{
223295
if (keyframes)
224296
{
225-
if (!keyframes->origins.empty()) lookDirection.origin = origin;
226-
if (!keyframes->positions.empty()) lookDirection.position = position;
227-
if (!keyframes->rotations.empty()) lookDirection.rotation = rotation;
297+
bool has_tracking = !keyframes->tracking.empty();
298+
if (!keyframes->origins.empty() || has_tracking) lookDirection.origin = origin;
299+
if (!keyframes->positions.empty() || has_tracking) lookDirection.position = position;
300+
if (!keyframes->rotations.empty() || has_tracking) lookDirection.rotation = rotation;
228301
}
229302
}
230303

0 commit comments

Comments
 (0)