21 #include "../ABC_alembic.h"
23 #include <Alembic/AbcMaterial/IMaterial.h>
70 using Alembic::Abc::IV3fArrayProperty;
71 using Alembic::Abc::ObjectHeader;
72 using Alembic::Abc::PropertyHeader;
73 using Alembic::Abc::V3fArraySamplePtr;
74 using Alembic::AbcGeom::ICamera;
75 using Alembic::AbcGeom::ICurves;
76 using Alembic::AbcGeom::IFaceSet;
77 using Alembic::AbcGeom::ILight;
78 using Alembic::AbcGeom::INuPatch;
79 using Alembic::AbcGeom::IObject;
80 using Alembic::AbcGeom::IPoints;
81 using Alembic::AbcGeom::IPolyMesh;
82 using Alembic::AbcGeom::IPolyMeshSchema;
83 using Alembic::AbcGeom::ISampleSelector;
84 using Alembic::AbcGeom::ISubD;
85 using Alembic::AbcGeom::IXform;
86 using Alembic::AbcGeom::kWrapExisting;
87 using Alembic::AbcGeom::MetaData;
88 using Alembic::AbcMaterial::IMaterial;
112 if (!
object.valid()) {
116 size_t children_claiming_this_object = 0;
117 size_t num_children =
object.getNumChildren();
119 for (
size_t i = 0; i < num_children; i++) {
121 children_claiming_this_object += child_claims_this_object ? 1 : 0;
124 const MetaData &md =
object.getMetaData();
125 bool get_path =
false;
126 bool parent_is_part_of_this_object =
false;
131 else if (IXform::matches(md)) {
136 get_path = children_claiming_this_object == 0;
140 parent_is_part_of_this_object =
false;
144 get_path = IPolyMesh::matches(md) || ISubD::matches(md) ||
146 INuPatch::matches(md) ||
148 ICamera::matches(md) || IPoints::matches(md) || ICurves::matches(md);
149 parent_is_part_of_this_object = get_path;
160 return parent_is_part_of_this_object;
164 const char *filename,
169 if (!archive->
valid()) {
188 return ALEMBIC_LIBRARY_VERSION;
191 static void find_iobject(
const IObject &
object, IObject &
ret,
const std::string &path)
193 if (!
object.valid()) {
197 std::vector<std::string> tokens;
198 split(path,
'/', tokens);
200 IObject tmp = object;
202 std::vector<std::string>::iterator iter;
203 for (iter = tokens.begin(); iter != tokens.end(); ++iter) {
204 IObject child = tmp.getChild(*iter);
234 const IObject &
object,
239 const std::string &full_name =
object.getFullName();
241 if (!
object.valid()) {
242 std::cerr <<
" - " << full_name <<
": object is invalid, skipping it and all its children.\n";
250 size_t children_claiming_this_object = 0;
251 size_t num_children =
object.getNumChildren();
255 for (
size_t i = 0; i < num_children; i++) {
256 const IObject ichild =
object.getChild(i);
259 std::pair<bool, AbcObjectReader *> child_result;
260 child_result =
visit_object(ichild, readers, settings, assign_as_parent);
262 bool child_claims_this_object = child_result.first;
265 if (child_reader ==
nullptr) {
269 if (child_claims_this_object) {
270 claiming_child_readers.push_back(child_reader);
273 nonclaiming_child_readers.push_back(child_reader);
277 children_claiming_this_object += child_claims_this_object ? 1 : 0;
279 BLI_assert(children_claiming_this_object == claiming_child_readers.size());
282 const MetaData &md =
object.getMetaData();
283 bool parent_is_part_of_this_object =
false;
288 else if (IXform::matches(md)) {
301 create_empty = claiming_child_readers.empty();
308 else if (IPolyMesh::matches(md)) {
310 parent_is_part_of_this_object =
true;
312 else if (ISubD::matches(md)) {
314 parent_is_part_of_this_object =
true;
316 else if (INuPatch::matches(md)) {
325 parent_is_part_of_this_object =
true;
328 else if (ICamera::matches(md)) {
330 parent_is_part_of_this_object =
true;
332 else if (IPoints::matches(md)) {
334 parent_is_part_of_this_object =
true;
336 else if (IMaterial::matches(md)) {
339 else if (ILight::matches(md)) {
342 else if (IFaceSet::matches(md)) {
345 else if (ICurves::matches(md)) {
347 parent_is_part_of_this_object =
true;
350 std::cerr <<
"Alembic object " << full_name <<
" is of unsupported schema type '"
351 <<
object.getMetaData().get(
"schemaObjTitle") <<
"'" << std::endl;
359 readers.push_back(reader);
368 if (nonclaiming_child_readers.size() + assign_as_parent.size() > 0) {
370 child_reader->parent_reader = reader;
378 if (!claiming_child_readers.empty()) {
391 r_assign_as_parent.push_back(child_reader);
399 r_assign_as_parent.push_back(child_reader);
402 r_assign_as_parent.push_back(child_reader);
405 r_assign_as_parent.push_back(child_reader);
410 return std::make_pair(parent_is_part_of_this_object, reader);
443 SCOPE_TIMER(
"Alembic import, objects reading and creation");
448 data->do_update = do_update;
449 data->progress = progress;
455 if (!archive->
valid()) {
470 cache_file->
scale =
data->settings.scale;
473 data->archive = archive;
474 data->settings.cache_file = cache_file;
476 *
data->do_update =
true;
477 *
data->progress = 0.05f;
487 data->was_cancelled =
true;
491 *
data->do_update =
true;
492 *
data->progress = 0.1f;
496 const float size =
static_cast<float>(
data->readers.size());
502 ISampleSelector sample_sel(0.0f);
503 std::vector<AbcObjectReader *>::iterator iter;
504 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
507 if (reader->
valid()) {
514 std::cerr <<
"Object " << reader->
name() <<
" in Alembic file " <<
data->filename
518 *
data->progress = 0.1f + 0.3f * (++i /
size);
519 *
data->do_update =
true;
522 data->was_cancelled =
true;
527 if (
data->settings.set_frame_range) {
530 if (
data->settings.is_sequence) {
531 SFRA =
data->settings.sequence_offset;
535 else if (min_time < max_time) {
536 SFRA =
static_cast<int>(round(min_time *
FPS));
537 EFRA =
static_cast<int>(round(max_time *
FPS));
543 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
558 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
562 *
data->progress = 0.7f + 0.3f * (++i /
size);
563 *
data->do_update =
true;
566 data->was_cancelled =
true;
578 std::vector<AbcObjectReader *>::iterator iter;
581 if (
data->was_cancelled) {
582 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
583 Object *ob = (*iter)->object();
604 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
605 Object *ob = (*iter)->object();
623 if (
data->is_background_job) {
630 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
641 switch (
data->error_code) {
644 data->import_ok = !
data->was_cancelled;
647 WM_report(
RPT_ERROR,
"Could not open Alembic archive for reading! See console for detail.");
657 delete data->archive;
662 const char *filepath,
665 bool set_frame_range,
668 bool validate_meshes,
669 bool as_background_job)
694 bool import_ok =
false;
695 if (as_background_job) {
712 short stop = 0, do_update = 0;
713 float progress = 0.0f;
735 bool is_constant =
false;
742 if (object->
parent ==
nullptr) {
748 float mat_parent[4][4];
751 float mat_local[4][4];
762 IObject iobject = abc_reader->
iobject();
764 if (!iobject.valid()) {
765 *err_str =
"Invalid object: verify object path";
769 const ObjectHeader &header = iobject.getHeader();
782 return ISampleSelector(
time, ISampleSelector::kFloorIndex);
789 const char **err_str,
793 if (abc_reader ==
nullptr) {
798 return abc_reader->
read_mesh(existing_mesh, sample_sel, read_flag, err_str);
805 if (abc_reader ==
nullptr) {
834 const char *object_path)
836 if (object_path[0] ==
'\0') {
842 if (!archive || !archive->
valid()) {
855 if (abc_reader ==
nullptr) {
859 abc_reader->
object(
object);
862 return reinterpret_cast<CacheReader *
>(abc_reader);
869 const PropertyHeader *prop_header = schema.getPropertyHeader(name);
875 ICompoundProperty prop = schema.getArbGeomParams();
881 return prop.getPropertyHeader(name);
892 IObject iobject = abc_reader->
iobject();
894 if (!iobject.valid()) {
898 const ObjectHeader &header = iobject.getHeader();
900 if (!IPolyMesh::matches(header)) {
904 IPolyMesh
mesh(iobject, kWrapExisting);
905 IPolyMeshSchema schema =
mesh.getSchema();
913 return IV3fArrayProperty::matches(prop_header->getMetaData());
917 const ISampleSelector &iss,
918 const std::string &name)
920 const PropertyHeader *prop_header = schema.getPropertyHeader(name);
923 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0);
924 return velocity_prop.getValue(iss);
927 ICompoundProperty prop = schema.getArbGeomParams();
930 return V3fArraySamplePtr();
933 const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0);
936 return velocity_prop.getValue(iss);
939 return V3fArraySamplePtr();
943 const char *velocity_name,
945 float velocity_scale,
947 float *r_vertex_velocities)
955 IObject iobject = abc_reader->
iobject();
957 if (!iobject.valid()) {
961 const ObjectHeader &header = iobject.getHeader();
963 if (!IPolyMesh::matches(header)) {
967 IPolyMesh
mesh(iobject, kWrapExisting);
968 IPolyMeshSchema schema =
mesh.getSchema();
969 ISampleSelector sample_sel(
time);
970 const IPolyMeshSchema::Sample
sample = schema.getValue(sample_sel);
972 V3fArraySamplePtr velocities =
get_velocity_prop(schema, sample_sel, velocity_name);
980 int num_velocity_vectors =
static_cast<int>(velocities->size());
982 if (num_velocity_vectors != num_vertices) {
986 for (
size_t i = 0; i < velocities->size(); ++i) {
987 const Imath::V3f &vel_in = (*velocities)[i];
void * BKE_cachefile_add(struct Main *bmain, const char *name)
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
struct Scene * CTX_data_scene(const bContext *C)
struct wmWindowManager * CTX_wm_manager(const bContext *C)
struct ViewLayer * CTX_data_view_layer(const bContext *C)
struct Main * CTX_data_main(const bContext *C)
struct wmWindow * CTX_wm_window(const bContext *C)
struct LayerCollection * BKE_layer_collection_get_active(struct ViewLayer *view_layer)
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
void id_us_min(struct ID *id)
void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL()
General operations, lookup, etc. for blender objects.
void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4])
File and directory operations.
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
#define STRNCPY(dst, src)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_COPY_ON_WRITE
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
void ED_undo_push(struct bContext *C, const char *str)
Read Guarded memory(de)allocation.
#define SCOPE_TIMER(message)
BLI_INLINE ArchiveReader * archive_from_handle(AbcArchiveHandle *handle)
bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, bool validate_meshes, bool as_background_job)
static void import_freejob(void *user_data)
static void import_startjob(void *user_data, short *stop, short *do_update, float *progress)
CacheReader * CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
bool ABC_mesh_topology_changed(CacheReader *reader, Object *ob, Mesh *existing_mesh, const float time, const char **err_str)
AbcArchiveHandle * ABC_create_handle(struct Main *bmain, const char *filename, ListBase *object_paths)
BLI_INLINE AbcArchiveHandle * handle_from_archive(ArchiveReader *archive)
bool ABC_has_vec3_array_property_named(struct CacheReader *reader, const char *name)
Mesh * ABC_read_mesh(CacheReader *reader, Object *ob, Mesh *existing_mesh, const float time, const char **err_str, int read_flag)
static bool gather_objects_paths(const IObject &object, ListBase *object_paths)
void CacheReader_incref(CacheReader *reader)
static ISampleSelector sample_selector_for_time(float time)
void ABC_free_handle(AbcArchiveHandle *handle)
static AbcObjectReader * get_abc_reader(CacheReader *reader, Object *ob, const char **err_str)
void ABC_get_transform(CacheReader *reader, float r_mat_world[4][4], float time, float scale)
int ABC_read_velocity_cache(CacheReader *reader, const char *velocity_name, const float time, float velocity_scale, int num_vertices, float *r_vertex_velocities)
static V3fArraySamplePtr get_velocity_prop(const IPolyMeshSchema &schema, const ISampleSelector &iss, const std::string &name)
static void import_endjob(void *user_data)
static void find_iobject(const IObject &object, IObject &ret, const std::string &path)
void CacheReader_free(CacheReader *reader)
static std::pair< bool, AbcObjectReader * > visit_object(const IObject &object, AbcObjectReader::ptr_vector &readers, ImportSettings &settings, AbcObjectReader::ptr_vector &r_assign_as_parent)
static const PropertyHeader * get_property_header(const IPolyMeshSchema &schema, const char *name)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
int getParent(int link_num) const
AbcObjectReader * parent_reader
virtual struct Mesh * read_mesh(struct Mesh *mesh, const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char **err_str)
void setupObjectTransform(const float time)
const Alembic::Abc::IObject & iobject() const
virtual bool valid() const =0
bool inherits_xform() const
const std::string & name() const
virtual bool topology_changed(Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel)
virtual void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)=0
void read_matrix(float r_mat[4][4], const float time, const float scale, bool &is_constant)
virtual bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, const Object *const ob, const char **err_str) const =0
std::vector< AbcObjectReader * > ptr_vector
Alembic::Abc::IObject getTop()
void *(* MEM_callocN)(size_t len, const char *str)
static void sample(SocketReader *reader, int x, int y, float color[4])
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)
AbcObjectReader * create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
The CacheReader struct is only used for anonymous pointers, to interface between C and C++ code....
std::vector< AbcObjectReader * > readers
struct Collection * collection
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_report(ReportType type, const char *message)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)