Blender V5.0
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
23using Alembic::Abc::IV3fArrayProperty;
24using Alembic::Abc::PropertyHeader;
25using Alembic::Abc::V3fArraySamplePtr;
26
27namespace blender::io::alembic {
28
29std::string get_valid_abc_name(const char *name)
30{
31 std::string abc_name(name);
32 std::replace(abc_name.begin(), abc_name.end(), ' ', '_');
33 std::replace(abc_name.begin(), abc_name.end(), '.', '_');
34 std::replace(abc_name.begin(), abc_name.end(), ':', '_');
35 std::replace(abc_name.begin(), abc_name.end(), '/', '_');
36 return abc_name;
37}
38
39Imath::M44d convert_matrix_datatype(const float mat[4][4])
40{
41 Imath::M44d m;
42
43 for (int i = 0; i < 4; i++) {
44 for (int j = 0; j < 4; j++) {
45 m[i][j] = double(mat[i][j]);
46 }
47 }
48
49 return m;
50}
51
52void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4])
53{
54 for (int i = 0; i < 4; i++) {
55 for (int j = 0; j < 4; j++) {
56 r_mat[i][j] = float(xform[i][j]);
57 }
58 }
59}
60
61void split(const std::string &s, const char delim, std::vector<std::string> &tokens)
62{
63 tokens.clear();
64
65 std::stringstream ss(s);
66 std::string item;
67
68 while (std::getline(ss, item, delim)) {
69 if (!item.empty()) {
70 tokens.push_back(item);
71 }
72 }
73}
74
75bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
76{
77 if (!prop.valid()) {
78 return false;
79 }
80
81 return prop.getPropertyHeader(name) != nullptr;
82}
83
84V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema,
85 const Alembic::AbcGeom::ISampleSelector &selector,
86 const std::string &name)
87{
88 for (size_t i = 0; i < schema.getNumProperties(); i++) {
89 const PropertyHeader &header = schema.getPropertyHeader(i);
90
91 if (header.isCompound()) {
92 const Alembic::Abc::ICompoundProperty &prop = Alembic::Abc::ICompoundProperty(
93 schema, header.getName());
94
95 if (has_property(prop, name)) {
96 /* Header cannot be null here, as its presence is checked via has_property, so it is safe
97 * to dereference. */
98 const PropertyHeader *header = prop.getPropertyHeader(name);
99 if (!IV3fArrayProperty::matches(*header)) {
100 continue;
101 }
102
103 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
104 if (velocity_prop) {
105 return velocity_prop.getValue(selector);
106 }
107 }
108 }
109 else if (header.isArray()) {
110 if (header.getName() == name && IV3fArrayProperty::matches(header)) {
111 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
112 return velocity_prop.getValue(selector);
113 }
114 }
115 }
116
117 return V3fArraySamplePtr();
118}
119
120using index_time_pair_t = std::pair<Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t>;
121
122std::optional<SampleInterpolationSettings> get_sample_interpolation_settings(
123 const Alembic::AbcGeom::ISampleSelector &selector,
124 const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling,
125 size_t samples_number)
126{
127 const chrono_t time = selector.getRequestedTime();
128 samples_number = std::max(samples_number, size_t(1));
129
130 index_time_pair_t t0 = time_sampling->getFloorIndex(time, samples_number);
131 Alembic::AbcCoreAbstract::index_t i0 = t0.first;
132
133 if (samples_number == 1 || (fabs(time - t0.second) < 0.0001)) {
134 return {};
135 }
136
137 index_time_pair_t t1 = time_sampling->getCeilIndex(time, samples_number);
138 Alembic::AbcCoreAbstract::index_t i1 = t1.first;
139
140 if (i0 == i1) {
141 return {};
142 }
143
144 const double bias = (time - t0.second) / (t1.second - t0.second);
145
146 if (fabs(1.0 - bias) < 0.0001) {
147 return {};
148 }
149
150 return SampleInterpolationSettings{i0, i1, bias};
151}
152
153// #define USE_NURBS
154
155AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
156{
157 AbcObjectReader *reader = nullptr;
158
159 const Alembic::AbcGeom::MetaData &md = object.getMetaData();
160
161 if (Alembic::AbcGeom::IXform::matches(md)) {
162 reader = new AbcEmptyReader(object, settings);
163 }
164 else if (Alembic::AbcGeom::IPolyMesh::matches(md)) {
165 reader = new AbcMeshReader(object, settings);
166 }
167 else if (Alembic::AbcGeom::ISubD::matches(md)) {
168 reader = new AbcSubDReader(object, settings);
169 }
170 else if (Alembic::AbcGeom::INuPatch::matches(md)) {
171#ifdef USE_NURBS
172 /* TODO(kevin): importing cyclic NURBS from other software crashes
173 * at the moment. This is due to the fact that NURBS in other
174 * software have duplicated points which causes buffer overflows in
175 * Blender. Need to figure out exactly how these points are
176 * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
177 * Until this is fixed, disabling NURBS reading. */
178 reader = new AbcNurbsReader(child, settings);
179#endif
180 }
181 else if (Alembic::AbcGeom::ICamera::matches(md)) {
182 reader = new AbcCameraReader(object, settings);
183 }
184 else if (Alembic::AbcGeom::IPoints::matches(md)) {
185 reader = new AbcPointsReader(object, settings);
186 }
187 else if (Alembic::AbcMaterial::IMaterial::matches(md)) {
188 /* Pass for now. */
189 }
190 else if (Alembic::AbcGeom::ILight::matches(md)) {
191 /* Pass for now. */
192 }
193 else if (Alembic::AbcGeom::IFaceSet::matches(md)) {
194 /* Pass, those are handled in the mesh reader. */
195 }
196 else if (Alembic::AbcGeom::ICurves::matches(md)) {
197 reader = new AbcCurveReader(object, settings);
198 }
199 else {
200 std::cerr << "Alembic: unknown how to handle objects of schema '" << md.get("schemaObjTitle")
201 << "', skipping object '" << object.getFullName() << "'" << std::endl;
202 }
203
204 return reader;
205}
206
207} // namespace blender::io::alembic
nullptr float
ccl_device_inline float2 fabs(const float2 a)
std::string get_valid_abc_name(const char *name)
Definition abc_util.cc:29
V3fArraySamplePtr get_velocity_prop(const Alembic::Abc::ICompoundProperty &schema, const Alembic::AbcGeom::ISampleSelector &selector, const std::string &name)
Definition abc_util.cc:84
Imath::M44d convert_matrix_datatype(const float mat[4][4])
Definition abc_util.cc:39
std::pair< Alembic::AbcCoreAbstract::index_t, Alembic::AbcGeom::chrono_t > index_time_pair_t
Definition abc_util.cc:120
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
Definition abc_util.cc:75
AbcObjectReader * create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
Definition abc_util.cc:155
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:122
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition abc_util.cc:61
const char * name
i
Definition text_draw.cc:230