Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/io/alembic/exporter/abc_export_capi.cc')
-rw-r--r--source/blender/io/alembic/exporter/abc_export_capi.cc229
1 files changed, 105 insertions, 124 deletions
diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc
index c0d04b50acd..fbc5b2d5c02 100644
--- a/source/blender/io/alembic/exporter/abc_export_capi.cc
+++ b/source/blender/io/alembic/exporter/abc_export_capi.cc
@@ -18,18 +18,15 @@
*/
#include "ABC_alembic.h"
-#include "abc_writer_camera.h"
-#include "abc_writer_curves.h"
-#include "abc_writer_hair.h"
-#include "abc_writer_mesh.h"
-#include "abc_writer_nurbs.h"
-#include "abc_writer_points.h"
-#include "abc_writer_transform.h"
+#include "abc_archive.h"
+#include "abc_hierarchy_iterator.h"
+#include "abc_subdiv_disabler.h"
#include "MEM_guardedalloc.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
@@ -47,179 +44,163 @@
#include "WM_api.h"
#include "WM_types.h"
-using namespace blender::io::alembic;
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+#include <algorithm>
struct ExportJobData {
- ViewLayer *view_layer;
Main *bmain;
+ Depsgraph *depsgraph;
wmWindowManager *wm;
- char filename[1024];
- ExportSettings settings;
-
- short *stop;
- short *do_update;
- float *progress;
+ char filename[FILE_MAX];
+ AlembicExportParams params;
bool was_canceled;
bool export_ok;
};
+namespace blender {
+namespace io {
+namespace alembic {
+
+// Construct the depsgraph for exporting.
+static void build_depsgraph(Depsgraph *depsgraph, Main *bmain)
+{
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+}
+
static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
ExportJobData *data = static_cast<ExportJobData *>(customdata);
+ data->was_canceled = false;
- data->stop = stop;
- data->do_update = do_update;
- data->progress = progress;
-
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
G.is_rendering = true;
WM_set_locked_interface(data->wm, true);
G.is_break = false;
- DEG_graph_build_from_view_layer(
- data->settings.depsgraph, data->bmain, data->settings.scene, data->view_layer);
- BKE_scene_graph_update_tagged(data->settings.depsgraph, data->bmain);
+ *progress = 0.0f;
+ *do_update = true;
- try {
- AbcExporter exporter(data->bmain, data->filename, data->settings);
+ build_depsgraph(data->depsgraph, data->bmain);
+ SubdivModifierDisabler subdiv_disabler(data->depsgraph);
+ if (!data->params.apply_subdiv) {
+ subdiv_disabler.disable_modifiers();
+ }
+ BKE_scene_graph_update_tagged(data->depsgraph, data->bmain);
- Scene *scene = data->settings.scene; /* for the CFRA macro */
- const int orig_frame = CFRA;
+ // For restoring the current frame after exporting animation is done.
+ Scene *scene = DEG_get_input_scene(data->depsgraph);
+ const int orig_frame = CFRA;
+ const bool export_animation = (data->params.frame_start != data->params.frame_end);
- data->was_canceled = false;
- exporter(do_update, progress, &data->was_canceled);
+ // Create the Alembic archive.
+ ABCArchive abc_archive(data->bmain, scene, data->params, std::string(data->filename));
- if (CFRA != orig_frame) {
- CFRA = orig_frame;
+ ABCHierarchyIterator iter(data->depsgraph, &abc_archive, data->params);
- BKE_scene_graph_update_for_newframe(data->settings.depsgraph, data->bmain);
- }
+ if (export_animation) {
+ CLOG_INFO(&LOG, 2, "Exporting animation");
+
+ // Writing the animated frames is not 100% of the work, but it's our best guess.
+ const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive.total_frame_count());
+ ABCArchive::Frames::const_iterator frame_it = abc_archive.frames_begin();
+ const ABCArchive::Frames::const_iterator frames_end = abc_archive.frames_end();
+
+ for (; frame_it != frames_end; frame_it++) {
+ double frame = *frame_it;
+
+ if (G.is_break || (stop != nullptr && *stop)) {
+ break;
+ }
+
+ // Update the scene for the next frame to render.
+ scene->r.cfra = static_cast<int>(frame);
+ scene->r.subframe = frame - scene->r.cfra;
+ BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
- data->export_ok = !data->was_canceled;
+ CLOG_INFO(&LOG, 2, "Exporting frame %.2f", frame);
+ ExportSubset export_subset = abc_archive.export_subset_for_frame(frame);
+ iter.set_export_subset(export_subset);
+ iter.iterate_and_write();
+
+ *progress += progress_per_frame;
+ *do_update = true;
+ }
}
- catch (const std::exception &e) {
- ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n';
+ else {
+ // If we're not animating, a single iteration over all objects is enough.
+ iter.iterate_and_write();
}
- catch (...) {
- ABC_LOG(data->settings.logger) << "Abc Export: unknown error...\n";
+
+ iter.release_writers();
+
+ // Finish up by going back to the keyframe that was current before we started.
+ if (CFRA != orig_frame) {
+ CFRA = orig_frame;
+ BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
}
+
+ data->export_ok = !data->was_canceled;
+
+ *progress = 1.0f;
+ *do_update = true;
}
static void export_endjob(void *customdata)
{
ExportJobData *data = static_cast<ExportJobData *>(customdata);
- DEG_graph_free(data->settings.depsgraph);
+ DEG_graph_free(data->depsgraph);
if (data->was_canceled && BLI_exists(data->filename)) {
BLI_delete(data->filename, false, false);
}
- std::string log = data->settings.logger.str();
- if (!log.empty()) {
- std::cerr << log;
- WM_report(RPT_ERROR, "Errors occurred during the export, look in the console to know more...");
- }
-
G.is_rendering = false;
WM_set_locked_interface(data->wm, false);
}
-bool ABC_export(struct Scene *scene,
- struct bContext *C,
+} // namespace alembic
+} // namespace io
+} // namespace blender
+
+bool ABC_export(Scene *scene,
+ bContext *C,
const char *filepath,
- const struct AlembicExportParams *params,
+ const AlembicExportParams *params,
bool as_background_job)
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
ExportJobData *job = static_cast<ExportJobData *>(
MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
- job->view_layer = CTX_data_view_layer(C);
job->bmain = CTX_data_main(C);
job->wm = CTX_wm_manager(C);
job->export_ok = false;
- BLI_strncpy(job->filename, filepath, 1024);
-
- /* Alright, alright, alright....
- *
- * ExportJobData contains an ExportSettings containing a SimpleLogger.
- *
- * Since ExportJobData is a C-style struct dynamically allocated with
- * MEM_mallocN (see above), its constructor is never called, therefore the
- * ExportSettings constructor is not called which implies that the
- * SimpleLogger one is not called either. SimpleLogger in turn does not call
- * the constructor of its data members which ultimately means that its
- * std::ostringstream member has a NULL pointer. To be able to properly use
- * the stream's operator<<, the pointer needs to be set, therefore we have
- * to properly construct everything. And this is done using the placement
- * new operator as here below. It seems hackish, but I'm too lazy to
- * do bigger refactor and maybe there is a better way which does not involve
- * hardcore refactoring. */
- new (&job->settings) ExportSettings();
- job->settings.scene = scene;
- job->settings.depsgraph = DEG_graph_new(job->bmain, scene, job->view_layer, DAG_EVAL_RENDER);
-
- /* TODO(Sybren): for now we only export the active scene layer.
- * Later in the 2.8 development process this may be replaced by using
- * a specific collection for Alembic I/O, which can then be toggled
- * between "real" objects and cached Alembic files. */
- job->settings.view_layer = job->view_layer;
-
- job->settings.frame_start = params->frame_start;
- job->settings.frame_end = params->frame_end;
- job->settings.frame_samples_xform = params->frame_samples_xform;
- job->settings.frame_samples_shape = params->frame_samples_shape;
- job->settings.shutter_open = params->shutter_open;
- job->settings.shutter_close = params->shutter_close;
-
- /* TODO(Sybren): For now this is ignored, until we can get selection
- * detection working through Base pointers (instead of ob->flags). */
- job->settings.selected_only = params->selected_only;
-
- job->settings.export_face_sets = params->face_sets;
- job->settings.export_normals = params->normals;
- job->settings.export_uvs = params->uvs;
- job->settings.export_vcols = params->vcolors;
- job->settings.export_hair = params->export_hair;
- job->settings.export_particles = params->export_particles;
- job->settings.apply_subdiv = params->apply_subdiv;
- job->settings.curves_as_mesh = params->curves_as_mesh;
- job->settings.flatten_hierarchy = params->flatten_hierarchy;
-
- /* TODO(Sybren): visible_layer & renderable only is ignored for now,
- * to be replaced with collections later in the 2.8 dev process
- * (also see note above). */
- job->settings.visible_objects_only = params->visible_objects_only;
- job->settings.renderable_only = params->renderable_only;
-
- job->settings.use_subdiv_schema = params->use_subdiv_schema;
- job->settings.pack_uv = params->packuv;
- job->settings.global_scale = params->global_scale;
- job->settings.triangulate = params->triangulate;
- job->settings.quad_method = params->quad_method;
- job->settings.ngon_method = params->ngon_method;
-
- if (job->settings.frame_start > job->settings.frame_end) {
- std::swap(job->settings.frame_start, job->settings.frame_end);
- }
+ BLI_strncpy(job->filename, filepath, sizeof(job->filename));
+
+ job->depsgraph = DEG_graph_new(
+ job->bmain, scene, view_layer, DAG_EVAL_RENDER /* TODO(Sybren): params->evaluation_mode */);
+ job->params = *params;
bool export_ok = false;
if (as_background_job) {
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- job->settings.scene,
- "Alembic Export",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_ALEMBIC);
+ wmJob *wm_job = WM_jobs_get(
+ job->wm, CTX_wm_window(C), scene, "Alembic Export", WM_JOB_PROGRESS, WM_JOB_TYPE_ALEMBIC);
/* setup job */
WM_jobs_customdata_set(wm_job, job, MEM_freeN);
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
+ WM_jobs_callbacks(wm_job,
+ blender::io::alembic::export_startjob,
+ NULL,
+ NULL,
+ blender::io::alembic::export_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
@@ -228,8 +209,8 @@ bool ABC_export(struct Scene *scene,
short stop = 0, do_update = 0;
float progress = 0.f;
- export_startjob(job, &stop, &do_update, &progress);
- export_endjob(job);
+ blender::io::alembic::export_startjob(job, &stop, &do_update, &progress);
+ blender::io::alembic::export_endjob(job);
export_ok = job->export_ok;
MEM_freeN(job);