24#include <pxr/base/vt/types.h>
25#include <pxr/usd/usdGeom/basisCurves.h>
26#include <pxr/usd/usdGeom/primvarsAPI.h>
37 return is_cyclic ? (usd_count / 3) : ((usd_count / 3) + 1);
54 for (const int i : range) {
55 offsets[i] = point_count(usdCounts[i], curve_type, is_cyclic);
70 positions[cp] =
to_float3(usdPoints[offset]);
71 handles_right[cp] =
to_float3(usdPoints[offset + 1]);
72 handles_left[cp] = 2.0f * positions[cp] - handles_right[cp];
74 else if (offset == usdPoints.
size() - 1) {
75 positions[cp] =
to_float3(usdPoints[offset]);
76 handles_left[cp] =
to_float3(usdPoints[offset - 1]);
77 handles_right[cp] = 2.0f * positions[cp] - handles_left[cp];
80 positions[cp] =
to_float3(usdPoints[offset]);
81 handles_left[cp] =
to_float3(usdPoints[offset - 1]);
82 handles_right[cp] =
to_float3(usdPoints[offset + 1]);
89 if (curves.
offsets() != usd_offsets) {
98 if (type == pxr::UsdGeomTokens->cubic) {
99 if (basis == pxr::UsdGeomTokens->bezier) {
102 if (basis == pxr::UsdGeomTokens->bspline) {
105 if (basis == pxr::UsdGeomTokens->catmullRom) {
126 if (value ==
nullptr) {
154 const pxr::UsdGeomCurves &usd_curves,
155 const pxr::UsdTimeCode time)
const
157 pxr::VtVec3fArray velocities;
158 usd_curves.GetVelocitiesAttr().Get(&velocities, time);
160 if (!velocities.empty()) {
166 velocity.
span.copy_from(usd_data.cast<
float3>());
172 const pxr::UsdTimeCode time)
const
174 pxr::UsdGeomPrimvarsAPI pv_api(
prim_);
176 std::vector<pxr::UsdGeomPrimvar> primvars = pv_api.GetPrimvarsWithValues();
177 for (
const pxr::UsdGeomPrimvar &pv : primvars) {
178 const pxr::SdfValueTypeName pv_type = pv.GetTypeName();
179 if (!pv_type.IsArray()) {
183 const pxr::TfToken pv_interp = pv.GetInterpolation();
187 if (!domain.has_value() || !type.has_value()) {
188 const pxr::TfToken pv_name = pxr::UsdGeomPrimvar::StripPrimvarsName(pv.GetPrimvarName());
191 "Primvar '%s' (interpolation %s, type %s) cannot be converted to Blender",
194 pv_type.GetAsToken().GetText());
217 if (curve_prim_.GetPointsAttr().ValueMightBeTimeVarying() ||
218 curve_prim_.GetWidthsAttr().ValueMightBeTimeVarying() ||
219 curve_prim_.GetVelocitiesAttr().ValueMightBeTimeVarying())
224 pxr::UsdGeomPrimvarsAPI pv_api(curve_prim_);
225 for (
const pxr::UsdGeomPrimvar &pv : pv_api.GetPrimvarsWithValues()) {
226 if (pv.ValueMightBeTimeVarying()) {
236 pxr::VtIntArray usd_counts;
237 pxr::VtVec3fArray usd_points;
238 pxr::VtFloatArray usd_widths;
243 curve_prim_.GetCurveVertexCountsAttr().Get(&usd_counts, time);
244 curve_prim_.GetPointsAttr().Get(&usd_points, time);
245 curve_prim_.GetWidthsAttr().Get(&usd_widths, time);
246 curve_prim_.GetBasisAttr().Get(&basis, time);
247 curve_prim_.GetTypeAttr().Get(&type, time);
248 curve_prim_.GetWrapAttr().Get(&
wrap, time);
252 const int curves_num = usd_counts.size();
257 curves.
resize(new_offsets.
last(), curves_num);
269 const int8_t curve_order = type == pxr::UsdGeomTokens->cubic ? 4 : 2;
275 Span<int> counts =
Span(usd_counts.cdata(), usd_counts.size());
278 if (type == pxr::UsdGeomTokens->cubic && basis == pxr::UsdGeomTokens->bezier) {
285 int usd_point_offset = 0;
286 int point_offset = 0;
288 const int usd_point_count = counts[
i];
298 points.
slice(usd_point_offset, usd_point_count));
303 usd_point_offset += usd_point_count;
307 static_assert(
sizeof(pxr::GfVec3f) ==
sizeof(
float3));
311 if (!usd_widths.empty()) {
315 pxr::TfToken widths_interp = curve_prim_.GetWidthsInterpolation();
316 if (widths_interp == pxr::UsdGeomTokens->constant) {
317 radii.
fill(widths[0] / 2.0f);
320 const bool is_bezier_vertex_interp = (type == pxr::UsdGeomTokens->cubic &&
321 basis == pxr::UsdGeomTokens->bezier &&
322 widths_interp == pxr::UsdGeomTokens->vertex);
323 if (is_bezier_vertex_interp) {
326 int usd_point_offset = 0;
327 int point_offset = 0;
329 const int usd_point_count = counts[
i];
334 radii[point_offset + cp] = widths[usd_point_offset + cp_offset] / 2.0f;
339 usd_point_offset += usd_point_count;
344 radii[i_point] = widths[i_point] / 2.0f;
struct Curves * BKE_curves_add(struct Main *bmain, const char *name)
Low-level operations for curves.
General operations, lookup, etc. for blender objects.
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
Object is a sort of wrapper for general info.
constexpr void fill(const T &value) const
constexpr void copy_from(Span< T > values) const
const T & last(const int64_t n=0) const
const Value * lookup_ptr(const Key &key) const
void add_new(const Key &key, const Value &value)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void fill(const T &value) const
constexpr void copy_from(Span< T > values) const
Span< NewT > constexpr cast() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
MutableSpan< float3 > positions_for_write()
MutableSpan< int8_t > handle_types_right_for_write()
IndexRange curves_range() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
MutableSpan< int8_t > nurbs_orders_for_write()
IndexRange points_range() const
Span< int > offsets() const
MutableSpan< float > radius_for_write()
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
MutableSpan< bool > cyclic_for_write()
MutableSpan< int8_t > handle_types_left_for_write()
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
void read_curve_sample(Curves *curves_id, pxr::UsdTimeCode time) override
bool is_animated() const override
void read_object_data(Main *bmain, pxr::UsdTimeCode time) override
void read_geometry(bke::GeometrySet &geometry_set, USDMeshReadParams params, const char **r_err_str) override
void read_custom_data(bke::CurvesGeometry &curves, const pxr::UsdTimeCode time) const
void create_object(Main *bmain) override
virtual bool is_animated() const =0
virtual void read_curve_sample(Curves *curves_id, pxr::UsdTimeCode time)=0
void read_velocities(bke::CurvesGeometry &curves, const pxr::UsdGeomCurves &usd_curves, const pxr::UsdTimeCode time) const
void add_cache_modifier()
ReportList * reports() const
static bool is_cyclic(const Nurb *nu)
static int bezier_point_count(int usd_count, bool is_cyclic)
static Array< int > calc_curve_offsets(const pxr::VtIntArray &usdCounts, const CurveType curve_type, bool is_cyclic)
static void add_bezier_control_point(int cp, int offset, MutableSpan< float3 > positions, MutableSpan< float3 > handles_left, MutableSpan< float3 > handles_right, const Span< pxr::GfVec3f > usdPoints)
static int point_count(int usdCount, CurveType curve_type, bool is_cyclic)
static CurveType get_curve_type(pxr::TfToken type, pxr::TfToken basis)
void copy_primvar_to_blender_attribute(const pxr::UsdGeomPrimvar &primvar, const pxr::UsdTimeCode time, const bke::AttrType data_type, const bke::AttrDomain domain, const OffsetIndices< int > face_indices, bke::MutableAttributeAccessor attributes)
std::optional< bke::AttrType > convert_usd_type_to_blender(const pxr::SdfValueTypeName usd_type)
static bool curves_topology_changed(const bke::CurvesGeometry &curves, const Span< int > usd_offsets)
static std::optional< bke::AttrDomain > convert_usd_interp_to_blender(const pxr::TfToken usd_domain)
static float3 to_float3(pxr::GfVec3f vec3f)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 3 > float3
float wrap(float value, float max, float min)
Curves * get_curves_for_write()
MutableVArraySpan< T > span