USD export: support authoring Kind

Added a switch to the exporter to write USD Kind.
Added options to add USD Kind to the Default Prim.
Added a special case for the IDProperty "usdkind",
which is now written as the Kind through the UsdModelAPI.
This commit is contained in:
Michael Kowalski 2022-12-09 18:37:54 -05:00
parent 98670cfe82
commit 6ce3e0495a
5 changed files with 110 additions and 1 deletions

View File

@ -164,6 +164,16 @@ const EnumPropertyItem prop_usdz_downscale_size[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem prop_default_prim_kind_items[] = {
{ USD_KIND_NONE, "NONE", 0, "None", "No kind is exported for default prim" },
{ USD_KIND_COMPONENT, "COMPONENT", 0, "Component", "Set Default Prim Kind to Component" },
{ USD_KIND_GROUP, "GROUP", 0, "Group", "Set Default Prim Kind to Group" },
{ USD_KIND_ASSEMBLY, "ASSEMBLY", 0, "Assembly", "Set Default Prim Kind to Assembly" },
{ USD_KIND_CUSTOM, "CUSTOM", 0, "Custom", "Specify a custom Kind for the Default Prim" },
{0, NULL, 0, NULL, NULL},
};
/* Stored in the wmOperator's customdata field to indicate it should run as a background job.
* This is set when the operator is invoked, and not set when it is only executed. */
enum { AS_BACKGROUND_JOB = 1 };
@ -314,6 +324,11 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
const bool export_blender_metadata = RNA_boolean_get(op->ptr, "export_blender_metadata");
/* USDKind support. */
const bool export_usd_kind = RNA_boolean_get(op->ptr, "export_usd_kind");
const int default_prim_kind = RNA_enum_get(op->ptr, "default_prim_kind");
char *default_prim_custom_kind = RNA_string_get_alloc(op->ptr, "default_prim_custom_kind", NULL, 0, NULL);
struct USDExportParams params = {RNA_int_get(op->ptr, "start"),
RNA_int_get(op->ptr, "end"),
export_animation,
@ -377,7 +392,11 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
export_blender_metadata,
triangulate_meshes,
quad_method,
ngon_method};
ngon_method,
.export_usd_kind = export_usd_kind,
.default_prim_kind = default_prim_kind,
.default_prim_custom_kind = default_prim_custom_kind
};
/* Take some defaults from the scene, if not specified explicitly. */
Scene *scene = CTX_data_scene(C);
@ -427,6 +446,7 @@ static void wm_usd_export_draw(bContext *C, wmOperator *op)
uiItemR(box, ptr, "end", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "frame_step", 0, NULL, ICON_NONE);
}
uiItemR(box, ptr, "export_usd_kind", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "export_as_overs", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "merge_transform_and_shape", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "export_identity_transforms", 0, NULL, ICON_NONE);
@ -493,6 +513,12 @@ static void wm_usd_export_draw(bContext *C, wmOperator *op)
uiItemR(box, ptr, "default_prim_path", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "root_prim_path", 0, NULL, ICON_NONE);
uiItemR(box, ptr, "material_prim_path", 0, NULL, ICON_NONE);
if (RNA_boolean_get(ptr, "export_usd_kind")) {
uiItemR(box, ptr, "default_prim_kind", 0, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "default_prim_kind") == USD_KIND_CUSTOM) {
uiItemR(box, ptr, "default_prim_custom_kind", 0, NULL, ICON_NONE);
}
}
box = uiLayoutBox(layout);
uiItemL(box, IFACE_("Conversion:"), ICON_ORIENTATION_GLOBAL);
@ -1010,6 +1036,26 @@ void WM_OT_usd_export(struct wmOperatorType *ot)
MOD_TRIANGULATE_NGON_BEAUTY,
"N-gon Method",
"Method for splitting the n-gons into triangles");
RNA_def_boolean(ot->srna,
"export_usd_kind",
true,
"Export USD Kind",
"Export Kind per-prim when specified through 'usdkind' custom property.");
RNA_def_enum(ot->srna,
"default_prim_kind",
prop_default_prim_kind_items,
USD_KIND_NONE,
"Default Prim Kind",
"Kind to author on the Default Prim");
RNA_def_string(ot->srna,
"default_prim_custom_kind",
NULL,
128,
"Default Prim Custom Kind",
"If default_prim_kind is True, author this value as the Default Prim's Kind");
}
/* ====== USD Import ====== */

View File

@ -11,6 +11,8 @@
#include <pxr/base/plug/registry.h>
#include <pxr/pxr.h>
#include <pxr/usd/kind/registry.h>
#include <pxr/usd/usd/modelAPI.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdGeom/metrics.h>
#include <pxr/usd/usdGeom/scope.h>
@ -99,6 +101,12 @@ static bool validate_params(const USDExportParams &params)
valid = false;
}
if (params.export_usd_kind && params.default_prim_kind == USD_KIND_CUSTOM && strlen(params.default_prim_custom_kind) == 0) {
WM_reportf(RPT_ERROR,
"USD Export: Default Prim Kind is set to Custom, but the value is empty.");
valid = false;
}
return valid;
}
@ -197,6 +205,31 @@ static void ensure_root_prim(pxr::UsdStageRefPtr stage, const USDExportParams &p
xf_api.SetRotate(pxr::GfVec3f(eul[0], eul[1], eul[2]));
}
/* Handle root prim USD Kind. */
if (params.export_usd_kind && params.default_prim_kind) {
pxr::UsdModelAPI api(root_prim);
switch (params.default_prim_kind) {
case USD_KIND_COMPONENT:
api.SetKind(pxr::KindTokens->component);
break;
case USD_KIND_GROUP:
api.SetKind(pxr::KindTokens->group);
break;
case USD_KIND_ASSEMBLY:
api.SetKind(pxr::KindTokens->assembly);
break;
case USD_KIND_CUSTOM:
api.SetKind(pxr::TfToken(params.default_prim_custom_kind));
break;
default:
break;
}
}
}
static void report_job_duration(const ExportJobData *data)

View File

@ -5,6 +5,8 @@
#include "usd_writer_material.h"
#include <pxr/base/tf/stringUtils.h>
#include <pxr/usd/kind/registry.h>
#include <pxr/usd/usd/modelAPI.h>
#include "BKE_customdata.h"
#include "BLI_assert.h"
@ -275,6 +277,12 @@ void USDAbstractWriter::write_visibility(const HierarchyContext &context,
usd_value_writer_.SetAttribute(attr_visibility, pxr::VtValue(visibility), timecode);
}
void USDAbstractWriter::write_kind(pxr::UsdPrim& prim, pxr::TfToken kind)
{
pxr::UsdModelAPI api(prim);
api.SetKind(kind);
}
bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const pxr::UsdPrim &prim)
{
BLI_assert(context.is_instance());
@ -344,8 +352,17 @@ void USDAbstractWriter::write_user_properties(pxr::UsdPrim &prim,
return;
}
const StringRef kind_identifier = "usdkind";
IDProperty *prop;
for (prop = (IDProperty *)properties->data.group.first; prop; prop = prop->next) {
if (kind_identifier == prop->name) {
if (prop->type == IDP_STRING && usd_export_context_.export_params.export_usd_kind && prop->data.pointer) {
write_kind(prim, pxr::TfToken(static_cast<char*>(prop->data.pointer)));
}
continue;
}
std::string prop_name = pxr::TfMakeValidIdentifier(prop->name);
std::string full_prop_name;

View File

@ -68,6 +68,8 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
const pxr::UsdTimeCode timecode,
pxr::UsdGeomImageable &usd_geometry);
void write_kind(pxr::UsdPrim& prim, pxr::TfToken kind);
/**
* Turn `prim` into an instance referencing `context.original_export_path`.
* Return true when the instancing was successful, false otherwise.

View File

@ -71,6 +71,14 @@ typedef enum eUSDAttrImportMode {
USD_ATTR_IMPORT_ALL = 2,
} eUSDAttrImportMode;
typedef enum eUSDDefaultPrimKind {
USD_KIND_NONE = 0,
USD_KIND_COMPONENT,
USD_KIND_GROUP,
USD_KIND_ASSEMBLY,
USD_KIND_CUSTOM
} eUSDDefaultPrimKind;
struct USDExportParams {
double frame_start;
double frame_end;
@ -138,6 +146,9 @@ struct USDExportParams {
bool triangulate_meshes;
int quad_method;
int ngon_method;
bool export_usd_kind;
eUSDDefaultPrimKind default_prim_kind;
char *default_prim_custom_kind;
};
struct USDImportParams {