Blender V4.5
abc_util.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
8
9#include "abc_util.h"
10
11#include "abc_reader_camera.h"
12#include "abc_reader_curves.h"
13#include "abc_reader_mesh.h"
14#include "abc_reader_points.h"
16
17#include <Alembic/AbcGeom/ILight.h>
18#include <Alembic/AbcGeom/INuPatch.h>
19#include <Alembic/AbcMaterial/IMaterial.h>
20
21#include <algorithm>
22
23#include "DNA_object_types.h"
24
25#include "BLI_time.h"
26
27using Alembic::Abc::IV3fArrayProperty;
28using Alembic::Abc::PropertyHeader;
29using Alembic::Abc::V3fArraySamplePtr;
30
31namespace blender::io::alembic {
32
33std::string get_id_name(const Object *const ob)
34{
35 if (!ob) {
36 return "";
37 }
38
39 return get_id_name(&ob->id);
40}
41
42std::string get_id_name(const ID *const id)
43{
44 return get_valid_abc_name(id->name + 2);
45}
46
47std::string get_valid_abc_name(const char *name)
48{
49 std::string abc_name(name);
50 std::replace(abc_name.begin(), abc_name.end(), ' ', '_');
51 std::replace(abc_name.begin(), abc_name.end(), '.', '_');
52 std::replace(abc_name.begin(), abc_name.end(), ':', '_');
53 std::replace(abc_name.begin(), abc_name.end(), '/', '_');
54 return abc_name;
55}
56
57std::string get_object_dag_path_name(const Object *const ob, Object *dupli_parent)
58{
59 std::string name = get_id_name(ob);
60
61 Object *p = ob->parent;
62
63 while (p) {
64 name = get_id_name(p) + "/" + name;
65 p = p->parent;
66 }
67
68 if (dupli_parent && (ob != dupli_parent)) {
69 name = get_id_name(dupli_parent) + "/" + name;
70 }
71
72 return name;
73}
74
75Imath::M44d convert_matrix_datatype(const float mat[4][4])
76{
77 Imath::M44d m;
78
79 for (int i = 0; i < 4; i++) {
80 for (int j = 0; j < 4; j++) {
81 m[i][j] = double(mat[i][j]);
82 }
83 }
84
85 return m;
86}
87
88void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4])
89{
90 for (int i = 0; i < 4; i++) {
91 for (int j = 0; j < 4; j++) {
92 r_mat[i][j] = float(xform[i][j]);
93 }
94 }
95}
96
97void split(const std::string &s, const char delim, std::vector<std::string> &tokens)
98{
99 tokens.clear();
100
101 std::stringstream ss(s);
102 std::string item;
103
104 while (std::getline(ss, item, delim)) {
105 if (!item.empty()) {
106 tokens.push_back(item);
107 }
108 }
109}
110
111bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
112{
113 if (!prop.valid()) {
114 return false;
115 }
116
117 return prop.getPropertyHeader(name) != nullptr;
118}
119
120V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema,
121 const Alembic::AbcGeom::ISampleSelector &selector,
122 const std::string &name)
123{
124 for (size_t i = 0; i < schema.getNumProperties(); i++) {
125 const PropertyHeader &header = schema.getPropertyHeader(i);
126
127 if (header.isCompound()) {
128 const Alembic::Abc::ICompoundProperty &prop = Alembic::Abc::ICompoundProperty(
129 schema, header.getName());
130
131 if (has_property(prop, name)) {
132 /* Header cannot be null here, as its presence is checked via has_property, so it is safe
133 * to dereference. */
134 const PropertyHeader *header = prop.getPropertyHeader(name);
135 if (!IV3fArrayProperty::matches(*header)) {
136 continue;
137 }
138
139 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
140 if (velocity_prop) {
141 return velocity_prop.getValue(selector);
142 }
143 }
144 }
145 else if (header.isArray()) {
146 if (header.getName() == name && IV3fArrayProperty::matches(header)) {
147 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
148 return velocity_prop.getValue(selector);
149 }
150 }
151 }
152
153 return V3fArraySamplePtr();
154}
155
156using index_time_pair_t = std::pair<Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t>;
157
158std::optional<SampleInterpolationSettings> get_sample_interpolation_settings(
159 const Alembic::AbcGeom::ISampleSelector &selector,
160 const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling,
161 size_t samples_number)
162{
163 const chrono_t time = selector.getRequestedTime();
164 samples_number = std::max(samples_number, size_t(1));
165
166 index_time_pair_t t0 = time_sampling->getFloorIndex(time, samples_number);
167 Alembic::AbcCoreAbstract::index_t i0 = t0.first;
168
169 if (samples_number == 1 || (fabs(time - t0.second) < 0.0001)) {
170 return {};
171 }
172
173 index_time_pair_t t1 = time_sampling->getCeilIndex(time, samples_number);
174 Alembic::AbcCoreAbstract::index_t i1 = t1.first;
175
176 if (i0 == i1) {
177 return {};
178 }
179
180 const double bias = (time - t0.second) / (t1.second - t0.second);
181
182 if (fabs(1.0 - bias) < 0.0001) {
183 return {};
184 }
185
186 return SampleInterpolationSettings{i0, i1, bias};
187}
188
189// #define USE_NURBS
190
191AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
192{
193 AbcObjectReader *reader = nullptr;
194
195 const Alembic::AbcGeom::MetaData &md = object.getMetaData();
196
197 if (Alembic::AbcGeom::IXform::matches(md)) {
198 reader = new AbcEmptyReader(object, settings);
199 }
200 else if (Alembic::AbcGeom::IPolyMesh::matches(md)) {
201 reader = new AbcMeshReader(object, settings);
202 }
203 else if (Alembic::AbcGeom::ISubD::matches(md)) {
204 reader = new AbcSubDReader(object, settings);
205 }
206 else if (Alembic::AbcGeom::INuPatch::matches(md)) {
207#ifdef USE_NURBS
208 /* TODO(kevin): importing cyclic NURBS from other software crashes
209 * at the moment. This is due to the fact that NURBS in other
210 * software have duplicated points which causes buffer overflows in
211 * Blender. Need to figure out exactly how these points are
212 * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
213 * Until this is fixed, disabling NURBS reading. */
214 reader = new AbcNurbsReader(child, settings);
215#endif
216 }
217 else if (Alembic::AbcGeom::ICamera::matches(md)) {
218 reader = new AbcCameraReader(object, settings);
219 }
220 else if (Alembic::AbcGeom::IPoints::matches(md)) {
221 reader = new AbcPointsReader(object, settings);
222 }
223 else if (Alembic::AbcMaterial::IMaterial::matches(md)) {
224 /* Pass for now. */
225 }
226 else if (Alembic::AbcGeom::ILight::matches(md)) {
227 /* Pass for now. */
228 }
229 else if (Alembic::AbcGeom::IFaceSet::matches(md)) {
230 /* Pass, those are handled in the mesh reader. */
231 }
232 else if (Alembic::AbcGeom::ICurves::matches(md)) {
233 reader = new AbcCurveReader(object, settings);
234 }
235 else {
236 std::cerr << "Alembic: unknown how to handle objects of schema '" << md.get("schemaObjTitle")
237 << "', skipping object '" << object.getFullName() << "'" << std::endl;
238 }
239
240 return reader;
241}
242
243/* ********************** */
244
245ScopeTimer::ScopeTimer(const char *message) : m_message(message), m_start(BLI_time_now_seconds())
246{
247}
248
250{
251 fprintf(stderr, "%s: %fs\n", m_message, BLI_time_now_seconds() - m_start);
252}
253
254/* ********************** */
255
256std::string SimpleLogger::str() const
257{
258 return m_stream.str();
259}
260
262{
263 m_stream.clear();
264 m_stream.str("");
265}
266
267std::ostringstream &SimpleLogger::stream()
268{
269 return m_stream;
270}
271
272std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger)
273{
274 os << logger.str();
275 return os;
276}
277
278} // namespace blender::io::alembic
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:65
Object is a sort of wrapper for general info.
ScopeTimer(const char *message)
Definition abc_util.cc:245
std::ostringstream & stream()
Definition abc_util.cc:267
ccl_device_inline float2 fabs(const float2 a)
std::string get_valid_abc_name(const char *name)
Definition abc_util.cc:47
std::ostream & operator<<(std::ostream &os, const SimpleLogger &logger)
Definition abc_util.cc:272
std::string get_object_dag_path_name(const Object *const ob, Object *dupli_parent)
get_object_dag_path_name returns the name under which the object will be exported in the Alembic file...
Definition abc_util.cc:57
V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema, const Alembic::AbcGeom::ISampleSelector &selector, const std::string &name)
Definition abc_util.cc:120
std::string get_id_name(const Object *const ob)
Definition abc_util.cc:33
Imath::M44d convert_matrix_datatype(const float mat[4][4])
Definition abc_util.cc:75
std::pair< Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t > index_time_pair_t
Definition abc_util.cc:156
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
Definition abc_util.cc:111
AbcObjectReader * create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
Definition abc_util.cc:191
std::optional< SampleInterpolationSettings > get_sample_interpolation_settings(const Alembic::AbcGeom::ISampleSelector &selector, const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling, size_t samples_number)
Definition abc_util.cc:158
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition abc_util.cc:97
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
struct Object * parent
i
Definition text_draw.cc:230