Blender  V3.3
usd_reader_curve.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Adapted from the Blender Alembic importer implementation. Copyright 2016 Kévin Dietrich.
3  * Modifications Copyright 2021 Tangent Animation. All rights reserved. */
4 
5 #include "usd_reader_curve.h"
6 
7 #include "BKE_curve.h"
8 #include "BKE_mesh.h"
9 #include "BKE_object.h"
10 
11 #include "BLI_listbase.h"
12 
13 #include "DNA_curve_types.h"
14 #include "DNA_object_types.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include <pxr/base/vt/array.h>
19 #include <pxr/base/vt/types.h>
20 #include <pxr/base/vt/value.h>
21 
22 #include <pxr/usd/usdGeom/basisCurves.h>
23 #include <pxr/usd/usdGeom/curves.h>
24 
25 namespace blender::io::usd {
26 
27 void USDCurvesReader::create_object(Main *bmain, const double /* motionSampleTime */)
28 {
29  curve_ = BKE_curve_add(bmain, name_.c_str(), OB_CURVES_LEGACY);
30 
31  curve_->flag |= CU_3D;
33  curve_->resolu = 2;
34 
36  object_->data = curve_;
37 }
38 
39 void USDCurvesReader::read_object_data(Main *bmain, double motionSampleTime)
40 {
41  Curve *cu = (Curve *)object_->data;
42  read_curve_sample(cu, motionSampleTime);
43 
44  if (curve_prim_.GetPointsAttr().ValueMightBeTimeVarying()) {
46  }
47 
48  USDXformReader::read_object_data(bmain, motionSampleTime);
49 }
50 
51 void USDCurvesReader::read_curve_sample(Curve *cu, const double motionSampleTime)
52 {
53  curve_prim_ = pxr::UsdGeomBasisCurves(prim_);
54 
55  if (!curve_prim_) {
56  return;
57  }
58 
59  pxr::UsdAttribute widthsAttr = curve_prim_.GetWidthsAttr();
60  pxr::UsdAttribute vertexAttr = curve_prim_.GetCurveVertexCountsAttr();
61  pxr::UsdAttribute pointsAttr = curve_prim_.GetPointsAttr();
62 
63  pxr::VtIntArray usdCounts;
64 
65  vertexAttr.Get(&usdCounts, motionSampleTime);
66  int num_subcurves = usdCounts.size();
67 
68  pxr::VtVec3fArray usdPoints;
69  pointsAttr.Get(&usdPoints, motionSampleTime);
70 
71  pxr::VtFloatArray usdWidths;
72  widthsAttr.Get(&usdWidths, motionSampleTime);
73 
74  pxr::UsdAttribute basisAttr = curve_prim_.GetBasisAttr();
75  pxr::TfToken basis;
76  basisAttr.Get(&basis, motionSampleTime);
77 
78  pxr::UsdAttribute typeAttr = curve_prim_.GetTypeAttr();
79  pxr::TfToken type;
80  typeAttr.Get(&type, motionSampleTime);
81 
82  pxr::UsdAttribute wrapAttr = curve_prim_.GetWrapAttr();
83  pxr::TfToken wrap;
84  wrapAttr.Get(&wrap, motionSampleTime);
85 
86  pxr::VtVec3fArray usdNormals;
87  curve_prim_.GetNormalsAttr().Get(&usdNormals, motionSampleTime);
88 
89  /* If normals, extrude, else bevel.
90  * Perhaps to be replaced by Blender/USD Schema. */
91  if (!usdNormals.empty()) {
92  /* Set extrusion to 1.0f. */
93  curve_->extrude = 1.0f;
94  }
95  else {
96  /* Set bevel depth to 1.0f. */
97  curve_->bevel_radius = 1.0f;
98  }
99 
100  size_t idx = 0;
101  for (size_t i = 0; i < num_subcurves; i++) {
102  const int num_verts = usdCounts[i];
103  Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), __func__));
104 
105  if (basis == pxr::UsdGeomTokens->bspline) {
106  nu->flag = CU_SMOOTH;
107  nu->type = CU_NURBS;
108  }
109  else if (basis == pxr::UsdGeomTokens->bezier) {
110  /* TODO(makowalski): Beziers are not properly imported as beziers. */
111  nu->type = CU_POLY;
112  }
113  else if (basis.IsEmpty()) {
114  nu->type = CU_POLY;
115  }
116  nu->resolu = cu->resolu;
117  nu->resolv = cu->resolv;
118 
119  nu->pntsu = num_verts;
120  nu->pntsv = 1;
121 
122  if (type == pxr::UsdGeomTokens->cubic) {
123  nu->orderu = 4;
124  }
125  else if (type == pxr::UsdGeomTokens->linear) {
126  nu->orderu = 2;
127  }
128 
129  if (wrap == pxr::UsdGeomTokens->periodic) {
130  nu->flagu |= CU_NURB_CYCLIC;
131  }
132  else if (wrap == pxr::UsdGeomTokens->pinned) {
133  nu->flagu |= CU_NURB_ENDPOINT;
134  }
135 
136  float weight = 1.0f;
137 
138  nu->bp = static_cast<BPoint *>(MEM_callocN(sizeof(BPoint) * nu->pntsu, __func__));
139  BPoint *bp = nu->bp;
140 
141  for (int j = 0; j < nu->pntsu; j++, bp++, idx++) {
142  bp->vec[0] = (float)usdPoints[idx][0];
143  bp->vec[1] = (float)usdPoints[idx][1];
144  bp->vec[2] = (float)usdPoints[idx][2];
145  bp->vec[3] = weight;
146  bp->f1 = SELECT;
147  bp->weight = weight;
148 
149  float radius = curve_->offset;
150  if (idx < usdWidths.size()) {
151  radius = usdWidths[idx];
152  }
153 
154  bp->radius = radius;
155  }
156 
159 
161  }
162 }
163 
164 Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
165  const double motionSampleTime,
166  const int /* read_flag */,
167  const char ** /* err_str */)
168 {
169  if (!curve_prim_) {
170  return existing_mesh;
171  }
172 
173  pxr::UsdAttribute widthsAttr = curve_prim_.GetWidthsAttr();
174  pxr::UsdAttribute vertexAttr = curve_prim_.GetCurveVertexCountsAttr();
175  pxr::UsdAttribute pointsAttr = curve_prim_.GetPointsAttr();
176 
177  pxr::VtIntArray usdCounts;
178 
179  vertexAttr.Get(&usdCounts, motionSampleTime);
180  int num_subcurves = usdCounts.size();
181 
182  pxr::VtVec3fArray usdPoints;
183  pointsAttr.Get(&usdPoints, motionSampleTime);
184 
185  int vertex_idx = 0;
186  int curve_idx;
187  Curve *curve = static_cast<Curve *>(object_->data);
188 
189  const int curve_count = BLI_listbase_count(&curve->nurb);
190  bool same_topology = curve_count == num_subcurves;
191 
192  if (same_topology) {
193  Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
194  for (curve_idx = 0; nurbs; nurbs = nurbs->next, curve_idx++) {
195  const int num_in_usd = usdCounts[curve_idx];
196  const int num_in_blender = nurbs->pntsu;
197 
198  if (num_in_usd != num_in_blender) {
199  same_topology = false;
200  break;
201  }
202  }
203  }
204 
205  if (!same_topology) {
207  read_curve_sample(curve, motionSampleTime);
208  }
209  else {
210  Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
211  for (curve_idx = 0; nurbs; nurbs = nurbs->next, curve_idx++) {
212  const int totpoint = usdCounts[curve_idx];
213 
214  if (nurbs->bp) {
215  BPoint *point = nurbs->bp;
216 
217  for (int i = 0; i < totpoint; i++, point++, vertex_idx++) {
218  point->vec[0] = usdPoints[vertex_idx][0];
219  point->vec[1] = usdPoints[vertex_idx][1];
220  point->vec[2] = usdPoints[vertex_idx][2];
221  }
222  }
223  else if (nurbs->bezt) {
224  BezTriple *bezier = nurbs->bezt;
225 
226  for (int i = 0; i < totpoint; i++, bezier++, vertex_idx++) {
227  bezier->vec[1][0] = usdPoints[vertex_idx][0];
228  bezier->vec[1][1] = usdPoints[vertex_idx][1];
229  bezier->vec[1][2] = usdPoints[vertex_idx][2];
230  }
231  }
232  }
233  }
234 
236 }
237 
238 } // namespace blender::io::usd
typedef float(TangentPoint)[2]
void BKE_nurb_knot_calc_v(struct Nurb *nu)
Definition: curve.cc:1239
struct Curve * BKE_curve_add(struct Main *bmain, const char *name, int type)
Definition: curve.cc:414
void BKE_nurb_knot_calc_u(struct Nurb *nu)
Definition: curve.cc:1234
void BKE_nurbList_free(struct ListBase *lb)
Definition: curve.cc:649
ListBase * BKE_curve_nurbs_get(struct Curve *cu)
Definition: curve.cc:4976
struct Mesh * BKE_mesh_new_nomain_from_curve(const struct Object *ob)
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
@ CU_POLY
@ CU_NURBS
@ CU_SMOOTH
#define CU_ACT_NONE
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
@ CU_3D
Object is a sort of wrapper for general info.
@ OB_CURVES_LEGACY
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
Mesh * read_mesh(struct Mesh *existing_mesh, double motionSampleTime, int read_flag, const char **err_str) override
void read_curve_sample(Curve *cu, double motionSampleTime)
pxr::UsdGeomBasisCurves curve_prim_
void read_object_data(Main *bmain, double motionSampleTime) override
void create_object(Main *bmain, double motionSampleTime) override
void read_object_data(Main *bmain, double motionSampleTime) override
#define SELECT
Curve curve
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
float weight
uint8_t f1
float vec[4]
float radius
float vec[3][3]
short resolv
float extrude
short resolu
float bevel_radius
float offset
ListBase nurb
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
short flagu
short orderu
struct Nurb * next
short flag
short type
BezTriple * bezt
BPoint * bp
short resolu
short resolv
void * data