New functionality to export armatures and shape keys as USD skeletons and blend shapes. Added "Armature", "Only Deform Bones" and "Shape Key" USD export options. Added USDArmatureWriter class. Extended USDMeshWriter to write skinned meshes for binding with skeletons and 'neutral' meshes with blend shape targets. Specifically, when exporting an armature, a skinned mesh is written in its pre-modified rest position. When exporting to blend shapes, a mesh with shape keys is saved with its vertices in the shape key basis shape position. Added USDHierarchyIterator::process_usd_skel() function to finish processing skeleton and blend shape export after the writer instances completed writing. This is necessary because some of the export operations require processing multiple prims at once. Extended USDTransformWriter::do_write() to write transforms sparsely, to avoid saving redundant transform values when exporting armatures. Added a create_skel_roots() function, called on the stage at the end of the export. This function attempts to ensure that skinned prims and skeletons are encapsulated under SkelRoot primitives, which is required in USD for correct skinning behavior. When exporting blend shape animations for multiple meshes bound to a single skeleton, we need to merge the blend shape time samples of the different meshes into a single animation primitive at the end of the export. This requires some tricky book keeping, where the weight time samples for a given mesh are initially saved by the mesh writer to a temporary attribute on the mesh and are later copied to the animation primitive as one of the final steps. When writing blend shapes and skinned meshes, the pre-modified mesh is exported. This is to ensure that the number of blend shape offsets matches the number of points, and so that the skinned mesh is saved in its rest position. Because the pre-modified mesh must be exported, modifiers in addition to Armature modifiers will not be applied. This still allows the round trip UsdSkel -> Blender -> UsdSkel, but some additional setup might be required to export to UsdSkel when there are multiple modifiers (for example, applying mirroring modifiers that precede the armature modifier). Exporting bendy bones or absolute shape keys isn't currently supported. Co-authored-by: Charles Wardlaw <charleswardlaw@noreply.localhost> Pull Request: https://projects.blender.org/blender/blender/pulls/111931
51 lines
1.7 KiB
C++
51 lines
1.7 KiB
C++
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
#include "usd_writer_transform.h"
|
|
#include "usd_hierarchy_iterator.h"
|
|
|
|
#include <pxr/base/gf/matrix4f.h>
|
|
#include <pxr/usd/usdGeom/xform.h>
|
|
|
|
#include "BKE_object.hh"
|
|
|
|
#include "BLI_math_matrix.h"
|
|
|
|
#include "DNA_layer_types.h"
|
|
|
|
namespace blender::io::usd {
|
|
|
|
USDTransformWriter::USDTransformWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) {}
|
|
|
|
void USDTransformWriter::do_write(HierarchyContext &context)
|
|
{
|
|
float parent_relative_matrix[4][4]; /* The object matrix relative to the parent. */
|
|
mul_m4_m4m4(parent_relative_matrix, context.parent_matrix_inv_world, context.matrix_world);
|
|
|
|
/* Write the transform relative to the parent. */
|
|
pxr::UsdGeomXform xform = pxr::UsdGeomXform::Define(usd_export_context_.stage,
|
|
usd_export_context_.usd_path);
|
|
if (!xformOp_) {
|
|
xformOp_ = xform.AddTransformOp();
|
|
}
|
|
|
|
pxr::GfMatrix4d mat_val(parent_relative_matrix);
|
|
usd_value_writer_.SetAttribute(xformOp_.GetAttr(), mat_val, get_export_time_code());
|
|
}
|
|
|
|
bool USDTransformWriter::check_is_animated(const HierarchyContext &context) const
|
|
{
|
|
if (context.duplicator != nullptr) {
|
|
/* This object is being duplicated, so could be emitted by a particle system and thus
|
|
* influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the
|
|
* depsgraph whether this object instance has a time source. */
|
|
return true;
|
|
}
|
|
if (check_has_physics(context)) {
|
|
return true;
|
|
}
|
|
return BKE_object_moves_in_time(context.object, context.animation_check_include_parent);
|
|
}
|
|
|
|
} // namespace blender::io::usd
|