Skip to content

Commit 5c20d8b

Browse files
committed
gltfpack: Implement support for disabling resampling when frequency is 0
Using -af 0 now disables resampling and keeps the original time values. When resampling is disabled, we can still mark tracks as constant and remove them if they are not necessary, which cuts down on the animation size. In this mode it is more difficult to support ranges, so we assume track range will cover the relevant timespan if any tracks with time survive. Doing this analysis for cubic splines is slightly more difficult as if tangents are non-zero, an otherwise "constant" track will not result in constant output, so we disable analysis in that case for simplicity.
1 parent c1a1658 commit 5c20d8b

File tree

3 files changed

+38
-34
lines changed

3 files changed

+38
-34
lines changed

gltf/animation.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -276,39 +276,49 @@ static float getWorldScale(cgltf_node* node)
276276

277277
void processAnimation(Animation& animation, const Settings& settings)
278278
{
279-
float mint = FLT_MAX, maxt = 0;
280-
281-
for (size_t i = 0; i < animation.tracks.size(); ++i)
279+
if (settings.anim_freq)
282280
{
283-
const Track& track = animation.tracks[i];
284-
assert(!track.time.empty());
281+
float mint = FLT_MAX, maxt = 0;
285282

286-
mint = std::min(mint, track.time.front());
287-
maxt = std::max(maxt, track.time.back());
288-
}
283+
for (size_t i = 0; i < animation.tracks.size(); ++i)
284+
{
285+
const Track& track = animation.tracks[i];
286+
assert(!track.time.empty());
287+
288+
mint = std::min(mint, track.time.front());
289+
maxt = std::max(maxt, track.time.back());
290+
}
289291

290-
mint = std::min(mint, maxt);
292+
mint = std::min(mint, maxt);
291293

292-
// round the number of frames to nearest but favor the "up" direction
293-
// this means that at 100 Hz resampling, we will try to preserve the last frame <10ms
294-
// but if the last frame is <2ms we favor just removing this data
295-
int frames = 1 + int((maxt - mint) * settings.anim_freq + 0.8f);
294+
// round the number of frames to nearest but favor the "up" direction
295+
// this means that at 100 Hz resampling, we will try to preserve the last frame <10ms
296+
// but if the last frame is <2ms we favor just removing this data
297+
int frames = 1 + int((maxt - mint) * settings.anim_freq + 0.8f);
296298

297-
animation.start = mint;
298-
animation.frames = frames;
299+
animation.start = mint;
300+
animation.frames = frames;
301+
}
299302

300303
std::vector<Attr> base;
301304

302305
for (size_t i = 0; i < animation.tracks.size(); ++i)
303306
{
304307
Track& track = animation.tracks[i];
305308

306-
std::vector<Attr> result;
307-
resampleKeyframes(result, track.time, track.data, track.path, track.interpolation, track.components, frames, mint, settings.anim_freq);
309+
if (settings.anim_freq)
310+
{
311+
std::vector<Attr> result;
312+
resampleKeyframes(result, track.time, track.data, track.path, track.interpolation, track.components, animation.frames, animation.start, settings.anim_freq);
313+
314+
track.time.clear();
315+
track.data.swap(result);
316+
track.interpolation = track.interpolation == cgltf_interpolation_type_cubic_spline ? cgltf_interpolation_type_linear : track.interpolation;
317+
}
308318

309-
track.time.clear();
310-
track.data.swap(result);
311-
track.interpolation = track.interpolation == cgltf_interpolation_type_cubic_spline ? cgltf_interpolation_type_linear : track.interpolation;
319+
// getMaxDelta assumes linear/step interpolation for now
320+
if (track.interpolation == cgltf_interpolation_type_cubic_spline)
321+
continue;
312322

313323
float tolerance = getDeltaTolerance(track.path);
314324

@@ -319,7 +329,7 @@ void processAnimation(Animation& animation, const Settings& settings)
319329
tolerance /= scale == 0.f ? 1.f : scale;
320330
}
321331

322-
float deviation = getMaxDelta(track.data, track.path, frames, &track.data[0], track.components);
332+
float deviation = getMaxDelta(track.data, track.path, track.data.size(), &track.data[0], track.components);
323333

324334
if (deviation <= tolerance)
325335
{

gltf/gltfpack.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,7 @@ int main(int argc, char** argv)
13311331
}
13321332
else if (strcmp(arg, "-af") == 0 && i + 1 < argc && isdigit(argv[i + 1][0]))
13331333
{
1334-
settings.anim_freq = clamp(atoi(argv[++i]), 1, 100);
1334+
settings.anim_freq = clamp(atoi(argv[++i]), 0, 100);
13351335
}
13361336
else if (strcmp(arg, "-ac") == 0)
13371337
{
@@ -1615,7 +1615,7 @@ int main(int argc, char** argv)
16151615
fprintf(stderr, "\t-at N: use N-bit quantization for translations (default: 16; N should be between 1 and 24)\n");
16161616
fprintf(stderr, "\t-ar N: use N-bit quantization for rotations (default: 12; N should be between 4 and 16)\n");
16171617
fprintf(stderr, "\t-as N: use N-bit quantization for scale (default: 16; N should be between 1 and 24)\n");
1618-
fprintf(stderr, "\t-af N: resample animations at N Hz (default: 30)\n");
1618+
fprintf(stderr, "\t-af N: resample animations at N Hz (default: 30; use 0 to disable)\n");
16191619
fprintf(stderr, "\t-ac: keep constant animation tracks even if they don't modify the node transform\n");
16201620
fprintf(stderr, "\nScene:\n");
16211621
fprintf(stderr, "\t-kn: keep named nodes and meshes attached to named nodes so that named nodes can be transformed externally\n");

gltf/write.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,19 +1420,13 @@ void writeAnimation(std::string& json, std::vector<BufferView>& views, std::stri
14201420
{
14211421
const Track& track = *tracks[j];
14221422

1423-
if (track.time.empty())
1424-
{
1425-
assert(track.data.size() == track.components * (track.constant ? 1 : animation.frames));
1423+
size_t keyframe_size = (track.interpolation == cgltf_interpolation_type_cubic_spline) ? 3 : 1;
1424+
size_t time_size = track.constant ? 1 : (track.time.empty() ? animation.frames : track.time.size());
14261425

1427-
needs_time = needs_time || !track.constant;
1428-
needs_pose = needs_pose || track.constant;
1429-
}
1430-
else
1431-
{
1432-
size_t keyframe_size = (track.interpolation == cgltf_interpolation_type_cubic_spline) ? 3 : 1;
1426+
assert(track.data.size() == keyframe_size * track.components * time_size);
14331427

1434-
assert(track.data.size() == keyframe_size * track.components * track.time.size());
1435-
}
1428+
needs_time = needs_time || (track.time.empty() && !track.constant);
1429+
needs_pose = needs_pose || track.constant;
14361430
}
14371431

14381432
bool needs_range = needs_pose && !needs_time && animation.frames > 1;

0 commit comments

Comments
 (0)