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