7 #include "../ABC_alembic.h"
10 #include <Alembic/AbcMaterial/IMaterial.h>
58 using Alembic::Abc::IV3fArrayProperty;
59 using Alembic::Abc::ObjectHeader;
60 using Alembic::Abc::PropertyHeader;
61 using Alembic::Abc::V3fArraySamplePtr;
62 using Alembic::AbcGeom::ICamera;
63 using Alembic::AbcGeom::ICurves;
64 using Alembic::AbcGeom::IFaceSet;
65 using Alembic::AbcGeom::ILight;
66 using Alembic::AbcGeom::INuPatch;
67 using Alembic::AbcGeom::IObject;
68 using Alembic::AbcGeom::IPoints;
69 using Alembic::AbcGeom::IPolyMesh;
70 using Alembic::AbcGeom::IPolyMeshSchema;
71 using Alembic::AbcGeom::ISampleSelector;
72 using Alembic::AbcGeom::ISubD;
73 using Alembic::AbcGeom::IXform;
74 using Alembic::AbcGeom::kWrapExisting;
75 using Alembic::AbcGeom::MetaData;
76 using Alembic::AbcMaterial::IMaterial;
96 if (!
object.valid()) {
100 size_t children_claiming_this_object = 0;
101 size_t num_children =
object.getNumChildren();
103 for (
size_t i = 0; i < num_children; i++) {
105 children_claiming_this_object += child_claims_this_object ? 1 : 0;
108 const MetaData &md =
object.getMetaData();
109 bool get_path =
false;
110 bool parent_is_part_of_this_object =
false;
115 else if (IXform::matches(md)) {
120 get_path = children_claiming_this_object == 0;
124 parent_is_part_of_this_object =
false;
128 get_path = IPolyMesh::matches(md) || ISubD::matches(md) ||
130 INuPatch::matches(md) ||
132 ICamera::matches(md) || IPoints::matches(md) || ICurves::matches(md);
133 parent_is_part_of_this_object = get_path;
144 return parent_is_part_of_this_object;
148 const char *filename,
152 std::vector<const char *> filenames;
153 filenames.push_back(filename);
157 filenames.push_back(layers->
filepath);
159 layers = layers->
next;
163 std::reverse(filenames.begin(), filenames.end());
167 if (!archive || !archive->
valid()) {
186 return ALEMBIC_LIBRARY_VERSION;
189 static void find_iobject(
const IObject &
object, IObject &
ret,
const std::string &path)
191 if (!
object.valid()) {
195 std::vector<std::string> tokens;
196 split(path,
'/', tokens);
198 IObject tmp = object;
200 std::vector<std::string>::iterator iter;
201 for (iter = tokens.begin(); iter != tokens.end(); ++iter) {
202 IObject child = tmp.getChild(*iter);
232 const IObject &
object,
237 const std::string &full_name =
object.getFullName();
239 if (!
object.valid()) {
240 std::cerr <<
" - " << full_name <<
": object is invalid, skipping it and all its children.\n";
248 size_t children_claiming_this_object = 0;
249 size_t num_children =
object.getNumChildren();
253 for (
size_t i = 0; i < num_children; i++) {
254 const IObject ichild =
object.getChild(i);
257 std::pair<bool, AbcObjectReader *> child_result;
258 child_result =
visit_object(ichild, readers, settings, assign_as_parent);
260 bool child_claims_this_object = child_result.first;
263 if (child_reader ==
nullptr) {
267 if (child_claims_this_object) {
268 claiming_child_readers.push_back(child_reader);
271 nonclaiming_child_readers.push_back(child_reader);
275 children_claiming_this_object += child_claims_this_object ? 1 : 0;
277 BLI_assert(children_claiming_this_object == claiming_child_readers.size());
281 const MetaData &md =
object.getMetaData();
282 bool parent_is_part_of_this_object =
false;
287 else if (IXform::matches(md)) {
300 create_empty = claiming_child_readers.empty();
307 else if (IPolyMesh::matches(md)) {
309 parent_is_part_of_this_object =
true;
311 else if (ISubD::matches(md)) {
313 parent_is_part_of_this_object =
true;
315 else if (INuPatch::matches(md)) {
324 parent_is_part_of_this_object =
true;
327 else if (ICamera::matches(md)) {
329 parent_is_part_of_this_object =
true;
331 else if (IPoints::matches(md)) {
333 parent_is_part_of_this_object =
true;
335 else if (IMaterial::matches(md)) {
338 else if (ILight::matches(md)) {
341 else if (IFaceSet::matches(md)) {
344 else if (ICurves::matches(md)) {
346 parent_is_part_of_this_object =
true;
349 std::cerr <<
"Alembic object " << full_name <<
" is of unsupported schema type '"
350 <<
object.getMetaData().get(
"schemaObjTitle") <<
"'" << std::endl;
358 readers.push_back(reader);
367 if (nonclaiming_child_readers.size() + assign_as_parent.size() > 0) {
369 child_reader->parent_reader = reader;
377 if (!claiming_child_readers.empty()) {
390 r_assign_as_parent.push_back(child_reader);
398 r_assign_as_parent.push_back(child_reader);
401 r_assign_as_parent.push_back(child_reader);
404 r_assign_as_parent.push_back(child_reader);
409 return std::make_pair(parent_is_part_of_this_object, reader);
444 std::cout <<
"Alembic import of '" <<
data->filename <<
"' took ";
451 SCOPE_TIMER(
"Alembic import, objects reading and creation");
456 data->do_update = do_update;
457 data->progress = progress;
458 data->start_time = blender::timeit::Clock::now();
464 if (!archive || !archive->
valid()) {
479 cache_file->
scale =
data->settings.scale;
482 data->archive = archive;
483 data->settings.cache_file = cache_file;
485 *
data->do_update =
true;
486 *
data->progress = 0.05f;
496 data->was_cancelled =
true;
500 *
data->do_update =
true;
501 *
data->progress = 0.1f;
505 const float size =
static_cast<float>(
data->readers.size());
511 ISampleSelector sample_sel(0.0);
512 std::vector<AbcObjectReader *>::iterator iter;
513 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
516 if (reader->
valid()) {
523 std::cerr <<
"Object " << reader->
name() <<
" in Alembic file " <<
data->filename
527 *
data->progress = 0.1f + 0.3f * (++i /
size);
528 *
data->do_update =
true;
531 data->was_cancelled =
true;
536 if (
data->settings.set_frame_range) {
539 if (
data->settings.is_sequence) {
544 else if (min_time < max_time) {
552 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
567 for (iter =
data->readers.begin(); iter !=
data->readers.end(); ++iter) {
571 *
data->progress = 0.7f + 0.3f * (++i /
size);
572 *
data->do_update =
true;
575 data->was_cancelled =
true;
588 if (
data->was_cancelled) {
635 if (
data->is_background_job) {
652 switch (
data->error_code) {
655 data->import_ok = !
data->was_cancelled;
658 WM_report(
RPT_ERROR,
"Could not open Alembic archive for reading! See console for detail.");
669 delete data->archive;
674 const char *filepath,
677 bool set_frame_range,
680 bool validate_meshes,
681 bool always_add_cache_reader,
682 bool as_background_job)
708 bool import_ok =
false;
709 if (as_background_job) {
726 short stop = 0, do_update = 0;
727 float progress = 0.0f;
749 bool is_constant =
false;
756 if (object->
parent ==
nullptr) {
762 float mat_parent[4][4];
765 float mat_local[4][4];
776 IObject iobject = abc_reader->
iobject();
778 if (!iobject.valid()) {
779 *err_str =
"Invalid object: verify object path";
783 const ObjectHeader &header = iobject.getHeader();
796 return ISampleSelector(
time, ISampleSelector::kFloorIndex);
803 const char **err_str)
806 if (abc_reader ==
nullptr) {
811 return abc_reader->
read_mesh(existing_mesh,
821 const Mesh *existing_mesh,
823 const char **err_str)
826 if (abc_reader ==
nullptr) {
855 const char *object_path)
857 if (object_path[0] ==
'\0') {
863 if (!archive || !archive->
valid()) {
876 if (abc_reader ==
nullptr) {
880 abc_reader->
object(
object);
883 return reinterpret_cast<CacheReader *
>(abc_reader);
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_main_collection_sync(const struct Main *bmain)
void BKE_layer_collection_resync_allow(void)
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 BKE_layer_collection_resync_forbid(void)
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])
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, size_t maxncpy) ATTR_NONNULL()
#define UNUSED_VARS_NDEBUG(...)
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)
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 always_add_cache_reader, 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)
static ISampleSelector sample_selector_for_time(chrono_t time)
void ABC_CacheReader_incref(CacheReader *reader)
CacheReader * CacheReader_open_alembic_object(CacheArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
void ABC_get_transform(CacheReader *reader, float r_mat_world[4][4], double time, float scale)
void ABC_free_handle(CacheArchiveHandle *handle)
BLI_INLINE CacheArchiveHandle * handle_from_archive(ArchiveReader *archive)
static bool gather_objects_paths(const IObject &object, ListBase *object_paths)
BLI_INLINE ArchiveReader * archive_from_handle(CacheArchiveHandle *handle)
bool ABC_mesh_topology_changed(CacheReader *reader, Object *ob, const Mesh *existing_mesh, const double time, const char **err_str)
CacheArchiveHandle * ABC_create_handle(struct Main *bmain, const char *filename, const CacheFileLayer *layers, ListBase *object_paths)
static AbcObjectReader * get_abc_reader(CacheReader *reader, Object *ob, const char **err_str)
Mesh * ABC_read_mesh(CacheReader *reader, Object *ob, Mesh *existing_mesh, const ABCReadParams *params, const char **err_str)
void ABC_CacheReader_free(CacheReader *reader)
static void import_endjob(void *user_data)
static void find_iobject(const IObject &object, IObject &ret, const std::string &path)
static std::pair< bool, AbcObjectReader * > visit_object(const IObject &object, AbcObjectReader::ptr_vector &readers, ImportSettings &settings, AbcObjectReader::ptr_vector &r_assign_as_parent)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
int getParent(int link_num) const
AbcObjectReader * parent_reader
void read_matrix(float r_mat[4][4], chrono_t time, float scale, bool &is_constant)
const Alembic::Abc::IObject & iobject() const
virtual bool valid() const =0
virtual bool topology_changed(const Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel)
void setupObjectTransform(chrono_t time)
bool inherits_xform() const
const std::string & name() const
virtual void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)=0
virtual struct Mesh * read_mesh(struct Mesh *mesh, const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char *velocity_name, float velocity_scale, const char **err_str)
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()
static ArchiveReader * get(struct Main *bmain, const std::vector< const char * > &filenames)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_callocN)(size_t len, const char *str)
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)
static void report_job_duration(const ExportJobData *data)
Clock::time_point TimePoint
void print_duration(Nanoseconds duration)
std::chrono::nanoseconds Nanoseconds
struct CacheFileLayer * next
blender::timeit::TimePoint start_time
std::vector< AbcObjectReader * > readers
struct Collection * collection
bool always_add_cache_reader
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_report(eReportType type, const char *message)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
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)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, int flag, int job_type)