1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup balembic
19 */
20
21 #include "abc_reader_object.h"
22 #include "abc_axis_conversion.h"
23 #include "abc_util.h"
24
25 #include "DNA_cachefile_types.h"
26 #include "DNA_constraint_types.h"
27 #include "DNA_modifier_types.h"
28 #include "DNA_space_types.h" /* for FILE_MAX */
29
30 #include "BKE_constraint.h"
31 #include "BKE_lib_id.h"
32 #include "BKE_modifier.h"
33 #include "BKE_object.h"
34
35 #include "BLI_listbase.h"
36 #include "BLI_math_geom.h"
37 #include "BLI_string.h"
38 #include "BLI_utildefines.h"
39
40 using Alembic::AbcGeom::IObject;
41 using Alembic::AbcGeom::IXform;
42 using Alembic::AbcGeom::IXformSchema;
43
44 namespace blender::io::alembic {
45
AbcObjectReader(const IObject & object,ImportSettings & settings)46 AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings)
47 : m_object(NULL),
48 m_iobject(object),
49 m_settings(&settings),
50 m_min_time(std::numeric_limits<chrono_t>::max()),
51 m_max_time(std::numeric_limits<chrono_t>::min()),
52 m_refcount(0),
53 parent_reader(NULL)
54 {
55 m_name = object.getFullName();
56 std::vector<std::string> parts;
57 split(m_name, '/', parts);
58
59 if (parts.size() >= 2) {
60 m_object_name = parts[parts.size() - 2];
61 m_data_name = parts[parts.size() - 1];
62 }
63 else {
64 m_object_name = m_data_name = parts[parts.size() - 1];
65 }
66
67 determine_inherits_xform();
68 }
69
70 /* Determine whether we can inherit our parent's XForm */
determine_inherits_xform()71 void AbcObjectReader::determine_inherits_xform()
72 {
73 m_inherits_xform = false;
74
75 IXform ixform = xform();
76 if (!ixform) {
77 return;
78 }
79
80 const IXformSchema &schema(ixform.getSchema());
81 if (!schema.valid()) {
82 std::cerr << "Alembic object " << ixform.getFullName() << " has an invalid schema."
83 << std::endl;
84 return;
85 }
86
87 m_inherits_xform = schema.getInheritsXforms();
88
89 IObject ixform_parent = ixform.getParent();
90 if (!ixform_parent.getParent()) {
91 /* The archive top object certainly is not a transform itself, so handle
92 * it as "no parent". */
93 m_inherits_xform = false;
94 }
95 else {
96 m_inherits_xform = ixform_parent && m_inherits_xform;
97 }
98 }
99
~AbcObjectReader()100 AbcObjectReader::~AbcObjectReader()
101 {
102 }
103
iobject() const104 const IObject &AbcObjectReader::iobject() const
105 {
106 return m_iobject;
107 }
108
object() const109 Object *AbcObjectReader::object() const
110 {
111 return m_object;
112 }
113
object(Object * ob)114 void AbcObjectReader::object(Object *ob)
115 {
116 m_object = ob;
117 }
118
blend_matrices(const Imath::M44d & m0,const Imath::M44d & m1,const float weight)119 static Imath::M44d blend_matrices(const Imath::M44d &m0, const Imath::M44d &m1, const float weight)
120 {
121 float mat0[4][4], mat1[4][4], ret[4][4];
122
123 /* Cannot use Imath::M44d::getValue() since this returns a pointer to
124 * doubles and interp_m4_m4m4 expects pointers to floats. So need to convert
125 * the matrices manually.
126 */
127
128 for (int i = 0; i < 4; i++) {
129 for (int j = 0; j < 4; j++) {
130 mat0[i][j] = static_cast<float>(m0[i][j]);
131 }
132 }
133
134 for (int i = 0; i < 4; i++) {
135 for (int j = 0; j < 4; j++) {
136 mat1[i][j] = static_cast<float>(m1[i][j]);
137 }
138 }
139
140 interp_m4_m4m4(ret, mat0, mat1, weight);
141
142 Imath::M44d m;
143
144 for (int i = 0; i < 4; i++) {
145 for (int j = 0; j < 4; j++) {
146 m[i][j] = ret[i][j];
147 }
148 }
149
150 return m;
151 }
152
get_matrix(const IXformSchema & schema,const float time)153 Imath::M44d get_matrix(const IXformSchema &schema, const float time)
154 {
155 Alembic::AbcGeom::index_t i0, i1;
156 Alembic::AbcGeom::XformSample s0, s1;
157
158 const float weight = get_weight_and_index(
159 time, schema.getTimeSampling(), schema.getNumSamples(), i0, i1);
160
161 schema.get(s0, Alembic::AbcGeom::ISampleSelector(i0));
162
163 if (i0 != i1) {
164 schema.get(s1, Alembic::AbcGeom::ISampleSelector(i1));
165 return blend_matrices(s0.getMatrix(), s1.getMatrix(), weight);
166 }
167
168 return s0.getMatrix();
169 }
170
read_mesh(struct Mesh * existing_mesh,const Alembic::Abc::ISampleSelector & UNUSED (sample_sel),int UNUSED (read_flag),const char ** UNUSED (err_str))171 struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh,
172 const Alembic::Abc::ISampleSelector &UNUSED(sample_sel),
173 int UNUSED(read_flag),
174 const char **UNUSED(err_str))
175 {
176 return existing_mesh;
177 }
178
topology_changed(Mesh *,const Alembic::Abc::ISampleSelector &)179 bool AbcObjectReader::topology_changed(Mesh * /*existing_mesh*/,
180 const Alembic::Abc::ISampleSelector & /*sample_sel*/)
181 {
182 /* The default implementation of read_mesh() just returns the original mesh, so never changes the
183 * topology. */
184 return false;
185 }
186
setupObjectTransform(const float time)187 void AbcObjectReader::setupObjectTransform(const float time)
188 {
189 bool is_constant = false;
190 float transform_from_alembic[4][4];
191
192 /* If the parent is a camera, apply the inverse rotation to make up for the from-Maya rotation.
193 * This assumes that the parent object also was imported from Alembic. */
194 if (m_object->parent != nullptr && m_object->parent->type == OB_CAMERA) {
195 axis_angle_to_mat4_single(m_object->parentinv, 'X', -M_PI_2);
196 }
197
198 this->read_matrix(transform_from_alembic, time, m_settings->scale, is_constant);
199
200 /* Apply the matrix to the object. */
201 BKE_object_apply_mat4(m_object, transform_from_alembic, true, false);
202 BKE_object_to_mat4(m_object, m_object->obmat);
203
204 if (!is_constant) {
205 bConstraint *con = BKE_constraint_add_for_object(
206 m_object, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE);
207 bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
208 BLI_strncpy(data->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
209
210 data->cache_file = m_settings->cache_file;
211 id_us_plus(&data->cache_file->id);
212 }
213 }
214
xform()215 Alembic::AbcGeom::IXform AbcObjectReader::xform()
216 {
217 /* Check that we have an empty object (locator, bone head/tail...). */
218 if (IXform::matches(m_iobject.getMetaData())) {
219 try {
220 return IXform(m_iobject, Alembic::AbcGeom::kWrapExisting);
221 }
222 catch (Alembic::Util::Exception &ex) {
223 printf("Alembic: error reading object transform for '%s': %s\n",
224 m_iobject.getFullName().c_str(),
225 ex.what());
226 return IXform();
227 }
228 }
229
230 /* Check that we have an object with actual data, in which case the
231 * parent Alembic object should contain the transform. */
232 IObject abc_parent = m_iobject.getParent();
233
234 /* The archive's top object can be recognized by not having a parent. */
235 if (abc_parent.getParent() && IXform::matches(abc_parent.getMetaData())) {
236 try {
237 return IXform(abc_parent, Alembic::AbcGeom::kWrapExisting);
238 }
239 catch (Alembic::Util::Exception &ex) {
240 printf("Alembic: error reading object transform for '%s': %s\n",
241 abc_parent.getFullName().c_str(),
242 ex.what());
243 return IXform();
244 }
245 }
246
247 /* This can happen in certain cases. For example, MeshLab exports
248 * point clouds without parent XForm. */
249 return IXform();
250 }
251
read_matrix(float r_mat[4][4],const float time,const float scale,bool & is_constant)252 void AbcObjectReader::read_matrix(float r_mat[4][4] /* local matrix */,
253 const float time,
254 const float scale,
255 bool &is_constant)
256 {
257 IXform ixform = xform();
258 if (!ixform) {
259 unit_m4(r_mat);
260 is_constant = true;
261 return;
262 }
263
264 const IXformSchema &schema(ixform.getSchema());
265 if (!schema.valid()) {
266 std::cerr << "Alembic object " << ixform.getFullName() << " has an invalid schema."
267 << std::endl;
268 return;
269 }
270
271 const Imath::M44d matrix = get_matrix(schema, time);
272 convert_matrix_datatype(matrix, r_mat);
273 copy_m44_axis_swap(r_mat, r_mat, ABC_ZUP_FROM_YUP);
274
275 /* Convert from Maya to Blender camera orientation. Children of this camera
276 * will have the opposite transform as their Parent Inverse matrix.
277 * See AbcObjectReader::setupObjectTransform(). */
278 if (m_object->type == OB_CAMERA) {
279 float camera_rotation[4][4];
280 axis_angle_to_mat4_single(camera_rotation, 'X', M_PI_2);
281 mul_m4_m4m4(r_mat, r_mat, camera_rotation);
282 }
283
284 if (!m_inherits_xform) {
285 /* Only apply scaling to root objects, parenting will propagate it. */
286 float scale_mat[4][4];
287 scale_m4_fl(scale_mat, scale);
288 mul_m4_m4m4(r_mat, scale_mat, r_mat);
289 }
290
291 is_constant = schema.isConstant();
292 }
293
addCacheModifier()294 void AbcObjectReader::addCacheModifier()
295 {
296 ModifierData *md = BKE_modifier_new(eModifierType_MeshSequenceCache);
297 BLI_addtail(&m_object->modifiers, md);
298
299 MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
300
301 mcmd->cache_file = m_settings->cache_file;
302 id_us_plus(&mcmd->cache_file->id);
303
304 BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
305 }
306
minTime() const307 chrono_t AbcObjectReader::minTime() const
308 {
309 return m_min_time;
310 }
311
maxTime() const312 chrono_t AbcObjectReader::maxTime() const
313 {
314 return m_max_time;
315 }
316
refcount() const317 int AbcObjectReader::refcount() const
318 {
319 return m_refcount;
320 }
321
incref()322 void AbcObjectReader::incref()
323 {
324 m_refcount++;
325 }
326
decref()327 void AbcObjectReader::decref()
328 {
329 m_refcount--;
330 BLI_assert(m_refcount >= 0);
331 }
332
333 } // namespace blender::io::alembic
334