Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add animation compression:draco-animation. #206

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 52 additions & 13 deletions src/FBX2glTF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,27 @@ int main(int argc, char* argv[]) {
->type_size(-1)
->type_name("(position|normal|tangent|binormial|color|uv0|uv1|auto)");

app.add_flag(
"-d,--draco", gltfOptions.draco.enabled, "Apply Draco mesh compression to geometries.")
->group("Draco");
app.add_option(
"-d,--draco",
[&](std::vector<std::string> choices) -> bool {
for (const std::string choice : choices) {
if (choice == "mesh") {
gltfOptions.draco.enabledMesh = true;
} else if (choice == "animation") {
gltfOptions.draco.enabledAnimation = true;
} else {
fmt::printf("Unknown -d,--draco: %s\n", choice);
throw CLI::RuntimeError(1);
}
}
return true;
},
"Apply Draco mesh|animation compression to geometries|animation data.")
->type_size(-1)
->type_name("(mesh|animation)");

app.add_option(
"--draco-compression-level",
"--draco-mesh-compression-level",
gltfOptions.draco.compressionLevel,
"The compression level to tune Draco to.",
true)
Expand All @@ -202,41 +217,65 @@ int main(int argc, char* argv[]) {
gltfOptions.draco.quantBitsPosition,
"How many bits to quantize position to.",
true)
->check(CLI::Range(1, 32))
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-bits-for-uv",
gltfOptions.draco.quantBitsTexCoord,
"How many bits to quantize UV coordinates to.",
true)
->check(CLI::Range(1, 32))
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-bits-for-normals",
gltfOptions.draco.quantBitsNormal,
"How many bits to quantize nornals to.",
true)
->check(CLI::Range(1, 32))
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-bits-for-colors",
gltfOptions.draco.quantBitsColor,
"How many bits to quantize colors to.",
true)
->check(CLI::Range(1, 32))
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-bits-for-other",
gltfOptions.draco.quantBitsGeneric,
"How many bits to quantize all other vertex attributes to.",
true)
->check(CLI::Range(1, 32))
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-animation-compression-level",
gltfOptions.draco.animationCompressionLevel,
"The animation compression level to tune Draco to.",
true)
->check(CLI::Range(0, 10))
->group("Draco");

app.add_option(
"--draco-bits-for-timestamp",
gltfOptions.draco.quantBitsTimestamp,
"How many bits to quantize timestamp to.",
true)
->check(CLI::Range(1, 30))
->group("Draco");

app.add_option(
"--draco-bits-for-keyframe",
gltfOptions.draco.quantBitsKeyframe,
"How many bits to quantize keyframe to.",
true)
->check(CLI::Range(1, 30))
->group("Draco");

CLI11_PARSE(app, argc, argv);

bool do_flip_u = false;
Expand All @@ -249,11 +288,11 @@ int main(int argc, char* argv[]) {
std::vector<std::function<Vec2f(Vec2f)>> texturesTransforms;
if (do_flip_u || do_flip_v) {
if (do_flip_u && do_flip_v) {
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], 1.0 - uv[1]); });
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], 1.0f - uv[1]); });
} else if (do_flip_u) {
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], uv[1]); });
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], uv[1]); });
} else {
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0 - uv[1]); });
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0f - uv[1]); });
}
}
if (verboseOutput) {
Expand Down Expand Up @@ -366,7 +405,7 @@ int main(int argc, char* argv[]) {

if (data_render_model->binary->empty() == false) {
const unsigned char* binaryData = &(*data_render_model->binary)[0];
unsigned long binarySize = data_render_model->binary->size();
size_t binarySize = data_render_model->binary->size();
if (fwrite(binaryData, binarySize, 1, fp) != 1) {
fmt::fprintf(
stderr, "ERROR: Failed to write %lu bytes to file '%s'.\n", binarySize, binaryPath);
Expand Down
15 changes: 13 additions & 2 deletions src/FBX2glTF.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,26 @@ struct GltfOptions {
/** If non-binary, whether to inline all resources, for a single (large) .glTF file. */
bool embedResources{false};

/** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */
/** Whether and how to use KHR_draco_mesh_compression & Draco_animation_compression to minimize static geometry size. */
struct {
bool enabled = false;
bool enabledMesh = false;
int compressionLevel = 7;
int quantBitsPosition = 14;
int quantBitsTexCoord = 10;
int quantBitsNormal = 10;
int quantBitsColor = 8;
int quantBitsGeneric = 8;
// int compressionLevel = -1; // 7
// int quantBitsPosition = -1; // 14
// int quantBitsTexCoord = -1; // 10
// int quantBitsNormal = -1; // 10
// int quantBitsColor = -1; // 8
// int quantBitsGeneric = -1; // 8

bool enabledAnimation = false;
int animationCompressionLevel = -1; // 5
int quantBitsTimestamp = -1;
int quantBitsKeyframe = -1;
} draco;

/** Whether to include FBX User Properties as 'extras' metadata in glTF nodes. */
Expand Down
41 changes: 41 additions & 0 deletions src/gltf/GltfModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,47 @@ class GltfModel {
return accessor;
};

template <class T>
std::shared_ptr<AccessorData> AddTimestampsToAnimation(
BufferData& buffer,
AnimationData& animationData,
const std::vector<T>& timestamps,
const GLType& glType,
const draco::DataType dracoComponentType) {
std::shared_ptr<AccessorData> accessor;
if (dracoComponentType != draco::DT_INVALID && animationData.dracoKeyframeAnimation != nullptr) {
accessor = accessors.hold(new AccessorData(glType));
accessor->count = to_uint32(timestamps.size());
animationData.AddDracoTimestamps(*accessor, timestamps);
} else {
accessor = AddAccessorAndView(buffer, glType, timestamps);
animationData.AddTimestamps(*accessor);
}
return accessor;
};

template <class T>
std::shared_ptr<AccessorData> AddChannelToAnimation(
BufferData& buffer,
AnimationData& animationData,
const NodeData& nDat,
const ChannelDefinition<T>& channelDef) {
std::shared_ptr<AccessorData> accessor;
if (channelDef.dracoComponentType != draco::DT_INVALID && animationData.dracoKeyframeAnimation != nullptr) {
accessor = accessors.hold(new AccessorData(channelDef.glType));
accessor->count = to_uint32(channelDef.channelData.size());
animationData.AddDracoNodeChannel(
nDat,
*accessor,
channelDef.path,
channelDef);
} else {
accessor = AddAccessorAndView(buffer, channelDef.glType, channelDef.channelData);
animationData.AddNodeChannel(nDat, *accessor, channelDef.path);
}
return accessor;
};

template <class T>
void serializeHolder(json& glTFJson, std::string key, const Holder<T> holder) {
if (!holder.ptrs.empty()) {
Expand Down
Loading