Files
test2/source/blender/io/usd/intern/usd_reader_utils.cc
2024-05-28 14:09:40 +10:00

291 lines
8.8 KiB
C++

/* SPDX-FileCopyrightText: 2024 NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "usd_reader_utils.hh"
#include <pxr/usd/usd/attribute.h>
#include "CLG_log.h"
static CLG_LogRef LOG = {"io.usd"};
namespace {
template<typename VECT>
void set_array_prop(IDProperty *idgroup,
const char *prop_name,
const pxr::UsdAttribute &attr,
const pxr::UsdTimeCode motionSampleTime)
{
if (!idgroup || !attr) {
return;
}
VECT vec;
if (!attr.Get<VECT>(&vec, motionSampleTime)) {
return;
}
IDPropertyTemplate val = {0};
val.array.len = int(vec.dimension);
if (val.array.len <= 0) {
CLOG_WARN(&LOG, "Invalid array length for prop %s", prop_name);
return;
}
if (std::is_same<float, typename VECT::ScalarType>()) {
val.array.type = IDP_FLOAT;
}
else if (std::is_same<pxr::GfHalf, typename VECT::ScalarType>()) {
val.array.type = IDP_FLOAT;
}
else if (std::is_same<double, typename VECT::ScalarType>()) {
val.array.type = IDP_DOUBLE;
}
else if (std::is_same<int, typename VECT::ScalarType>()) {
val.array.type = IDP_INT;
}
else {
CLOG_WARN(&LOG, "Couldn't determine array type for prop %s", prop_name);
return;
}
IDProperty *prop = IDP_New(IDP_ARRAY, &val, prop_name);
if (!prop) {
CLOG_WARN(&LOG, "Couldn't create array prop %s", prop_name);
return;
}
if (std::is_same<pxr::GfHalf, typename VECT::ScalarType>()) {
float *prop_data = static_cast<float *>(prop->data.pointer);
for (int i = 0; i < val.array.len; ++i) {
prop_data[i] = vec[i];
}
}
else {
std::memcpy(prop->data.pointer, vec.data(), prop->len * sizeof(typename VECT::ScalarType));
}
IDP_AddToGroup(idgroup, prop);
}
bool equivalent(const pxr::SdfValueTypeName &type_name1, const pxr::SdfValueTypeName &type_name2)
{
return type_name1.GetType().IsA(type_name2.GetType());
}
} // anonymous namespace
namespace blender::io::usd {
/* TfToken objects are not cheap to construct, so we do it once. */
namespace usdtokens {
static const pxr::TfToken userProperties("userProperties", pxr::TfToken::Immortal);
} // namespace usdtokens
static void set_string_prop(IDProperty *idgroup, const char *prop_name, const char *str_val)
{
if (!idgroup) {
return;
}
IDPropertyTemplate val = {0};
val.string.str = str_val;
/* Note length includes null terminator. */
val.string.len = strlen(str_val) + 1;
val.string.subtype = IDP_STRING_SUB_UTF8;
IDProperty *prop = IDP_New(IDP_STRING, &val, prop_name);
IDP_AddToGroup(idgroup, prop);
}
static void set_int_prop(IDProperty *idgroup, const char *prop_name, const int ival)
{
if (!idgroup) {
return;
}
IDPropertyTemplate val = {0};
val.i = ival;
IDProperty *prop = IDP_New(IDP_INT, &val, prop_name);
IDP_AddToGroup(idgroup, prop);
}
static void set_bool_prop(IDProperty *idgroup, const char *prop_name, const bool bval)
{
if (!idgroup) {
return;
}
IDPropertyTemplate val = {0};
val.i = bval;
IDProperty *prop = IDP_New(IDP_BOOLEAN, &val, prop_name);
IDP_AddToGroup(idgroup, prop);
}
static void set_float_prop(IDProperty *idgroup, const char *prop_name, const float fval)
{
if (!idgroup) {
return;
}
IDPropertyTemplate val = {0};
val.f = fval;
IDProperty *prop = IDP_New(IDP_FLOAT, &val, prop_name);
IDP_AddToGroup(idgroup, prop);
}
static void set_double_prop(IDProperty *idgroup, const char *prop_name, const double dval)
{
if (!idgroup) {
return;
}
IDPropertyTemplate val = {0};
val.d = dval;
IDProperty *prop = IDP_New(IDP_DOUBLE, &val, prop_name);
IDP_AddToGroup(idgroup, prop);
}
void set_id_props_from_prim(ID *id,
const pxr::UsdPrim &prim,
const eUSDAttrImportMode attr_import_mode,
const pxr::UsdTimeCode time_code)
{
pxr::UsdAttributeVector attribs = prim.GetAuthoredAttributes();
if (attribs.empty()) {
return;
}
bool all_custom_attrs = (attr_import_mode == USD_ATTR_IMPORT_ALL);
for (const pxr::UsdAttribute &attr : attribs) {
if (!attr.IsCustom()) {
continue;
}
std::vector<std::string> attr_names = attr.SplitName();
bool is_user_prop = attr_names[0] == "userProperties";
if (attr_names.size() > 2 && is_user_prop && attr_names[1] == "blender") {
continue;
}
if (!all_custom_attrs && !is_user_prop) {
continue;
}
IDProperty *idgroup = IDP_EnsureProperties(id);
/* When importing user properties, strip the namespace. */
pxr::TfToken attr_name;
if (is_user_prop) {
/* We strip the userProperties namespace, but leave others in case
* someone's custom attribute namespace is important in their pipeline. */
const std::string token = "userProperties:";
const std::string name = attr.GetName().GetString();
attr_name = pxr::TfToken(name.substr(token.size(), name.size() - token.size()));
}
else {
attr_name = attr.GetName();
}
pxr::SdfValueTypeName type_name = attr.GetTypeName();
if (type_name == pxr::SdfValueTypeNames->Int) {
int ival = 0;
if (attr.Get<int>(&ival, time_code)) {
set_int_prop(idgroup, attr_name.GetString().c_str(), ival);
}
}
else if (type_name == pxr::SdfValueTypeNames->Float) {
float fval = 0.0f;
if (attr.Get<float>(&fval, time_code)) {
set_float_prop(idgroup, attr_name.GetString().c_str(), fval);
}
}
else if (type_name == pxr::SdfValueTypeNames->Double) {
double dval = 0.0;
if (attr.Get<double>(&dval, time_code)) {
set_double_prop(idgroup, attr_name.GetString().c_str(), dval);
}
}
else if (type_name == pxr::SdfValueTypeNames->Half) {
pxr::GfHalf hval = 0.0f;
if (attr.Get<pxr::GfHalf>(&hval, time_code)) {
set_float_prop(idgroup, attr_name.GetString().c_str(), hval);
}
}
else if (type_name == pxr::SdfValueTypeNames->String) {
std::string sval;
if (attr.Get<std::string>(&sval, time_code)) {
set_string_prop(idgroup, attr_name.GetString().c_str(), sval.c_str());
}
}
else if (type_name == pxr::SdfValueTypeNames->Token) {
pxr::TfToken tval;
if (attr.Get<pxr::TfToken>(&tval, time_code)) {
set_string_prop(idgroup, attr_name.GetString().c_str(), tval.GetString().c_str());
}
}
else if (type_name == pxr::SdfValueTypeNames->Asset) {
pxr::SdfAssetPath aval;
if (attr.Get<pxr::SdfAssetPath>(&aval, time_code)) {
set_string_prop(idgroup, attr_name.GetString().c_str(), aval.GetAssetPath().c_str());
}
}
else if (type_name == pxr::SdfValueTypeNames->Bool) {
bool bval = false;
if (attr.Get<bool>(&bval, time_code)) {
set_bool_prop(idgroup, attr_name.GetString().c_str(), bval);
}
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Float2)) {
set_array_prop<pxr::GfVec2f>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Float3)) {
set_array_prop<pxr::GfVec3f>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Float4)) {
set_array_prop<pxr::GfVec4f>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Double2)) {
set_array_prop<pxr::GfVec2d>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Double3)) {
set_array_prop<pxr::GfVec3d>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Double4)) {
set_array_prop<pxr::GfVec4d>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Int2)) {
set_array_prop<pxr::GfVec2i>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Int3)) {
set_array_prop<pxr::GfVec3i>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Int4)) {
set_array_prop<pxr::GfVec4i>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Half2)) {
set_array_prop<pxr::GfVec2h>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Half3)) {
set_array_prop<pxr::GfVec3h>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
else if (equivalent(type_name, pxr::SdfValueTypeNames->Half4)) {
set_array_prop<pxr::GfVec4h>(idgroup, attr_name.GetString().c_str(), attr, time_code);
}
}
}
} // namespace blender::io::usd