Blender  V3.3
abc_reader_nurbs.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "abc_reader_nurbs.h"
8 #include "abc_axis_conversion.h"
9 #include "abc_reader_transform.h"
10 #include "abc_util.h"
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "DNA_curve_types.h"
15 #include "DNA_object_types.h"
16 
17 #include "BLI_listbase.h"
18 #include "BLI_string.h"
19 
20 #include "BKE_curve.h"
21 #include "BKE_object.h"
22 
23 using Alembic::AbcGeom::FloatArraySamplePtr;
24 using Alembic::AbcGeom::kWrapExisting;
25 using Alembic::AbcGeom::MetaData;
26 using Alembic::AbcGeom::P3fArraySamplePtr;
27 
28 using Alembic::AbcGeom::ICompoundProperty;
29 using Alembic::AbcGeom::INuPatch;
30 using Alembic::AbcGeom::INuPatchSchema;
31 using Alembic::AbcGeom::IObject;
32 
33 namespace blender::io::alembic {
34 
35 AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings)
36  : AbcObjectReader(object, settings)
37 {
38  getNurbsPatches(m_iobject);
39  get_min_max_time(m_iobject, m_schemas[0].first, m_min_time, m_max_time);
40 }
41 
43 {
44  if (m_schemas.empty()) {
45  return false;
46  }
47 
48  std::vector<std::pair<INuPatchSchema, IObject>>::const_iterator it;
49  for (it = m_schemas.begin(); it != m_schemas.end(); ++it) {
50  const INuPatchSchema &schema = it->first;
51 
52  if (!schema.valid()) {
53  return false;
54  }
55  }
56 
57  return true;
58 }
59 
61  const Alembic::AbcCoreAbstract::v12::ObjectHeader &alembic_header,
62  const Object *const ob,
63  const char **err_str) const
64 {
65  if (!Alembic::AbcGeom::INuPatch::matches(alembic_header)) {
66  *err_str =
67  "Object type mismatch, Alembic object path pointed to NURBS when importing, but not any "
68  "more.";
69  return false;
70  }
71 
72  if (ob->type != OB_CURVES_LEGACY) {
73  *err_str = "Object type mismatch, Alembic object path points to NURBS.";
74  return false;
75  }
76 
77  return true;
78 }
79 
80 static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots)
81 {
82  if (!knots || knots->size() < 2) {
83  return false;
84  }
85 
86  /* Skip first and last knots, as they are used for padding. */
87  const size_t num_knots = knots->size() - 2;
88  nu_knots = static_cast<float *>(MEM_callocN(num_knots * sizeof(float), "abc_setsplineknotsu"));
89 
90  for (size_t i = 0; i < num_knots; i++) {
91  nu_knots[i] = (*knots)[i + 1];
92  }
93 
94  return true;
95 }
96 
97 void AbcNurbsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
98 {
99  Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, m_data_name.c_str(), OB_SURF));
100  cu->actvert = CU_ACT_NONE;
101 
102  std::vector<std::pair<INuPatchSchema, IObject>>::iterator it;
103 
104  for (it = m_schemas.begin(); it != m_schemas.end(); ++it) {
105  Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), "abc_getnurb"));
106  nu->flag = CU_SMOOTH;
107  nu->type = CU_NURBS;
108  nu->resolu = cu->resolu;
109  nu->resolv = cu->resolv;
110 
111  const INuPatchSchema &schema = it->first;
112  INuPatchSchema::Sample smp;
113  try {
114  smp = schema.getValue(sample_sel);
115  }
116  catch (Alembic::Util::Exception &ex) {
117  printf("Alembic: error reading nurbs sample for '%s/%s' at time %f: %s\n",
118  m_iobject.getFullName().c_str(),
119  schema.getName().c_str(),
120  sample_sel.getRequestedTime(),
121  ex.what());
122  return;
123  }
124 
125  nu->orderu = smp.getUOrder() - 1;
126  nu->orderv = smp.getVOrder() - 1;
127  nu->pntsu = smp.getNumU();
128  nu->pntsv = smp.getNumV();
129 
130  /* Read positions and weights. */
131 
132  const P3fArraySamplePtr positions = smp.getPositions();
133  const FloatArraySamplePtr weights = smp.getPositionWeights();
134 
135  const size_t num_points = positions->size();
136 
137  nu->bp = static_cast<BPoint *>(MEM_callocN(num_points * sizeof(BPoint), "abc_setsplinetype"));
138 
139  BPoint *bp = nu->bp;
140  float posw_in = 1.0f;
141 
142  for (int i = 0; i < num_points; i++, bp++) {
143  const Imath::V3f &pos_in = (*positions)[i];
144 
145  if (weights) {
146  posw_in = (*weights)[i];
147  }
148 
149  copy_zup_from_yup(bp->vec, pos_in.getValue());
150  bp->vec[3] = posw_in;
151  bp->f1 = SELECT;
152  bp->radius = 1.0f;
153  bp->weight = 1.0f;
154  }
155 
156  /* Read knots. */
157 
158  if (!set_knots(smp.getUKnot(), nu->knotsu)) {
160  }
161 
162  if (!set_knots(smp.getVKnot(), nu->knotsv)) {
164  }
165 
166  /* Read flags. */
167 
168  ICompoundProperty user_props = schema.getUserProperties();
169 
170  if (has_property(user_props, "enpoint_u")) {
171  nu->flagu |= CU_NURB_ENDPOINT;
172  }
173 
174  if (has_property(user_props, "enpoint_v")) {
175  nu->flagv |= CU_NURB_ENDPOINT;
176  }
177 
178  if (has_property(user_props, "cyclic_u")) {
179  nu->flagu |= CU_NURB_CYCLIC;
180  }
181 
182  if (has_property(user_props, "cyclic_v")) {
183  nu->flagv |= CU_NURB_CYCLIC;
184  }
185 
187  }
188 
190  m_object->data = cu;
191 }
192 
193 void AbcNurbsReader::getNurbsPatches(const IObject &obj)
194 {
195  if (!obj.valid()) {
196  return;
197  }
198 
199  const int num_children = obj.getNumChildren();
200 
201  if (num_children == 0) {
202  INuPatch abc_nurb(obj, kWrapExisting);
203  INuPatchSchema schem = abc_nurb.getSchema();
204  m_schemas.emplace_back(schem, obj);
205  return;
206  }
207 
208  for (int i = 0; i < num_children; i++) {
209  bool ok = true;
210  IObject child(obj, obj.getChildHeader(i).getName());
211 
212  if (!m_name.empty() && child.valid() && !begins_with(child.getFullName(), m_name)) {
213  ok = false;
214  }
215 
216  if (!child.valid()) {
217  continue;
218  }
219 
220  const MetaData &md = child.getMetaData();
221 
222  if (INuPatch::matches(md) && ok) {
223  INuPatch abc_nurb(child, kWrapExisting);
224  INuPatchSchema schem = abc_nurb.getSchema();
225  m_schemas.emplace_back(schem, child);
226  }
227 
228  getNurbsPatches(child);
229  }
230 }
231 
232 } // namespace blender::io::alembic
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
ListBase * BKE_curve_nurbs_get(struct Curve *cu)
Definition: curve.cc:4976
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
@ CU_NURBS
@ CU_SMOOTH
#define CU_ACT_NONE
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
Object is a sort of wrapper for general info.
@ OB_SURF
@ OB_CURVES_LEGACY
Read Guarded memory(de)allocation.
bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, const Object *const ob, const char **err_str) const override
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) override
AbcNurbsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
#define SELECT
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
bool begins_with(const TContainer &input, const TContainer &match)
Definition: abc_util.h:42
void get_min_max_time(const Alembic::AbcGeom::IObject &object, const Schema &schema, chrono_t &min, chrono_t &max)
Definition: abc_util.h:66
BLI_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
Definition: abc_util.cc:106
static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots)
MutableSpan< float3 > positions
float weight
uint8_t f1
float vec[4]
float radius
short resolv
short resolu
Definition: BKE_main.h:121
short flagu
short orderu
short orderv
float * knotsu
short flag
short type
float * knotsv
BPoint * bp
short resolu
short resolv
short flagv
void * data