Skip to content
Closed
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
5 changes: 3 additions & 2 deletions momentum/examples/convert_model/convert_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ int main(int argc, char** argv) {
// save output
if (oextension == ".fbx") {
MT_LOGI("Saving fbx file...");
saveFbx(
options->output_model_file, character, poses, offsets, fps, options->character_mesh_save);
FileSaveOptions fbxOptions;
fbxOptions.mesh = options->character_mesh_save;
saveFbx(options->output_model_file, character, poses, offsets, fps, {}, fbxOptions);
} else if (oextension == ".glb" || oextension == ".gltf") {
MT_LOGI("Saving gltf/glb file...");
if (hasMotion) {
Expand Down
49 changes: 4 additions & 45 deletions momentum/io/character_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,36 +155,18 @@ void saveCharacter(
filename.string());

if (format == CharacterFormat::Gltf) {
// Convert FileSaveOptions to GltfOptions
GltfOptions gltfOptions;
gltfOptions.extensions = options.extensions;
gltfOptions.collisions = options.collisions;
gltfOptions.locators = options.locators;
gltfOptions.mesh = options.mesh;
gltfOptions.blendShapes = options.blendShapes;

saveGltfCharacter(
filename,
character,
fps,
{character.parameterTransform.name, motion},
{},
markerSequence,
options.gltfFileFormat,
gltfOptions);
options);
} else if (format == CharacterFormat::Fbx) {
// Save as FBX
saveFbx(
filename,
character,
motion,
VectorXf(),
static_cast<double>(fps),
options.mesh,
options.coordSystemInfo,
options.permissive,
markerSequence,
options.fbxNamespace);
filename, character, motion, VectorXf(), static_cast<double>(fps), markerSequence, options);
} else {
MT_THROW(
"{} is not a supported format. Supported formats: .fbx, .glb, .gltf", filename.string());
Expand All @@ -206,34 +188,11 @@ void saveCharacter(
filename.string());

if (format == CharacterFormat::Gltf) {
// Convert FileSaveOptions to GltfOptions
GltfOptions gltfOptions;
gltfOptions.extensions = options.extensions;
gltfOptions.collisions = options.collisions;
gltfOptions.locators = options.locators;
gltfOptions.mesh = options.mesh;
gltfOptions.blendShapes = options.blendShapes;

saveGltfCharacter(
filename,
character,
fps,
skeletonStates,
markerSequence,
options.gltfFileFormat,
gltfOptions);
saveGltfCharacter(filename, character, fps, skeletonStates, markerSequence, options);
} else if (format == CharacterFormat::Fbx) {
// Save as FBX
saveFbxWithSkeletonStates(
filename,
character,
skeletonStates,
static_cast<double>(fps),
options.mesh,
options.coordSystemInfo,
options.permissive,
markerSequence,
options.fbxNamespace);
filename, character, skeletonStates, static_cast<double>(fps), markerSequence, options);
} else {
MT_THROW(
"{} is not a supported format. Supported formats: .fbx, .glb, .gltf", filename.string());
Expand Down
89 changes: 22 additions & 67 deletions momentum/io/fbx/fbx_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,134 +795,100 @@ MarkerSequence loadFbxMarkerSequence(const filesystem::path& filename, bool stri
void saveFbx(
const filesystem::path& filename,
const Character& character,
const MatrixXf& poses, // model parameters
const MatrixXf& poses,
const VectorXf& identity,
const double framerate,
const bool saveMesh,
const FbxCoordSystemInfo& coordSystemInfo,
const bool permissive,
std::span<const std::vector<Marker>> markerSequence,
std::string_view fbxNamespace) {
const FileSaveOptions& options) {
CharacterParameters params;
if (identity.size() == character.parameterTransform.numJointParameters()) {
params.offsets = identity;
} else {
params.offsets = character.parameterTransform.bindPose();
}

// first convert model parameters to joint values
CharacterState state;
MatrixXf jointValues;
if (poses.cols() > 0) {
// Set the initial pose to initialize the state
params.pose = poses.col(0);
state.set(params, character, false, false, false);

// Resize the jointValues matrix based on the size of joint parameters and number of poses
jointValues.resize(state.skeletonState.jointParameters.v.size(), poses.cols());

// Store the joint parameters for the initial pose
jointValues.col(0) = state.skeletonState.jointParameters.v;

// Iterate through each subsequent pose
for (Eigen::Index f = 1; f < poses.cols(); f++) {
// set the current pose
params.pose = poses.col(f);
state.set(params, character, false, false, false);
jointValues.col(f) = state.skeletonState.jointParameters.v;
}
}

// Call the helper function to save FBX file with joint values
saveFbxCommon(
filename,
character,
jointValues,
framerate,
saveMesh,
options.mesh,
false,
coordSystemInfo,
permissive,
options.coordSystemInfo,
options.permissive,
markerSequence,
fbxNamespace);
options.fbxNamespace);
}

void saveFbxWithJointParams(
const filesystem::path& filename,
const Character& character,
const MatrixXf& jointParams,
const double framerate,
const bool saveMesh,
const FbxCoordSystemInfo& coordSystemInfo,
const bool permissive,
std::span<const std::vector<Marker>> markerSequence,
std::string_view fbxNamespace) {
// Call the helper function to save FBX file with joint values.
// Set skipActiveJointParamCheck=true to skip the active joint param check as the joint params are
// passed in directly from user.
const FileSaveOptions& options) {
saveFbxCommon(
filename,
character,
jointParams,
framerate,
saveMesh,
options.mesh,
true,
coordSystemInfo,
permissive,
options.coordSystemInfo,
options.permissive,
markerSequence,
fbxNamespace);
options.fbxNamespace);
}

void saveFbxWithSkeletonStates(
const filesystem::path& filename,
const Character& character,
std::span<const SkeletonState> skeletonStates,
const double framerate,
const bool saveMesh,
const FbxCoordSystemInfo& coordSystemInfo,
const bool permissive,
std::span<const std::vector<Marker>> markerSequence,
std::string_view fbxNamespace) {
const FileSaveOptions& options) {
const size_t nFrames = skeletonStates.size();
MatrixXf jointParams(character.parameterTransform.zero().v.size(), nFrames);
for (size_t iFrame = 0; iFrame < nFrames; ++iFrame) {
jointParams.col(iFrame) =
skeletonStateToJointParameters(skeletonStates[iFrame], character.skeleton).v;
}

// Call the helper function to save FBX file with joint values.
// Set skipActiveJointParamCheck=true to skip the active joint param check as the joint params are
// passed in directly from user.
saveFbxCommon(
filename,
character,
jointParams,
framerate,
saveMesh,
options.mesh,
true,
coordSystemInfo,
permissive,
options.coordSystemInfo,
options.permissive,
markerSequence,
fbxNamespace);
options.fbxNamespace);
}

void saveFbxModel(
const filesystem::path& filename,
const Character& character,
const FbxCoordSystemInfo& coordSystemInfo,
bool permissive,
std::string_view fbxNamespace) {
saveFbx(
filename,
character,
MatrixXf(),
VectorXf(),
120.0,
true,
coordSystemInfo,
permissive,
{},
fbxNamespace);
const FileSaveOptions& options) {
saveFbx(filename, character, MatrixXf(), VectorXf(), 120.0, {}, options);
}

#else // !MOMENTUM_WITH_FBX_SDK
Expand All @@ -933,11 +899,8 @@ void saveFbx(
const MatrixXf& /* poses */,
const VectorXf& /* identity */,
const double /* framerate */,
const bool /* saveMesh */,
const FbxCoordSystemInfo& /* coordSystemInfo */,
const bool /* permissive */,
std::span<const std::vector<Marker>> /* markerSequence */,
std::string_view /* fbxNamespace */) {
const FileSaveOptions& /* options */) {
MT_THROW(
"FBX saving is not supported in OpenFBX-only mode. FBX loading is available via OpenFBX, but saving requires the full Autodesk FBX SDK.");
}
Expand All @@ -947,11 +910,8 @@ void saveFbxWithJointParams(
const Character& /* character */,
const MatrixXf& /* jointParams */,
const double /* framerate */,
const bool /* saveMesh */,
const FbxCoordSystemInfo& /* coordSystemInfo */,
const bool /* permissive */,
std::span<const std::vector<Marker>> /* markerSequence */,
std::string_view /* fbxNamespace */) {
const FileSaveOptions& /* options */) {
MT_THROW(
"FBX saving is not supported in OpenFBX-only mode. FBX loading is available via OpenFBX, but saving requires the full Autodesk FBX SDK.");
}
Expand All @@ -961,21 +921,16 @@ void saveFbxWithSkeletonStates(
const Character& /* character */,
std::span<const SkeletonState> /* skeletonStates */,
const double /* framerate */,
const bool /* saveMesh */,
const FbxCoordSystemInfo& /* coordSystemInfo */,
const bool /* permissive */,
std::span<const std::vector<Marker>> /* markerSequence */,
std::string_view /* fbxNamespace */) {
const FileSaveOptions& /* options */) {
MT_THROW(
"FBX saving is not supported in OpenFBX-only mode. FBX loading is available via OpenFBX, but saving requires the full Autodesk FBX SDK.");
}

void saveFbxModel(
const filesystem::path& /* filename */,
const Character& /* character */,
const FbxCoordSystemInfo& /* coordSystemInfo */,
bool /* permissive */,
std::string_view /* fbxNamespace */) {
const FileSaveOptions& /* options */) {
MT_THROW(
"FBX saving is not supported in OpenFBX-only mode. FBX loading is available via OpenFBX, but saving requires the full Autodesk FBX SDK.");
}
Expand Down
43 changes: 9 additions & 34 deletions momentum/io/fbx/fbx_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,80 +67,55 @@ std::tuple<Character, std::vector<MatrixXf>, float> loadFbxCharacterWithMotion(
/// @param poses Model parameters for each frame (empty for bind pose only)
/// @param identity Identity pose parameters (empty to use bind pose)
/// @param framerate Animation framerate in frames per second
/// @param saveMesh Whether to include mesh geometry in the output
/// @param coordSystemInfo Coordinate system configuration for the FBX file
/// @param permissive Permissive mode allows saving mesh-only characters (without skin weights)
/// @param fbxNamespace Optional namespace to prepend to all node names (e.g., "ns" will become
/// "ns:")
/// @param markerSequence Optional marker sequence data to save with the character
/// @param options Optional file save options for controlling output (default: FileSaveOptions{})
void saveFbx(
const filesystem::path& filename,
const Character& character,
const MatrixXf& poses = MatrixXf(),
const VectorXf& identity = VectorXf(),
double framerate = 120.0,
bool saveMesh = false,
const FbxCoordSystemInfo& coordSystemInfo = FbxCoordSystemInfo(),
bool permissive = false,
std::span<const std::vector<Marker>> markerSequence = {},
std::string_view fbxNamespace = "");
const FileSaveOptions& options = FileSaveOptions());

/// Save a character with animation using joint parameters directly.
/// @param filename Path to the output FBX file
/// @param character The character to save
/// @param jointParams Joint parameters for each frame (empty for bind pose only)
/// @param framerate Animation framerate in frames per second
/// @param saveMesh Whether to include mesh geometry in the output
/// @param coordSystemInfo Coordinate system configuration for the FBX file
/// @param permissive Permissive mode allows saving mesh-only characters (without skin weights)
/// @param markerSequence Optional marker sequence data to save with the character
/// @param fbxNamespace Optional namespace to prepend to all node names (e.g., "ns" will become
/// "ns:")
/// @param options Optional file save options for controlling output (default: FileSaveOptions{})
void saveFbxWithJointParams(
const filesystem::path& filename,
const Character& character,
const MatrixXf& jointParams = MatrixXf(),
double framerate = 120.0,
bool saveMesh = false,
const FbxCoordSystemInfo& coordSystemInfo = FbxCoordSystemInfo(),
bool permissive = false,
std::span<const std::vector<Marker>> markerSequence = {},
std::string_view fbxNamespace = "");
const FileSaveOptions& options = FileSaveOptions());

/// Save a character with animation using skeleton states directly.
/// @param filename Path to the output FBX file
/// @param character The character to save
/// @param skeletonStates SkeletonState for each frame (empty for bind pose only)
/// @param framerate Animation framerate in frames per second
/// @param saveMesh Whether to include mesh geometry in the output
/// @param coordSystemInfo Coordinate system configuration for the FBX file
/// @param permissive Permissive mode allows saving mesh-only characters (without skin weights)
/// @param markerSequence Optional marker sequence data to save with the character
/// @param fbxNamespace Optional namespace to prepend to all node names (e.g., "ns" will become
/// "ns:")
/// @param options Optional file save options for controlling output (default: FileSaveOptions{})
void saveFbxWithSkeletonStates(
const filesystem::path& filename,
const Character& character,
std::span<const SkeletonState> skeletonStates,
double framerate = 120.0,
bool saveMesh = false,
const FbxCoordSystemInfo& coordSystemInfo = FbxCoordSystemInfo(),
bool permissive = false,
std::span<const std::vector<Marker>> markerSequence = {},
std::string_view fbxNamespace = "");
const FileSaveOptions& options = FileSaveOptions());

/// Save a character model (skeleton and mesh) without animation.
/// @param filename Path to the output FBX file
/// @param character The character to save
/// @param coordSystemInfo Coordinate system configuration for the FBX file
/// @param permissive Permissive mode allows saving mesh-only characters (without skin weights)
/// @param fbxNamespace Optional namespace to prepend to all node names (e.g., "ns" will become
/// "ns:")
/// @param options Optional file save options for controlling output (default: FileSaveOptions{})
void saveFbxModel(
const filesystem::path& filename,
const Character& character,
const FbxCoordSystemInfo& coordSystemInfo = FbxCoordSystemInfo(),
bool permissive = false,
std::string_view fbxNamespace = "");
const FileSaveOptions& options = FileSaveOptions());

/// Loads a MarkerSequence from an FBX file.
///
Expand Down
Loading
Loading