USD Export: New Curves/Hair Support #105375

Merged
Michael Kowalski merged 19 commits from SonnyCampbell_Unity/blender:unity/T102376-USD-Curves-Export into main 2023-05-16 20:04:26 +02:00
3 changed files with 68 additions and 57 deletions
Showing only changes of commit 1e4bda4473 - Show all commits

View File

@ -13,6 +13,7 @@
#include "usd_writer_transform.h"
#include "usd_writer_volume.h"
#include <memory>
#include <string>
#include <pxr/base/tf/stringUtils.h>
@ -109,8 +110,9 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
break;
case OB_CURVES_LEGACY: {
const Curve *legacy_curve = static_cast<Curve *>(context->object->data);
Curves *curves = bke::curve_legacy_to_curves(*legacy_curve);
data_writer = new USDCurvesWriter(usd_export_context, curves);
std::unique_ptr<Curves> curves = std::unique_ptr<Curves>(
bke::curve_legacy_to_curves(*legacy_curve));
data_writer = new USDCurvesWriter(usd_export_context, std::move(curves));
break;
}
case OB_CURVES:

View File

@ -14,6 +14,7 @@
#include "usd_writer_curves.h"
#include "BKE_curves.hh"
#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BLI_math_geom.h"
@ -24,15 +25,23 @@
namespace blender::io::usd {
USDCurvesWriter::USDCurvesWriter(const USDExporterContext &ctx)
: USDAbstractWriter(ctx), converted_curves(nullptr)
: USDAbstractWriter(ctx), converted_curves_(nullptr)
{
}
USDCurvesWriter::USDCurvesWriter(const USDExporterContext &ctx, Curves *converted_legacy_curves)
: USDAbstractWriter(ctx), converted_curves(converted_legacy_curves)
USDCurvesWriter::USDCurvesWriter(const USDExporterContext &ctx,
std::unique_ptr<Curves> converted_legacy_curves)
: USDAbstractWriter(ctx), converted_curves_(std::move(converted_legacy_curves))
{
}
USDCurvesWriter::~USDCurvesWriter()
{
if (converted_curves_) {
BKE_id_free(nullptr, converted_curves_.release());
}
}
pxr::UsdGeomCurves USDCurvesWriter::DefineUsdGeomBasisCurves(pxr::VtValue curve_basis,
bool cyclic,
bool cubic)
@ -61,7 +70,7 @@ pxr::UsdGeomCurves USDCurvesWriter::DefineUsdGeomBasisCurves(pxr::VtValue curve_
return curves;
}
void populate_curve_widths(const bke::CurvesGeometry &geometry, pxr::VtArray<float> &widths)
static void populate_curve_widths(const bke::CurvesGeometry &geometry, pxr::VtArray<float> &widths)
{
const bke::AttributeAccessor curve_attributes = geometry.attributes();
const VArray<float> radii = curve_attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
@ -73,47 +82,45 @@ void populate_curve_widths(const bke::CurvesGeometry &geometry, pxr::VtArray<flo
}
}
void set_curve_width_interpolation(const pxr::VtArray<float> &widths,
const pxr::VtArray<int> &segments,
const pxr::VtIntArray &control_point_counts,
const bool cyclic,
pxr::TfToken &interpolation)
static pxr::TfToken set_curve_width_interpolation(const pxr::VtArray<float> &widths,
const pxr::VtArray<int> &segments,
const pxr::VtIntArray &control_point_counts,
const bool cyclic)
{
SonnyCampbell_Unity marked this conversation as resolved Outdated

Use snake_case for variable names (https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Naming)

Use `snake_case` for variable names (https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Naming)
if (widths.size() == 0) {
return;
if (widths.empty()) {
return pxr::TfToken();
}
size_t expectedVaryingSize;
if (cyclic) {
expectedVaryingSize = std::accumulate(segments.begin(), segments.end(), 0);
}
else {
expectedVaryingSize = std::accumulate(segments.begin(), segments.end(), 0) +
control_point_counts.size();
}
size_t accumulatedControlPointCount = std::accumulate(
const size_t accumulatedControlPointCount = std::accumulate(
control_point_counts.begin(), control_point_counts.end(), 0);
/* For Blender curves, radii are always stored per point. For linear curves, this should match
* with USD's vertex interpolation. For cubic curves, this should match with USD's varying
* interpolation. */
if (widths.size() == accumulatedControlPointCount)
interpolation = pxr::UsdGeomTokens->vertex;
if (widths.size() == expectedVaryingSize)
interpolation = pxr::UsdGeomTokens->varying;
else {
WM_reportf(RPT_WARNING, "Curve width size not supported for USD interpolation.");
if (widths.size() == accumulatedControlPointCount) {
return pxr::UsdGeomTokens->vertex;
}
size_t expectedVaryingSize = std::accumulate(segments.begin(), segments.end(), 0);
if (!cyclic) {
expectedVaryingSize += control_point_counts.size();
}
if (widths.size() == expectedVaryingSize) {
return pxr::UsdGeomTokens->varying;
}
WM_reportf(RPT_WARNING, "Curve width size not supported for USD interpolation.");
return pxr::TfToken();
}
void populate_curve_props(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::TfToken &interpolation,
const bool cyclic,
const bool cubic)
static void populate_curve_props(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::TfToken &interpolation,
const bool cyclic,
const bool cubic)
{
const int num_curves = geometry.curve_num;
const Span<float3> positions = geometry.positions();
@ -146,15 +153,15 @@ void populate_curve_props(const bke::CurvesGeometry &geometry,
}
populate_curve_widths(geometry, widths);
set_curve_width_interpolation(widths, segments, control_point_counts, cyclic, interpolation);
interpolation = set_curve_width_interpolation(widths, segments, control_point_counts, cyclic);
}
void populate_curve_props_for_bezier(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::TfToken &interpolation,
const bool cyclic)
static void populate_curve_props_for_bezier(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::TfToken &interpolation,
const bool cyclic)
{
const int bezier_vstep = 3;
const int num_curves = geometry.curve_num;
@ -208,17 +215,17 @@ void populate_curve_props_for_bezier(const bke::CurvesGeometry &geometry,
}
populate_curve_widths(geometry, widths);
set_curve_width_interpolation(widths, segments, control_point_counts, cyclic, interpolation);
interpolation = set_curve_width_interpolation(widths, segments, control_point_counts, cyclic);
}
void populate_curve_props_for_nurbs(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::VtArray<double> &knots,
pxr::VtArray<int> &orders,
pxr::TfToken &interpolation,
const bool cyclic)
static void populate_curve_props_for_nurbs(const bke::CurvesGeometry &geometry,
pxr::VtArray<pxr::GfVec3f> &verts,
pxr::VtIntArray &control_point_counts,
pxr::VtArray<float> &widths,
pxr::VtArray<double> &knots,
pxr::VtArray<int> &orders,
pxr::TfToken &interpolation,
const bool cyclic)
{
const int num_curves = geometry.curve_num;
orders.resize(num_curves);
@ -273,8 +280,8 @@ void populate_curve_props_for_nurbs(const bke::CurvesGeometry &geometry,
void USDCurvesWriter::do_write(HierarchyContext &context)
{
Curves *curve = converted_curves ? converted_curves :
static_cast<Curves *>(context.object->data);
const Curves *curve = converted_curves_ ? converted_curves_.get() :
static_cast<Curves *>(context.object->data);
const bke::CurvesGeometry &geometry = bke::CurvesGeometry::wrap(curve->geometry);
if (geometry.points_num() == 0) {

View File

@ -2,6 +2,8 @@
* Copyright 2022 Blender Foundation. All rights reserved. */
#pragma once
#include <memory>
#include "DNA_curves_types.h"
#include "usd_writer_abstract.h"
@ -13,7 +15,8 @@ namespace blender::io::usd {
class USDCurvesWriter : public USDAbstractWriter {
public:
USDCurvesWriter(const USDExporterContext &ctx);
USDCurvesWriter(const USDExporterContext &ctx, Curves *converted_legacy_curves);
USDCurvesWriter(const USDExporterContext &ctx, std::unique_ptr<Curves> converted_legacy_curves);
~USDCurvesWriter();
protected:
virtual void do_write(HierarchyContext &context) override;
@ -21,9 +24,8 @@ class USDCurvesWriter : public USDAbstractWriter {
void assign_materials(const HierarchyContext &context, pxr::UsdGeomCurves usd_curve);
private:
Curves *converted_curves;
std::unique_ptr<Curves> converted_curves_;
pxr::UsdGeomCurves DefineUsdGeomBasisCurves(pxr::VtValue curve_basis, bool cyclic, bool cubic);
};
} // namespace blender::io::usd