From eb522af4fec58876ac1b0a73ad9bcdae2d82d33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 6 Mar 2020 16:19:35 +0100 Subject: Cleanup: move Alembic, AVI, Collada, and USD to `source/blender/io` This moves the `alembic`, `avi`, `collada`, and `usd` modules into a common `io` directory. This also cleans up some `#include "../../{somedir}/{somefile}.h"` by adding `../../io/{somedir}` to `CMakeLists.txt` and then just using `#include "{somefile}.h"`. No functional changes. --- source/blender/usd/CMakeLists.txt | 111 ---- .../usd/intern/abstract_hierarchy_iterator.cc | 595 --------------------- .../usd/intern/abstract_hierarchy_iterator.h | 251 --------- source/blender/usd/intern/usd_capi.cc | 233 -------- source/blender/usd/intern/usd_exporter_context.h | 44 -- .../blender/usd/intern/usd_hierarchy_iterator.cc | 150 ------ source/blender/usd/intern/usd_hierarchy_iterator.h | 71 --- source/blender/usd/intern/usd_writer_abstract.cc | 147 ----- source/blender/usd/intern/usd_writer_abstract.h | 77 --- source/blender/usd/intern/usd_writer_camera.cc | 111 ---- source/blender/usd/intern/usd_writer_camera.h | 38 -- source/blender/usd/intern/usd_writer_hair.cc | 90 ---- source/blender/usd/intern/usd_writer_hair.h | 38 -- source/blender/usd/intern/usd_writer_light.cc | 112 ---- source/blender/usd/intern/usd_writer_light.h | 37 -- source/blender/usd/intern/usd_writer_mesh.cc | 489 ----------------- source/blender/usd/intern/usd_writer_mesh.h | 66 --- source/blender/usd/intern/usd_writer_metaball.cc | 81 --- source/blender/usd/intern/usd_writer_metaball.h | 42 -- source/blender/usd/intern/usd_writer_transform.cc | 64 --- source/blender/usd/intern/usd_writer_transform.h | 42 -- source/blender/usd/usd.h | 63 --- 22 files changed, 2952 deletions(-) delete mode 100644 source/blender/usd/CMakeLists.txt delete mode 100644 source/blender/usd/intern/abstract_hierarchy_iterator.cc delete mode 100644 source/blender/usd/intern/abstract_hierarchy_iterator.h delete mode 100644 source/blender/usd/intern/usd_capi.cc delete mode 100644 source/blender/usd/intern/usd_exporter_context.h delete mode 100644 source/blender/usd/intern/usd_hierarchy_iterator.cc delete mode 100644 source/blender/usd/intern/usd_hierarchy_iterator.h delete mode 100644 source/blender/usd/intern/usd_writer_abstract.cc delete mode 100644 source/blender/usd/intern/usd_writer_abstract.h delete mode 100644 source/blender/usd/intern/usd_writer_camera.cc delete mode 100644 source/blender/usd/intern/usd_writer_camera.h delete mode 100644 source/blender/usd/intern/usd_writer_hair.cc delete mode 100644 source/blender/usd/intern/usd_writer_hair.h delete mode 100644 source/blender/usd/intern/usd_writer_light.cc delete mode 100644 source/blender/usd/intern/usd_writer_light.h delete mode 100644 source/blender/usd/intern/usd_writer_mesh.cc delete mode 100644 source/blender/usd/intern/usd_writer_mesh.h delete mode 100644 source/blender/usd/intern/usd_writer_metaball.cc delete mode 100644 source/blender/usd/intern/usd_writer_metaball.h delete mode 100644 source/blender/usd/intern/usd_writer_transform.cc delete mode 100644 source/blender/usd/intern/usd_writer_transform.h delete mode 100644 source/blender/usd/usd.h (limited to 'source/blender/usd') diff --git a/source/blender/usd/CMakeLists.txt b/source/blender/usd/CMakeLists.txt deleted file mode 100644 index d85b3cfe4e5..00000000000 --- a/source/blender/usd/CMakeLists.txt +++ /dev/null @@ -1,111 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2019, Blender Foundation -# All rights reserved. -# ***** END GPL LICENSE BLOCK ***** - -# This suppresses the warning "This file includes at least one deprecated or antiquated -# header which may be removed without further notice at a future date", which is caused -# by the USD library including on Linux. This has been reported at: -# https://github.com/PixarAnimationStudios/USD/issues/1057. -if(UNIX AND NOT APPLE) - add_definitions(-D_GLIBCXX_PERMIT_BACKWARD_HASH) -endif() -if(WIN32) - add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) -endif() -add_definitions(-DPXR_STATIC) - -set(INC - . - ../blenkernel - ../blenlib - ../blenloader - ../bmesh - ../depsgraph - ../editors/include - ../makesdna - ../makesrna - ../windowmanager - ../../../intern/guardedalloc - ../../../intern/utfconv -) - -set(INC_SYS - ${USD_INCLUDE_DIRS} - ${BOOST_INCLUDE_DIR} - ${TBB_INCLUDE_DIR} -) - -set(SRC - intern/abstract_hierarchy_iterator.cc - intern/usd_capi.cc - intern/usd_hierarchy_iterator.cc - intern/usd_writer_abstract.cc - intern/usd_writer_camera.cc - intern/usd_writer_hair.cc - intern/usd_writer_light.cc - intern/usd_writer_mesh.cc - intern/usd_writer_metaball.cc - intern/usd_writer_transform.cc - - usd.h - intern/abstract_hierarchy_iterator.h - intern/usd_exporter_context.h - intern/usd_hierarchy_iterator.h - intern/usd_writer_abstract.h - intern/usd_writer_camera.h - intern/usd_writer_hair.h - intern/usd_writer_light.h - intern/usd_writer_mesh.h - intern/usd_writer_metaball.h - intern/usd_writer_transform.h -) - -set(LIB - bf_blenkernel - bf_blenlib -) - -list(APPEND LIB - ${BOOST_LIBRARIES} -) - -list(APPEND LIB -) - -blender_add_lib(bf_usd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") - -if(WIN32) - set_property(TARGET bf_usd APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /WHOLEARCHIVE:${USD_DEBUG_LIB}") - set_property(TARGET bf_usd APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /WHOLEARCHIVE:${USD_RELEASE_LIB}") - set_property(TARGET bf_usd APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO " /WHOLEARCHIVE:${USD_RELEASE_LIB}") - set_property(TARGET bf_usd APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL " /WHOLEARCHIVE:${USD_RELEASE_LIB}") -endif() - -# Source: https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives -if(WIN32) - target_link_libraries(bf_usd INTERFACE ${USD_LIBRARIES}) -elseif(CMAKE_COMPILER_IS_GNUCXX) - target_link_libraries(bf_usd INTERFACE "-Wl,--whole-archive ${USD_LIBRARIES} -Wl,--no-whole-archive ${TBB_LIBRARIES}") -elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - target_link_libraries(bf_usd INTERFACE -Wl,-force_load ${USD_LIBRARIES}) -else() - message(FATAL_ERROR "Unknown how to link USD with your compiler ${CMAKE_CXX_COMPILER_ID}") -endif() - -target_link_libraries(bf_usd INTERFACE ${TBB_LIBRARIES}) diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/usd/intern/abstract_hierarchy_iterator.cc deleted file mode 100644 index a8ed2c5f2a5..00000000000 --- a/source/blender/usd/intern/abstract_hierarchy_iterator.cc +++ /dev/null @@ -1,595 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "abstract_hierarchy_iterator.h" - -#include -#include -#include -#include - -extern "C" { -#include "BKE_anim.h" -#include "BKE_particle.h" - -#include "BLI_assert.h" -#include "BLI_listbase.h" -#include "BLI_math_matrix.h" - -#include "DNA_ID.h" -#include "DNA_layer_types.h" -#include "DNA_object_types.h" -#include "DNA_particle_types.h" - -#include "DEG_depsgraph_query.h" -} - -namespace USD { - -const HierarchyContext *HierarchyContext::root() -{ - return nullptr; -} - -bool HierarchyContext::operator<(const HierarchyContext &other) const -{ - if (object != other.object) { - return object < other.object; - } - if (duplicator != NULL && duplicator == other.duplicator) { - // Only resort to string comparisons when both objects are created by the same duplicator. - return export_name < other.export_name; - } - - return export_parent < other.export_parent; -} - -bool HierarchyContext::is_instance() const -{ - return !original_export_path.empty(); -} -void HierarchyContext::mark_as_instance_of(const std::string &reference_export_path) -{ - original_export_path = reference_export_path; -} -void HierarchyContext::mark_as_not_instanced() -{ - original_export_path.clear(); -} - -AbstractHierarchyWriter::~AbstractHierarchyWriter() -{ -} - -AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph) - : depsgraph_(depsgraph), writers_() -{ -} - -AbstractHierarchyIterator::~AbstractHierarchyIterator() -{ -} - -void AbstractHierarchyIterator::iterate_and_write() -{ - export_graph_construct(); - connect_loose_objects(); - export_graph_prune(); - determine_export_paths(HierarchyContext::root()); - determine_duplication_references(HierarchyContext::root(), ""); - make_writers(HierarchyContext::root()); - export_graph_clear(); -} - -void AbstractHierarchyIterator::release_writers() -{ - for (WriterMap::value_type it : writers_) { - delete_object_writer(it.second); - } - writers_.clear(); -} - -std::string AbstractHierarchyIterator::make_valid_name(const std::string &name) const -{ - return name; -} - -std::string AbstractHierarchyIterator::get_id_name(const ID *id) const -{ - if (id == nullptr) { - return ""; - } - - return make_valid_name(std::string(id->name + 2)); -} - -std::string AbstractHierarchyIterator::get_object_data_path(const HierarchyContext *context) const -{ - BLI_assert(!context->export_path.empty()); - BLI_assert(context->object->data); - - return path_concatenate(context->export_path, get_object_data_name(context->object)); -} - -void AbstractHierarchyIterator::debug_print_export_graph(const ExportGraph &graph) const -{ - size_t total_graph_size = 0; - for (const ExportGraph::value_type &map_iter : graph) { - const DupliAndDuplicator &parent_info = map_iter.first; - Object *const export_parent = parent_info.first; - Object *const duplicator = parent_info.second; - - if (duplicator != nullptr) { - printf(" DU %s (as dupped by %s):\n", - export_parent == nullptr ? "-null-" : (export_parent->id.name + 2), - duplicator->id.name + 2); - } - else { - printf(" OB %s:\n", export_parent == nullptr ? "-null-" : (export_parent->id.name + 2)); - } - - total_graph_size += map_iter.second.size(); - for (HierarchyContext *child_ctx : map_iter.second) { - if (child_ctx->duplicator == nullptr) { - printf(" - %s%s%s\n", - child_ctx->object->id.name + 2, - child_ctx->weak_export ? " (weak)" : "", - child_ctx->original_export_path.size() ? - (std::string("ref ") + child_ctx->original_export_path).c_str() : - ""); - } - else { - printf(" - %s (dup by %s%s) %s\n", - child_ctx->object->id.name + 2, - child_ctx->duplicator->id.name + 2, - child_ctx->weak_export ? ", weak" : "", - child_ctx->original_export_path.size() ? - (std::string("ref ") + child_ctx->original_export_path).c_str() : - ""); - } - } - } - printf(" (Total graph size: %lu objects\n", total_graph_size); -} - -void AbstractHierarchyIterator::export_graph_construct() -{ - Scene *scene = DEG_get_evaluated_scene(depsgraph_); - - DEG_OBJECT_ITER_BEGIN (depsgraph_, - object, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { - // Non-instanced objects always have their object-parent as export-parent. - const bool weak_export = mark_as_weak_export(object); - visit_object(object, object->parent, weak_export); - - if (weak_export) { - // If a duplicator shouldn't be exported, its duplilist also shouldn't be. - continue; - } - - // Export the duplicated objects instanced by this object. - ListBase *lb = object_duplilist(depsgraph_, scene, object); - if (lb) { - // Construct the set of duplicated objects, so that later we can determine whether a parent - // is also duplicated itself. - std::set dupli_set; - LISTBASE_FOREACH (DupliObject *, dupli_object, lb) { - if (!should_visit_dupli_object(dupli_object)) { - continue; - } - dupli_set.insert(dupli_object->ob); - } - - LISTBASE_FOREACH (DupliObject *, dupli_object, lb) { - if (!should_visit_dupli_object(dupli_object)) { - continue; - } - - visit_dupli_object(dupli_object, object, dupli_set); - } - } - - free_object_duplilist(lb); - } - DEG_OBJECT_ITER_END; -} - -void AbstractHierarchyIterator::connect_loose_objects() -{ - // Find those objects whose parent is not part of the export graph; these - // objects would be skipped when traversing the graph as a hierarchy. - // These objects will have to be re-attached to some parent object in order to - // fit into the hierarchy. - ExportGraph loose_objects_graph = export_graph_; - for (const ExportGraph::value_type &map_iter : export_graph_) { - for (const HierarchyContext *child : map_iter.second) { - // An object that is marked as a child of another object is not considered 'loose'. - loose_objects_graph.erase(std::make_pair(child->object, child->duplicator)); - } - } - // The root of the hierarchy is always found, so it's never considered 'loose'. - loose_objects_graph.erase(std::make_pair(nullptr, nullptr)); - - // Iterate over the loose objects and connect them to their export parent. - for (const ExportGraph::value_type &map_iter : loose_objects_graph) { - const DupliAndDuplicator &export_info = map_iter.first; - Object *object = export_info.first; - Object *export_parent = object->parent; - - while (true) { - // Loose objects will all be real objects, as duplicated objects always have - // their duplicator or other exported duplicated object as ancestor. - ExportGraph::iterator found_parent_iter = export_graph_.find( - std::make_pair(export_parent, nullptr)); - - visit_object(object, export_parent, true); - if (found_parent_iter != export_graph_.end()) { - break; - } - // 'export_parent' will never be nullptr here, as the export graph contains the - // tuple as root and thus will cause a break. - BLI_assert(export_parent != nullptr); - - object = export_parent; - export_parent = export_parent->parent; - } - } -} - -static bool remove_weak_subtrees(const HierarchyContext *context, - AbstractHierarchyIterator::ExportGraph &clean_graph, - const AbstractHierarchyIterator::ExportGraph &input_graph) -{ - bool all_is_weak = context != nullptr && context->weak_export; - Object *object = context != nullptr ? context->object : nullptr; - Object *duplicator = context != nullptr ? context->duplicator : nullptr; - - const AbstractHierarchyIterator::DupliAndDuplicator map_key = std::make_pair(object, duplicator); - AbstractHierarchyIterator::ExportGraph::const_iterator child_iterator; - - child_iterator = input_graph.find(map_key); - if (child_iterator != input_graph.end()) { - for (HierarchyContext *child_context : child_iterator->second) { - bool child_tree_is_weak = remove_weak_subtrees(child_context, clean_graph, input_graph); - all_is_weak &= child_tree_is_weak; - - if (child_tree_is_weak) { - // This subtree is all weak, so we can remove it from the current object's children. - clean_graph[map_key].erase(child_context); - delete child_context; - } - } - } - - if (all_is_weak) { - // This node and all its children are weak, so it can be removed from the export graph. - clean_graph.erase(map_key); - } - - return all_is_weak; -} - -void AbstractHierarchyIterator::export_graph_prune() -{ - // Take a copy of the map so that we can modify while recursing. - ExportGraph unpruned_export_graph = export_graph_; - remove_weak_subtrees(HierarchyContext::root(), export_graph_, unpruned_export_graph); -} - -void AbstractHierarchyIterator::export_graph_clear() -{ - for (ExportGraph::iterator::value_type &it : export_graph_) { - for (HierarchyContext *context : it.second) { - delete context; - } - } - export_graph_.clear(); -} - -void AbstractHierarchyIterator::visit_object(Object *object, - Object *export_parent, - bool weak_export) -{ - HierarchyContext *context = new HierarchyContext(); - context->object = object; - context->export_name = get_object_name(object); - context->export_parent = export_parent; - context->duplicator = nullptr; - context->weak_export = weak_export; - context->animation_check_include_parent = false; - context->export_path = ""; - context->original_export_path = ""; - copy_m4_m4(context->matrix_world, object->obmat); - - export_graph_[std::make_pair(export_parent, nullptr)].insert(context); -} - -void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object, - Object *duplicator, - const std::set &dupli_set) -{ - ExportGraph::key_type graph_index; - bool animation_check_include_parent = false; - - HierarchyContext *context = new HierarchyContext(); - context->object = dupli_object->ob; - context->duplicator = duplicator; - context->weak_export = false; - context->export_path = ""; - context->original_export_path = ""; - - /* If the dupli-object's parent is also instanced by this object, use that as the - * export parent. Otherwise use the dupli-parent as export parent. */ - Object *parent = dupli_object->ob->parent; - if (parent != nullptr && dupli_set.find(parent) != dupli_set.end()) { - // The parent object is part of the duplicated collection. - context->export_parent = parent; - graph_index = std::make_pair(parent, duplicator); - } - else { - /* The parent object is NOT part of the duplicated collection. This means that the world - * transform of this dupliobject can be influenced by objects that are not part of its - * export graph. */ - animation_check_include_parent = true; - context->export_parent = duplicator; - graph_index = std::make_pair(duplicator, nullptr); - } - - context->animation_check_include_parent = animation_check_include_parent; - copy_m4_m4(context->matrix_world, dupli_object->mat); - - // Construct export name for the dupli-instance. - std::stringstream suffix_stream; - suffix_stream << std::hex; - for (int i = 0; i < MAX_DUPLI_RECUR && dupli_object->persistent_id[i] != INT_MAX; i++) { - suffix_stream << "-" << dupli_object->persistent_id[i]; - } - context->export_name = make_valid_name(get_object_name(context->object) + suffix_stream.str()); - - export_graph_[graph_index].insert(context); -} - -AbstractHierarchyIterator::ExportChildren &AbstractHierarchyIterator::graph_children( - const HierarchyContext *context) -{ - if (context == nullptr) { - return export_graph_[std::make_pair(nullptr, nullptr)]; - } - - return export_graph_[std::make_pair(context->object, context->duplicator)]; -} - -void AbstractHierarchyIterator::determine_export_paths(const HierarchyContext *parent_context) -{ - const std::string &parent_export_path = parent_context ? parent_context->export_path : ""; - - for (HierarchyContext *context : graph_children(parent_context)) { - context->export_path = path_concatenate(parent_export_path, context->export_name); - - if (context->duplicator == nullptr) { - /* This is an original (i.e. non-instanced) object, so we should keep track of where it was - * exported to, just in case it gets instanced somewhere. */ - ID *source_ob = &context->object->id; - duplisource_export_path_[source_ob] = context->export_path; - - if (context->object->data != nullptr) { - ID *object_data = static_cast(context->object->data); - ID *source_data = object_data; - duplisource_export_path_[source_data] = get_object_data_path(context); - } - } - - determine_export_paths(context); - } -} - -void AbstractHierarchyIterator::determine_duplication_references( - const HierarchyContext *parent_context, std::string indent) -{ - ExportChildren children = graph_children(parent_context); - - for (HierarchyContext *context : children) { - if (context->duplicator != nullptr) { - ID *source_id = &context->object->id; - const ExportPathMap::const_iterator &it = duplisource_export_path_.find(source_id); - - if (it == duplisource_export_path_.end()) { - // The original was not found, so mark this instance as "the original". - context->mark_as_not_instanced(); - duplisource_export_path_[source_id] = context->export_path; - } - else { - context->mark_as_instance_of(it->second); - } - - if (context->object->data) { - ID *source_data_id = (ID *)context->object->data; - const ExportPathMap::const_iterator &it = duplisource_export_path_.find(source_data_id); - - if (it == duplisource_export_path_.end()) { - // The original was not found, so mark this instance as "original". - std::string data_path = get_object_data_path(context); - context->mark_as_not_instanced(); - duplisource_export_path_[source_id] = context->export_path; - duplisource_export_path_[source_data_id] = data_path; - } - } - } - - determine_duplication_references(context, indent + " "); - } -} - -void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_context) -{ - AbstractHierarchyWriter *transform_writer = nullptr; - float parent_matrix_inv_world[4][4]; - - if (parent_context) { - invert_m4_m4(parent_matrix_inv_world, parent_context->matrix_world); - } - else { - unit_m4(parent_matrix_inv_world); - } - - for (HierarchyContext *context : graph_children(parent_context)) { - copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world); - - // Get or create the transform writer. - transform_writer = ensure_writer(context, &AbstractHierarchyIterator::create_transform_writer); - if (transform_writer == nullptr) { - // Unable to export, so there is nothing to attach any children to; just abort this entire - // branch of the export hierarchy. - return; - } - - BLI_assert(DEG_is_evaluated_object(context->object)); - /* XXX This can lead to too many XForms being written. For example, a camera writer can refuse - * to write an orthographic camera. By the time that this is known, the XForm has already been - * written. */ - transform_writer->write(*context); - - if (!context->weak_export) { - make_writers_particle_systems(context); - make_writer_object_data(context); - } - - // Recurse into this object's children. - make_writers(context); - } - - // TODO(Sybren): iterate over all unused writers and call unused_during_iteration() or something. -} - -void AbstractHierarchyIterator::make_writer_object_data(const HierarchyContext *context) -{ - if (context->object->data == nullptr) { - return; - } - - HierarchyContext data_context = *context; - data_context.export_path = get_object_data_path(context); - - /* data_context.original_export_path is just a copy from the context. It points to the object, - * but needs to point to the object data. */ - if (data_context.is_instance()) { - ID *object_data = static_cast(context->object->data); - data_context.original_export_path = duplisource_export_path_[object_data]; - - /* If the object is marked as an instance, so should the object data. */ - BLI_assert(data_context.is_instance()); - } - - AbstractHierarchyWriter *data_writer; - data_writer = ensure_writer(&data_context, &AbstractHierarchyIterator::create_data_writer); - if (data_writer == nullptr) { - return; - } - - data_writer->write(data_context); -} - -void AbstractHierarchyIterator::make_writers_particle_systems( - const HierarchyContext *transform_context) -{ - Object *object = transform_context->object; - ParticleSystem *psys = static_cast(object->particlesystem.first); - for (; psys; psys = psys->next) { - if (!psys_check_enabled(object, psys, true)) { - continue; - } - - HierarchyContext hair_context = *transform_context; - hair_context.export_path = path_concatenate(transform_context->export_path, - get_id_name(&psys->part->id)); - hair_context.particle_system = psys; - - AbstractHierarchyWriter *writer = nullptr; - switch (psys->part->type) { - case PART_HAIR: - writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_hair_writer); - break; - case PART_EMITTER: - writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_particle_writer); - break; - } - - if (writer != nullptr) { - writer->write(hair_context); - } - } -} - -std::string AbstractHierarchyIterator::get_object_name(const Object *object) const -{ - return get_id_name(&object->id); -} - -std::string AbstractHierarchyIterator::get_object_data_name(const Object *object) const -{ - ID *object_data = static_cast(object->data); - return get_id_name(object_data); -} - -AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer(const std::string &export_path) -{ - WriterMap::iterator it = writers_.find(export_path); - - if (it == writers_.end()) { - return nullptr; - } - return it->second; -} - -AbstractHierarchyWriter *AbstractHierarchyIterator::ensure_writer( - HierarchyContext *context, AbstractHierarchyIterator::create_writer_func create_func) -{ - AbstractHierarchyWriter *writer = get_writer(context->export_path); - if (writer != nullptr) { - return writer; - } - - writer = (this->*create_func)(context); - if (writer == nullptr) { - return nullptr; - } - - writers_[context->export_path] = writer; - - return writer; -} - -std::string AbstractHierarchyIterator::path_concatenate(const std::string &parent_path, - const std::string &child_path) const -{ - return parent_path + "/" + child_path; -} - -bool AbstractHierarchyIterator::mark_as_weak_export(const Object * /*object*/) const -{ - return false; -} -bool AbstractHierarchyIterator::should_visit_dupli_object(const DupliObject *dupli_object) const -{ - // Removing dupli_object->no_draw hides things like custom bone shapes. - return !dupli_object->no_draw; -} - -} // namespace USD diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.h b/source/blender/usd/intern/abstract_hierarchy_iterator.h deleted file mode 100644 index 8bca2ddd447..00000000000 --- a/source/blender/usd/intern/abstract_hierarchy_iterator.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ - -/* - * This file contains the AbstractHierarchyIterator. It is intended for exporters for file - * formats that concern an entire hierarchy of objects (rather than, for example, an OBJ file that - * contains only a single mesh). Examples are Universal Scene Description (USD) and Alembic. - * AbstractHierarchyIterator is intended to be subclassed to support concrete file formats. - * - * The AbstractHierarchyIterator makes a distinction between the actual object hierarchy and the - * export hierarchy. The former is the parent/child structure in Blender, which can have multiple - * parent-like objects. For example, a duplicated object can have both a duplicator and a parent, - * both determining the final transform. The export hierarchy is the hierarchy as written to the - * file, and every object has only one export-parent. - * - * Currently the AbstractHierarchyIterator does not make any decisions about *what* to export. - * Selections like "selected only" or "no hair systems" are left to concrete subclasses. - */ - -#ifndef __ABSTRACT_HIERARCHY_ITERATOR_H__ -#define __ABSTRACT_HIERARCHY_ITERATOR_H__ - -#include -#include -#include - -struct Base; -struct Depsgraph; -struct DupliObject; -struct ID; -struct Object; -struct ParticleSystem; -struct ViewLayer; - -namespace USD { - -class AbstractHierarchyWriter; - -/* HierarchyContext structs are created by the AbstractHierarchyIterator. Each HierarchyContext - * struct contains everything necessary to export a single object to a file. */ -struct HierarchyContext { - /*********** Determined during hierarchy iteration: ***************/ - Object *object; - Object *export_parent; - Object *duplicator; - float matrix_world[4][4]; - std::string export_name; - - /* When weak_export=true, the object will be exported only as transform, and only if is an - * ancestor of an object with weak_export=false. - * - * In other words: when weak_export=true but this object has no children, or all decendants also - * have weak_export=true, this object (and by recursive reasoning all its decendants) will be - * excluded from the export. - * - * The export hierarchy is kept as close to the the hierarchy in Blender as possible. As such, an - * object that serves as a parent for another object, but which should NOT be exported itself, is - * exported only as transform (i.e. as empty). This happens with objects that are part of a - * holdout collection (which prevents them from being exported) but also parent of an exported - * object. */ - bool weak_export; - - /* When true, this object should check its parents for animation data when determining whether - * it's animated. This is necessary when a parent object in Blender is not part of the export. */ - bool animation_check_include_parent; - - /*********** Determined during writer creation: ***************/ - float parent_matrix_inv_world[4][4]; // Inverse of the parent's world matrix. - std::string export_path; // Hierarchical path, such as "/grandparent/parent/objectname". - ParticleSystem *particle_system; // Only set for particle/hair writers. - - /* Hierarchical path of the object this object is duplicating; only set when this object should - * be stored as a reference to its original. It can happen that the original is not part of the - * exported objects, in which case this string is empty even though 'duplicator' is set. */ - std::string original_export_path; - - bool operator<(const HierarchyContext &other) const; - - /* Return a HierarchyContext representing the root of the export hierarchy. */ - static const HierarchyContext *root(); - - /* For handling instanced collections, instances created by particles, etc. */ - bool is_instance() const; - void mark_as_instance_of(const std::string &reference_export_path); - void mark_as_not_instanced(); -}; - -/* Abstract writer for objects. Create concrete subclasses to write to USD, Alembic, etc. - * - * Instantiated by the AbstractHierarchyIterator on the first frame an object exists. Generally - * that's the first frame to be exported, but can be later, for example when objects are - * instantiated by particles. The AbstractHierarchyWriter::write() function is called on every - * frame the object exists in the dependency graph and should be exported. - */ -class AbstractHierarchyWriter { - public: - virtual ~AbstractHierarchyWriter(); - virtual void write(HierarchyContext &context) = 0; - // TODO(Sybren): add function like absent() that's called when a writer was previously created, - // but wasn't used while exporting the current frame (for example, a particle-instanced mesh of - // which the particle is no longer alive). -}; - -/* AbstractHierarchyIterator iterates over objects in a dependency graph, and constructs export - * writers. These writers are then called to perform the actual writing to a USD or Alembic file. - * - * Dealing with file- and scene-level data (for example, creating a USD scene, setting the frame - * rate, etc.) is not part of the AbstractHierarchyIterator class structure, and should be done - * in separate code. - */ -class AbstractHierarchyIterator { - public: - /* Mapping from export path to writer. */ - typedef std::map WriterMap; - /* Pair of a (potentially duplicated) object and its duplicator (or nullptr). - * This is typically used to store a pair of HierarchyContext::object and - * HierarchyContext::duplicator. */ - typedef std::pair DupliAndDuplicator; - /* All the children of some object, as per the export hierarchy. */ - typedef std::set ExportChildren; - /* Mapping from an object and its duplicator to the object's export-children. */ - typedef std::map ExportGraph; - /* Mapping from ID to its export path. This is used for instancing; given an - * instanced datablock, the export path of the original can be looked up. */ - typedef std::map ExportPathMap; - - protected: - ExportGraph export_graph_; - ExportPathMap duplisource_export_path_; - Depsgraph *depsgraph_; - WriterMap writers_; - - public: - explicit AbstractHierarchyIterator(Depsgraph *depsgraph); - virtual ~AbstractHierarchyIterator(); - - /* Iterate over the depsgraph, create writers, and tell the writers to write. - * Main entry point for the AbstractHierarchyIterator, must be called for every to-be-exported - * frame. */ - void iterate_and_write(); - - /* Release all writers. Call after all frames have been exported. */ - void release_writers(); - - /* Convert the given name to something that is valid for the exported file format. - * This base implementation is a no-op; override in a concrete subclass. */ - virtual std::string make_valid_name(const std::string &name) const; - - /* Return the name of this ID datablock that is valid for the exported file format. Overriding is - * only necessary if make_valid_name(id->name+2) is not suitable for the exported file format. - * NULL-safe: when `id == nullptr` this returns an empty string. */ - virtual std::string get_id_name(const ID *id) const; - - /* Given a HierarchyContext of some Object *, return an export path that is valid for its - * object->data. Overriding is necessary when the exported format does NOT expect the object's - * data to be a child of the object. */ - virtual std::string get_object_data_path(const HierarchyContext *context) const; - - private: - void debug_print_export_graph(const ExportGraph &graph) const; - - void export_graph_construct(); - void connect_loose_objects(); - void export_graph_prune(); - void export_graph_clear(); - - void visit_object(Object *object, Object *export_parent, bool weak_export); - void visit_dupli_object(DupliObject *dupli_object, - Object *duplicator, - const std::set &dupli_set); - - ExportChildren &graph_children(const HierarchyContext *parent_context); - - void determine_export_paths(const HierarchyContext *parent_context); - void determine_duplication_references(const HierarchyContext *parent_context, - std::string indent); - - void make_writers(const HierarchyContext *parent_context); - void make_writer_object_data(const HierarchyContext *context); - void make_writers_particle_systems(const HierarchyContext *context); - - /* Convenience wrappers around get_id_name(). */ - std::string get_object_name(const Object *object) const; - std::string get_object_data_name(const Object *object) const; - - AbstractHierarchyWriter *get_writer(const std::string &export_path); - - typedef AbstractHierarchyWriter *(AbstractHierarchyIterator::*create_writer_func)( - const HierarchyContext *); - /* Ensure that a writer exists; if it doesn't, call create_func(context). The create_func - * function should be one of the create_XXXX_writer(context) functions declared below. */ - AbstractHierarchyWriter *ensure_writer(HierarchyContext *context, - create_writer_func create_func); - - protected: - /* Construct a valid path for the export file format. This class concatenates by using '/' as a - * path separator, which is valid for both Alembic and USD. */ - virtual std::string path_concatenate(const std::string &parent_path, - const std::string &child_path) const; - - /* Return whether this object should be marked as 'weak export' or not. - * - * When this returns false, writers for the transform and data are created, - * and dupli-objects dupli-object generated from this object will be passed to - * should_visit_dupli_object(). - * - * When this returns true, only a transform writer is created and marked as - * 'weak export'. In this case, the transform writer will be removed before - * exporting starts, unless a decendant of this object is to be exported. - * Dupli-object generated from this object will also be skipped. - * - * See HierarchyContext::weak_export. - */ - virtual bool mark_as_weak_export(const Object *object) const; - - virtual bool should_visit_dupli_object(const DupliObject *dupli_object) const; - - /* These functions should create an AbstractHierarchyWriter subclass instance, or return - * nullptr if the object or its data should not be exported. Returning a nullptr for - * data/hair/particle will NOT prevent the transform to be written. - * - * The returned writer is owned by the AbstractHierarchyWriter, and should be freed in - * delete_object_writer(). */ - virtual AbstractHierarchyWriter *create_transform_writer(const HierarchyContext *context) = 0; - virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) = 0; - virtual AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) = 0; - virtual AbstractHierarchyWriter *create_particle_writer(const HierarchyContext *context) = 0; - - /* Called by release_writers() to free what the create_XXX_writer() functions allocated. */ - virtual void delete_object_writer(AbstractHierarchyWriter *writer) = 0; -}; - -} // namespace USD - -#endif /* __ABSTRACT_HIERARCHY_ITERATOR_H__ */ diff --git a/source/blender/usd/intern/usd_capi.cc b/source/blender/usd/intern/usd_capi.cc deleted file mode 100644 index 83e11cd7bf3..00000000000 --- a/source/blender/usd/intern/usd_capi.cc +++ /dev/null @@ -1,233 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ - -#include "usd.h" -#include "usd_hierarchy_iterator.h" - -#include -#include -#include - -#include "MEM_guardedalloc.h" - -extern "C" { -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_query.h" - -#include "DNA_scene_types.h" - -#include "BKE_blender_version.h" -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_scene.h" - -#include "BLI_fileops.h" -#include "BLI_path_util.h" -#include "BLI_string.h" - -#include "WM_api.h" -#include "WM_types.h" -} - -namespace USD { - -struct ExportJobData { - ViewLayer *view_layer; - Main *bmain; - Depsgraph *depsgraph; - wmWindowManager *wm; - - char filename[FILE_MAX]; - USDExportParams params; - - short *stop; - short *do_update; - float *progress; - - bool was_canceled; - bool export_ok; -}; - -static void export_startjob(void *customdata, short *stop, short *do_update, float *progress) -{ - ExportJobData *data = static_cast(customdata); - - data->stop = stop; - data->do_update = do_update; - data->progress = progress; - data->was_canceled = false; - - G.is_rendering = true; - WM_set_locked_interface(data->wm, true); - G.is_break = false; - - // Construct the depsgraph for exporting. - Scene *scene = DEG_get_input_scene(data->depsgraph); - ViewLayer *view_layer = DEG_get_input_view_layer(data->depsgraph); - DEG_graph_build_from_view_layer(data->depsgraph, data->bmain, scene, view_layer); - BKE_scene_graph_update_tagged(data->depsgraph, data->bmain); - - *progress = 0.0f; - *do_update = true; - - // For restoring the current frame after exporting animation is done. - const int orig_frame = CFRA; - - pxr::UsdStageRefPtr usd_stage = pxr::UsdStage::CreateNew(data->filename); - if (!usd_stage) { - /* This happens when the USD JSON files cannot be found. When that happens, - * the USD library doesn't know it has the functionality to write USDA and - * USDC files, and creating a new UsdStage fails. */ - WM_reportf( - RPT_ERROR, "USD Export: unable to find suitable USD plugin to write %s", data->filename); - data->export_ok = false; - return; - } - - usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z)); - usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, - pxr::VtValue(scene->unit.scale_length)); - usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender ") + versionstr); - - // Set up the stage for animated data. - if (data->params.export_animation) { - usd_stage->SetTimeCodesPerSecond(FPS); - usd_stage->SetStartTimeCode(scene->r.sfra); - usd_stage->SetEndTimeCode(scene->r.efra); - } - - USDHierarchyIterator iter(data->depsgraph, usd_stage, data->params); - - if (data->params.export_animation) { - // Writing the animated frames is not 100% of the work, but it's our best guess. - float progress_per_frame = 1.0f / std::max(1, (scene->r.efra - scene->r.sfra + 1)); - - for (float frame = scene->r.sfra; frame <= scene->r.efra; frame++) { - if (G.is_break || (stop != nullptr && *stop)) { - break; - } - - // Update the scene for the next frame to render. - scene->r.cfra = static_cast(frame); - scene->r.subframe = frame - scene->r.cfra; - BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain); - - iter.set_export_frame(frame); - iter.iterate_and_write(); - - *progress += progress_per_frame; - *do_update = true; - } - } - else { - // If we're not animating, a single iteration over all objects is enough. - iter.iterate_and_write(); - } - - iter.release_writers(); - usd_stage->GetRootLayer()->Save(); - - // 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(customdata); - - DEG_graph_free(data->depsgraph); - - if (data->was_canceled && BLI_exists(data->filename)) { - BLI_delete(data->filename, false, false); - } - - G.is_rendering = false; - WM_set_locked_interface(data->wm, false); -} - -} // namespace USD - -bool USD_export(bContext *C, - const char *filepath, - const USDExportParams *params, - bool as_background_job) -{ - ViewLayer *view_layer = CTX_data_view_layer(C); - Scene *scene = CTX_data_scene(C); - - USD::ExportJobData *job = static_cast( - MEM_mallocN(sizeof(USD::ExportJobData), "ExportJobData")); - - job->bmain = CTX_data_main(C); - job->wm = CTX_wm_manager(C); - job->export_ok = false; - BLI_strncpy(job->filename, filepath, sizeof(job->filename)); - - job->depsgraph = DEG_graph_new(job->bmain, scene, view_layer, params->evaluation_mode); - job->params = *params; - - bool export_ok = false; - if (as_background_job) { - wmJob *wm_job = WM_jobs_get( - job->wm, CTX_wm_window(C), scene, "USD 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, USD::export_startjob, NULL, NULL, USD::export_endjob); - - WM_jobs_start(CTX_wm_manager(C), wm_job); - } - else { - /* Fake a job context, so that we don't need NULL pointer checks while exporting. */ - short stop = 0, do_update = 0; - float progress = 0.f; - - USD::export_startjob(job, &stop, &do_update, &progress); - USD::export_endjob(job); - export_ok = job->export_ok; - - MEM_freeN(job); - } - - return export_ok; -} - -int USD_get_version(void) -{ - /* USD 19.11 defines: - * - * #define PXR_MAJOR_VERSION 0 - * #define PXR_MINOR_VERSION 19 - * #define PXR_PATCH_VERSION 11 - * #define PXR_VERSION 1911 - * - * So the major version is implicit/invisible in the public version number. - */ - return PXR_VERSION; -} diff --git a/source/blender/usd/intern/usd_exporter_context.h b/source/blender/usd/intern/usd_exporter_context.h deleted file mode 100644 index 4ae415b3d34..00000000000 --- a/source/blender/usd/intern/usd_exporter_context.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_EXPORTER_CONTEXT_H__ -#define __USD_EXPORTER_CONTEXT_H__ - -#include "usd.h" - -#include -#include - -struct Depsgraph; -struct Object; - -namespace USD { - -class USDHierarchyIterator; - -struct USDExporterContext { - Depsgraph *depsgraph; - const pxr::UsdStageRefPtr stage; - const pxr::SdfPath usd_path; - const USDHierarchyIterator *hierarchy_iterator; - const USDExportParams &export_params; -}; - -} // namespace USD - -#endif /* __USD_EXPORTER_CONTEXT_H__ */ diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.cc b/source/blender/usd/intern/usd_hierarchy_iterator.cc deleted file mode 100644 index fd888f39adc..00000000000 --- a/source/blender/usd/intern/usd_hierarchy_iterator.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd.h" - -#include "usd_hierarchy_iterator.h" -#include "usd_writer_abstract.h" -#include "usd_writer_camera.h" -#include "usd_writer_hair.h" -#include "usd_writer_light.h" -#include "usd_writer_mesh.h" -#include "usd_writer_metaball.h" -#include "usd_writer_transform.h" - -#include - -#include - -extern "C" { -#include "BKE_anim.h" - -#include "BLI_assert.h" - -#include "DEG_depsgraph_query.h" - -#include "DNA_ID.h" -#include "DNA_layer_types.h" -#include "DNA_object_types.h" -} - -namespace USD { - -USDHierarchyIterator::USDHierarchyIterator(Depsgraph *depsgraph, - pxr::UsdStageRefPtr stage, - const USDExportParams ¶ms) - : AbstractHierarchyIterator(depsgraph), stage_(stage), params_(params) -{ -} - -bool USDHierarchyIterator::mark_as_weak_export(const Object *object) const -{ - if (params_.selected_objects_only && (object->base_flag & BASE_SELECTED) == 0) { - return true; - } - return false; -} - -void USDHierarchyIterator::delete_object_writer(AbstractHierarchyWriter *writer) -{ - delete static_cast(writer); -} - -std::string USDHierarchyIterator::make_valid_name(const std::string &name) const -{ - return pxr::TfMakeValidIdentifier(name); -} - -void USDHierarchyIterator::set_export_frame(float frame_nr) -{ - // The USD stage is already set up to have FPS timecodes per frame. - export_time_ = pxr::UsdTimeCode(frame_nr); -} - -const pxr::UsdTimeCode &USDHierarchyIterator::get_export_time_code() const -{ - return export_time_; -} - -USDExporterContext USDHierarchyIterator::create_usd_export_context(const HierarchyContext *context) -{ - return USDExporterContext{depsgraph_, stage_, pxr::SdfPath(context->export_path), this, params_}; -} - -AbstractHierarchyWriter *USDHierarchyIterator::create_transform_writer( - const HierarchyContext *context) -{ - return new USDTransformWriter(create_usd_export_context(context)); -} - -AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const HierarchyContext *context) -{ - USDExporterContext usd_export_context = create_usd_export_context(context); - USDAbstractWriter *data_writer = nullptr; - - switch (context->object->type) { - case OB_MESH: - data_writer = new USDMeshWriter(usd_export_context); - break; - case OB_CAMERA: - data_writer = new USDCameraWriter(usd_export_context); - break; - case OB_LAMP: - data_writer = new USDLightWriter(usd_export_context); - break; - case OB_MBALL: - data_writer = new USDMetaballWriter(usd_export_context); - break; - - case OB_EMPTY: - case OB_CURVE: - case OB_SURF: - case OB_FONT: - case OB_SPEAKER: - case OB_LIGHTPROBE: - case OB_LATTICE: - case OB_ARMATURE: - case OB_GPENCIL: - return nullptr; - case OB_TYPE_MAX: - BLI_assert(!"OB_TYPE_MAX should not be used"); - return nullptr; - } - - if (!data_writer->is_supported(context)) { - delete data_writer; - return nullptr; - } - - return data_writer; -} - -AbstractHierarchyWriter *USDHierarchyIterator::create_hair_writer(const HierarchyContext *context) -{ - if (!params_.export_hair) { - return nullptr; - } - return new USDHairWriter(create_usd_export_context(context)); -} - -AbstractHierarchyWriter *USDHierarchyIterator::create_particle_writer(const HierarchyContext *) -{ - return nullptr; -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.h b/source/blender/usd/intern/usd_hierarchy_iterator.h deleted file mode 100644 index 90c82c6e551..00000000000 --- a/source/blender/usd/intern/usd_hierarchy_iterator.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_HIERARCHY_ITERATOR_H__ -#define __USD_HIERARCHY_ITERATOR_H__ - -#include "abstract_hierarchy_iterator.h" -#include "usd_exporter_context.h" -#include "usd.h" - -#include - -#include -#include - -struct Depsgraph; -struct ID; -struct Object; - -namespace USD { - -class USDHierarchyIterator : public AbstractHierarchyIterator { - private: - const pxr::UsdStageRefPtr stage_; - pxr::UsdTimeCode export_time_; - const USDExportParams ¶ms_; - - public: - USDHierarchyIterator(Depsgraph *depsgraph, - pxr::UsdStageRefPtr stage, - const USDExportParams ¶ms); - - void set_export_frame(float frame_nr); - const pxr::UsdTimeCode &get_export_time_code() const; - - virtual std::string make_valid_name(const std::string &name) const override; - - protected: - virtual bool mark_as_weak_export(const Object *object) const override; - - virtual AbstractHierarchyWriter *create_transform_writer( - const HierarchyContext *context) override; - virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) override; - virtual AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) override; - virtual AbstractHierarchyWriter *create_particle_writer( - const HierarchyContext *context) override; - - virtual void delete_object_writer(AbstractHierarchyWriter *writer) override; - - private: - USDExporterContext create_usd_export_context(const HierarchyContext *context); -}; - -} // namespace USD - -#endif /* __USD_HIERARCHY_ITERATOR_H__ */ diff --git a/source/blender/usd/intern/usd_writer_abstract.cc b/source/blender/usd/intern/usd_writer_abstract.cc deleted file mode 100644 index 4d0b4364fb5..00000000000 --- a/source/blender/usd/intern/usd_writer_abstract.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_abstract.h" -#include "usd_hierarchy_iterator.h" - -#include - -extern "C" { -#include "BKE_animsys.h" -#include "BKE_key.h" - -#include "DNA_modifier_types.h" -} - -/* TfToken objects are not cheap to construct, so we do it once. */ -namespace usdtokens { -// Materials -static const pxr::TfToken diffuse_color("diffuseColor", pxr::TfToken::Immortal); -static const pxr::TfToken metallic("metallic", pxr::TfToken::Immortal); -static const pxr::TfToken preview_shader("previewShader", pxr::TfToken::Immortal); -static const pxr::TfToken preview_surface("UsdPreviewSurface", pxr::TfToken::Immortal); -static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal); -static const pxr::TfToken surface("surface", pxr::TfToken::Immortal); -} // namespace usdtokens - -namespace USD { - -USDAbstractWriter::USDAbstractWriter(const USDExporterContext &usd_export_context) - : usd_export_context_(usd_export_context), - usd_value_writer_(), - frame_has_been_written_(false), - is_animated_(false) -{ -} - -USDAbstractWriter::~USDAbstractWriter() -{ -} - -bool USDAbstractWriter::is_supported(const HierarchyContext * /*context*/) const -{ - return true; -} - -pxr::UsdTimeCode USDAbstractWriter::get_export_time_code() const -{ - if (is_animated_) { - return usd_export_context_.hierarchy_iterator->get_export_time_code(); - } - // By using the default timecode USD won't even write a single `timeSample` for non-animated - // data. Instead, it writes it as non-timesampled. - static pxr::UsdTimeCode default_timecode = pxr::UsdTimeCode::Default(); - return default_timecode; -} - -void USDAbstractWriter::write(HierarchyContext &context) -{ - if (!frame_has_been_written_) { - is_animated_ = usd_export_context_.export_params.export_animation && - check_is_animated(context); - } - else if (!is_animated_) { - /* A frame has already been written, and without animation one frame is enough. */ - return; - } - - do_write(context); - - frame_has_been_written_ = true; -} - -bool USDAbstractWriter::check_is_animated(const HierarchyContext &context) const -{ - const Object *object = context.object; - - if (BKE_animdata_id_is_animated(static_cast(object->data))) { - return true; - } - if (BKE_key_from_object(object) != nullptr) { - return true; - } - - /* Test modifiers. */ - /* TODO(Sybren): replace this with a check on the depsgraph to properly check for dependency on - * time. */ - ModifierData *md = static_cast(object->modifiers.first); - while (md) { - if (md->type != eModifierType_Subsurf) { - return true; - } - md = md->next; - } - - return false; -} - -const pxr::SdfPath &USDAbstractWriter::usd_path() const -{ - return usd_export_context_.usd_path; -} - -pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(Material *material) -{ - static pxr::SdfPath material_library_path("/_materials"); - pxr::UsdStageRefPtr stage = usd_export_context_.stage; - - // Construct the material. - pxr::TfToken material_name(usd_export_context_.hierarchy_iterator->get_id_name(&material->id)); - pxr::SdfPath usd_path = material_library_path.AppendChild(material_name); - pxr::UsdShadeMaterial usd_material = pxr::UsdShadeMaterial::Get(stage, usd_path); - if (usd_material) { - return usd_material; - } - usd_material = pxr::UsdShadeMaterial::Define(stage, usd_path); - - // Construct the shader. - pxr::SdfPath shader_path = usd_path.AppendChild(usdtokens::preview_shader); - pxr::UsdShadeShader shader = pxr::UsdShadeShader::Define(stage, shader_path); - shader.CreateIdAttr(pxr::VtValue(usdtokens::preview_surface)); - shader.CreateInput(usdtokens::diffuse_color, pxr::SdfValueTypeNames->Color3f) - .Set(pxr::GfVec3f(material->r, material->g, material->b)); - shader.CreateInput(usdtokens::roughness, pxr::SdfValueTypeNames->Float).Set(material->roughness); - shader.CreateInput(usdtokens::metallic, pxr::SdfValueTypeNames->Float).Set(material->metallic); - - // Connect the shader and the material together. - usd_material.CreateSurfaceOutput().ConnectToSource(shader, usdtokens::surface); - - return usd_material; -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_abstract.h b/source/blender/usd/intern/usd_writer_abstract.h deleted file mode 100644 index 835d3a42c80..00000000000 --- a/source/blender/usd/intern/usd_writer_abstract.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_ABSTRACT_H__ -#define __USD_WRITER_ABSTRACT_H__ - -#include "usd_exporter_context.h" -#include "abstract_hierarchy_iterator.h" - -#include -#include -#include -#include - -#include - -extern "C" { -#include "DEG_depsgraph_query.h" -#include "DNA_material_types.h" -} - -struct Material; -struct Object; - -namespace USD { - -class USDAbstractWriter : public AbstractHierarchyWriter { - protected: - const USDExporterContext usd_export_context_; - pxr::UsdUtilsSparseValueWriter usd_value_writer_; - - bool frame_has_been_written_; - bool is_animated_; - - public: - USDAbstractWriter(const USDExporterContext &usd_export_context); - virtual ~USDAbstractWriter(); - - virtual void write(HierarchyContext &context) override; - - /* Returns true if the data to be written is actually supported. This would, for example, allow a - * hypothetical camera writer accept a perspective camera but reject an orthogonal one. - * - * Returning false from a transform writer will prevent the object and all its decendants from - * being exported. Returning false from a data writer (object data, hair, or particles) will - * only prevent that data from being written (and thus cause the object to be exported as an - * Empty). */ - virtual bool is_supported(const HierarchyContext *context) const; - - const pxr::SdfPath &usd_path() const; - - protected: - virtual void do_write(HierarchyContext &context) = 0; - virtual bool check_is_animated(const HierarchyContext &context) const; - pxr::UsdTimeCode get_export_time_code() const; - - pxr::UsdShadeMaterial ensure_usd_material(Material *material); -}; - -} // namespace USD - -#endif /* __USD_WRITER_ABSTRACT_H__ */ diff --git a/source/blender/usd/intern/usd_writer_camera.cc b/source/blender/usd/intern/usd_writer_camera.cc deleted file mode 100644 index 9b85d69559c..00000000000 --- a/source/blender/usd/intern/usd_writer_camera.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_camera.h" -#include "usd_hierarchy_iterator.h" - -#include -#include - -extern "C" { -#include "BKE_camera.h" -#include "BLI_assert.h" - -#include "DNA_camera_types.h" -#include "DNA_scene_types.h" -} - -namespace USD { - -USDCameraWriter::USDCameraWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) -{ -} - -bool USDCameraWriter::is_supported(const HierarchyContext *context) const -{ - Camera *camera = static_cast(context->object->data); - return camera->type == CAM_PERSP; -} - -static void camera_sensor_size_for_render(const Camera *camera, - const struct RenderData *rd, - float *r_sensor_x, - float *r_sensor_y) -{ - /* Compute the final image size in pixels. */ - float sizex = rd->xsch * rd->xasp; - float sizey = rd->ysch * rd->yasp; - - int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, sizex, sizey); - - switch (sensor_fit) { - case CAMERA_SENSOR_FIT_HOR: - *r_sensor_x = camera->sensor_x; - *r_sensor_y = camera->sensor_x * sizey / sizex; - break; - case CAMERA_SENSOR_FIT_VERT: - *r_sensor_x = camera->sensor_y * sizex / sizey; - *r_sensor_y = camera->sensor_y; - break; - case CAMERA_SENSOR_FIT_AUTO: - BLI_assert(!"Camera fit should be either horizontal or vertical"); - break; - } -} - -void USDCameraWriter::do_write(HierarchyContext &context) -{ - pxr::UsdTimeCode timecode = get_export_time_code(); - pxr::UsdGeomCamera usd_camera = pxr::UsdGeomCamera::Define(usd_export_context_.stage, - usd_export_context_.usd_path); - - Camera *camera = static_cast(context.object->data); - Scene *scene = DEG_get_evaluated_scene(usd_export_context_.depsgraph); - - usd_camera.CreateProjectionAttr().Set(pxr::UsdGeomTokens->perspective); - - /* USD stores the focal length in "millimeters or tenths of world units", because at some point - * they decided world units might be centimeters. Quite confusing, as the USD Viewer shows the - * correct FoV when we write millimeters and not "tenths of world units". - */ - usd_camera.CreateFocalLengthAttr().Set(camera->lens, timecode); - - float aperture_x, aperture_y; - camera_sensor_size_for_render(camera, &scene->r, &aperture_x, &aperture_y); - - float film_aspect = aperture_x / aperture_y; - usd_camera.CreateHorizontalApertureAttr().Set(aperture_x, timecode); - usd_camera.CreateVerticalApertureAttr().Set(aperture_y, timecode); - usd_camera.CreateHorizontalApertureOffsetAttr().Set(aperture_x * camera->shiftx, timecode); - usd_camera.CreateVerticalApertureOffsetAttr().Set(aperture_y * camera->shifty * film_aspect, - timecode); - - usd_camera.CreateClippingRangeAttr().Set( - pxr::VtValue(pxr::GfVec2f(camera->clip_start, camera->clip_end)), timecode); - - // Write DoF-related attributes. - if (camera->dof.flag & CAM_DOF_ENABLED) { - usd_camera.CreateFStopAttr().Set(camera->dof.aperture_fstop, timecode); - - float focus_distance = scene->unit.scale_length * - BKE_camera_object_dof_distance(context.object); - usd_camera.CreateFocusDistanceAttr().Set(focus_distance, timecode); - } -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_camera.h b/source/blender/usd/intern/usd_writer_camera.h deleted file mode 100644 index 971264ef11e..00000000000 --- a/source/blender/usd/intern/usd_writer_camera.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_CAMERA_H__ -#define __USD_WRITER_CAMERA_H__ - -#include "usd_writer_abstract.h" - -namespace USD { - -/* Writer for writing camera data to UsdGeomCamera. */ -class USDCameraWriter : public USDAbstractWriter { - public: - USDCameraWriter(const USDExporterContext &ctx); - - protected: - virtual bool is_supported(const HierarchyContext *context) const override; - virtual void do_write(HierarchyContext &context) override; -}; - -} // namespace USD - -#endif /* __USD_WRITER_CAMERA_H__ */ diff --git a/source/blender/usd/intern/usd_writer_hair.cc b/source/blender/usd/intern/usd_writer_hair.cc deleted file mode 100644 index 9251425c0b8..00000000000 --- a/source/blender/usd/intern/usd_writer_hair.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_hair.h" -#include "usd_hierarchy_iterator.h" - -#include -#include - -extern "C" { -#include "BKE_particle.h" - -#include "DNA_particle_types.h" -} - -namespace USD { - -USDHairWriter::USDHairWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) -{ -} - -void USDHairWriter::do_write(HierarchyContext &context) -{ - ParticleSystem *psys = context.particle_system; - ParticleCacheKey **cache = psys->pathcache; - if (cache == nullptr) { - return; - } - - pxr::UsdTimeCode timecode = get_export_time_code(); - pxr::UsdGeomBasisCurves curves = pxr::UsdGeomBasisCurves::Define(usd_export_context_.stage, - usd_export_context_.usd_path); - - // TODO(Sybren): deal with (psys->part->flag & PART_HAIR_BSPLINE) - curves.CreateBasisAttr(pxr::VtValue(pxr::UsdGeomTokens->bspline)); - curves.CreateTypeAttr(pxr::VtValue(pxr::UsdGeomTokens->cubic)); - - pxr::VtArray points; - pxr::VtIntArray curve_point_counts; - curve_point_counts.reserve(psys->totpart); - - ParticleCacheKey *strand; - for (int strand_index = 0; strand_index < psys->totpart; ++strand_index) { - strand = cache[strand_index]; - - int point_count = strand->segments + 1; - curve_point_counts.push_back(point_count); - - for (int point_index = 0; point_index < point_count; ++point_index, ++strand) { - points.push_back(pxr::GfVec3f(strand->co)); - } - } - - pxr::UsdAttribute attr_points = curves.CreatePointsAttr(pxr::VtValue(), true); - pxr::UsdAttribute attr_vertex_counts = curves.CreateCurveVertexCountsAttr(pxr::VtValue(), true); - if (!attr_points.HasValue()) { - attr_points.Set(points, pxr::UsdTimeCode::Default()); - attr_vertex_counts.Set(curve_point_counts, pxr::UsdTimeCode::Default()); - } - usd_value_writer_.SetAttribute(attr_points, pxr::VtValue(points), timecode); - usd_value_writer_.SetAttribute(attr_vertex_counts, pxr::VtValue(curve_point_counts), timecode); - - if (psys->totpart > 0) { - pxr::VtArray colors; - colors.push_back(pxr::GfVec3f(cache[0]->col)); - curves.CreateDisplayColorAttr(pxr::VtValue(colors)); - } -} - -bool USDHairWriter::check_is_animated(const HierarchyContext &) const -{ - return true; -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_hair.h b/source/blender/usd/intern/usd_writer_hair.h deleted file mode 100644 index 1e882fa1654..00000000000 --- a/source/blender/usd/intern/usd_writer_hair.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_HAIR_H__ -#define __USD_WRITER_HAIR_H__ - -#include "usd_writer_abstract.h" - -namespace USD { - -/* Writer for writing hair particle data as USD curves. */ -class USDHairWriter : public USDAbstractWriter { - public: - USDHairWriter(const USDExporterContext &ctx); - - protected: - virtual void do_write(HierarchyContext &context) override; - virtual bool check_is_animated(const HierarchyContext &context) const override; -}; - -} // namespace USD - -#endif /* __USD_WRITER_HAIR_H__ */ diff --git a/source/blender/usd/intern/usd_writer_light.cc b/source/blender/usd/intern/usd_writer_light.cc deleted file mode 100644 index e13e2c58a79..00000000000 --- a/source/blender/usd/intern/usd_writer_light.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_light.h" -#include "usd_hierarchy_iterator.h" - -#include -#include -#include -#include - -extern "C" { -#include "BLI_assert.h" -#include "BLI_utildefines.h" - -#include "DNA_light_types.h" -#include "DNA_object_types.h" -} - -namespace USD { - -USDLightWriter::USDLightWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) -{ -} - -bool USDLightWriter::is_supported(const HierarchyContext *context) const -{ - Light *light = static_cast(context->object->data); - return ELEM(light->type, LA_AREA, LA_LOCAL, LA_SUN); -} - -void USDLightWriter::do_write(HierarchyContext &context) -{ - pxr::UsdStageRefPtr stage = usd_export_context_.stage; - const pxr::SdfPath &usd_path = usd_export_context_.usd_path; - pxr::UsdTimeCode timecode = get_export_time_code(); - - Light *light = static_cast(context.object->data); - pxr::UsdLuxLight usd_light; - - switch (light->type) { - case LA_AREA: - switch (light->area_shape) { - case LA_AREA_DISK: - case LA_AREA_ELLIPSE: { /* An ellipse light will deteriorate into a disk light. */ - pxr::UsdLuxDiskLight disk_light = pxr::UsdLuxDiskLight::Define(stage, usd_path); - disk_light.CreateRadiusAttr().Set(light->area_size, timecode); - usd_light = disk_light; - break; - } - case LA_AREA_RECT: { - pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path); - rect_light.CreateWidthAttr().Set(light->area_size, timecode); - rect_light.CreateHeightAttr().Set(light->area_sizey, timecode); - usd_light = rect_light; - break; - } - case LA_AREA_SQUARE: { - pxr::UsdLuxRectLight rect_light = pxr::UsdLuxRectLight::Define(stage, usd_path); - rect_light.CreateWidthAttr().Set(light->area_size, timecode); - rect_light.CreateHeightAttr().Set(light->area_size, timecode); - usd_light = rect_light; - break; - } - } - break; - case LA_LOCAL: { - pxr::UsdLuxSphereLight sphere_light = pxr::UsdLuxSphereLight::Define(stage, usd_path); - sphere_light.CreateRadiusAttr().Set(light->area_size, timecode); - usd_light = sphere_light; - break; - } - case LA_SUN: - usd_light = pxr::UsdLuxDistantLight::Define(stage, usd_path); - break; - default: - BLI_assert(!"is_supported() returned true for unsupported light type"); - } - - /* Scale factor to get to somewhat-similar illumination. Since the USDViewer had similar - * over-exposure as Blender Internal with the same values, this code applies the reverse of the - * versioning code in light_emission_unify(). */ - float usd_intensity; - if (light->type == LA_SUN) { - /* Untested, as the Hydra GL viewport of USDViewer doesn't support distant lights. */ - usd_intensity = light->energy; - } - else { - usd_intensity = light->energy / 100.f; - } - usd_light.CreateIntensityAttr().Set(usd_intensity, timecode); - - usd_light.CreateColorAttr().Set(pxr::GfVec3f(light->r, light->g, light->b), timecode); - usd_light.CreateSpecularAttr().Set(light->spec_fac, timecode); -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_light.h b/source/blender/usd/intern/usd_writer_light.h deleted file mode 100644 index 349c034b6bc..00000000000 --- a/source/blender/usd/intern/usd_writer_light.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_LIGHT_H__ -#define __USD_WRITER_LIGHT_H__ - -#include "usd_writer_abstract.h" - -namespace USD { - -class USDLightWriter : public USDAbstractWriter { - public: - USDLightWriter(const USDExporterContext &ctx); - - protected: - virtual bool is_supported(const HierarchyContext *context) const override; - virtual void do_write(HierarchyContext &context) override; -}; - -} // namespace USD - -#endif /* __USD_WRITER_LIGHT_H__ */ diff --git a/source/blender/usd/intern/usd_writer_mesh.cc b/source/blender/usd/intern/usd_writer_mesh.cc deleted file mode 100644 index 74005afaf31..00000000000 --- a/source/blender/usd/intern/usd_writer_mesh.cc +++ /dev/null @@ -1,489 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_mesh.h" -#include "usd_hierarchy_iterator.h" - -#include -#include -#include - -extern "C" { -#include "BLI_assert.h" -#include "BLI_math_vector.h" - -#include "BKE_anim.h" -#include "BKE_customdata.h" -#include "BKE_lib_id.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_modifier.h" -#include "BKE_object.h" - -#include "DEG_depsgraph.h" - -#include "DNA_layer_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_fluidsim_types.h" -#include "DNA_particle_types.h" -} - -namespace USD { - -USDGenericMeshWriter::USDGenericMeshWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) -{ -} - -bool USDGenericMeshWriter::is_supported(const HierarchyContext *context) const -{ - Object *object = context->object; - bool is_dupli = context->duplicator != nullptr; - int base_flag; - - if (is_dupli) { - /* Construct the object's base flags from its dupliparent, just like is done in - * deg_objects_dupli_iterator_next(). Without this, the visibility check below will fail. Doing - * this here, instead of a more suitable location in AbstractHierarchyIterator, prevents - * copying the Object for every dupli. */ - base_flag = object->base_flag; - object->base_flag = context->duplicator->base_flag | BASE_FROM_DUPLI; - } - - int visibility = BKE_object_visibility(object, - usd_export_context_.export_params.evaluation_mode); - - if (is_dupli) { - object->base_flag = base_flag; - } - - return (visibility & OB_VISIBLE_SELF) != 0; -} - -void USDGenericMeshWriter::do_write(HierarchyContext &context) -{ - Object *object_eval = context.object; - bool needsfree = false; - Mesh *mesh = get_export_mesh(object_eval, needsfree); - - if (mesh == NULL) { - return; - } - - try { - write_mesh(context, mesh); - - if (needsfree) { - free_export_mesh(mesh); - } - } - catch (...) { - if (needsfree) { - free_export_mesh(mesh); - } - throw; - } -} - -void USDGenericMeshWriter::free_export_mesh(Mesh *mesh) -{ - BKE_id_free(NULL, mesh); -} - -struct USDMeshData { - pxr::VtArray points; - pxr::VtIntArray face_vertex_counts; - pxr::VtIntArray face_indices; - std::map face_groups; - - /* The length of this array specifies the number of creases on the surface. Each element gives - * the number of (must be adjacent) vertices in each crease, whose indices are linearly laid out - * in the 'creaseIndices' attribute. Since each crease must be at least one edge long, each - * element of this array should be greater than one. */ - pxr::VtIntArray crease_lengths; - /* The indices of all vertices forming creased edges. The size of this array must be equal to the - * sum of all elements of the 'creaseLengths' attribute. */ - pxr::VtIntArray crease_vertex_indices; - /* The per-crease or per-edge sharpness for all creases (Usd.Mesh.SHARPNESS_INFINITE for a - * perfectly sharp crease). Since 'creaseLengths' encodes the number of vertices in each crease, - * the number of elements in this array will be either len(creaseLengths) or the sum over all X - * of (creaseLengths[X] - 1). Note that while the RI spec allows each crease to have either a - * single sharpness or a value per-edge, USD will encode either a single sharpness per crease on - * a mesh, or sharpnesses for all edges making up the creases on a mesh. */ - pxr::VtFloatArray crease_sharpnesses; -}; - -void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) -{ - pxr::UsdTimeCode timecode = get_export_time_code(); - - const CustomData *ldata = &mesh->ldata; - for (int layer_idx = 0; layer_idx < ldata->totlayer; layer_idx++) { - const CustomDataLayer *layer = &ldata->layers[layer_idx]; - if (layer->type != CD_MLOOPUV) { - continue; - } - - /* UV coordinates are stored in a Primvar on the Mesh, and can be referenced from materials. - * The primvar name is the same as the UV Map name. This is to allow the standard name "st" - * for texture coordinates by naming the UV Map as such, without having to guess which UV Map - * is the "standard" one. */ - pxr::TfToken primvar_name(pxr::TfMakeValidIdentifier(layer->name)); - pxr::UsdGeomPrimvar uv_coords_primvar = usd_mesh.CreatePrimvar( - primvar_name, pxr::SdfValueTypeNames->TexCoord2fArray, pxr::UsdGeomTokens->faceVarying); - - MLoopUV *mloopuv = static_cast(layer->data); - pxr::VtArray uv_coords; - for (int loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) { - uv_coords.push_back(pxr::GfVec2f(mloopuv[loop_idx].uv)); - } - - if (!uv_coords_primvar.HasValue()) { - uv_coords_primvar.Set(uv_coords, pxr::UsdTimeCode::Default()); - } - const pxr::UsdAttribute &uv_coords_attr = uv_coords_primvar.GetAttr(); - usd_value_writer_.SetAttribute(uv_coords_attr, pxr::VtValue(uv_coords), timecode); - } -} - -void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) -{ - pxr::UsdTimeCode timecode = get_export_time_code(); - pxr::UsdTimeCode defaultTime = pxr::UsdTimeCode::Default(); - pxr::UsdStageRefPtr stage = usd_export_context_.stage; - const pxr::SdfPath &usd_path = usd_export_context_.usd_path; - - pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage, usd_path); - USDMeshData usd_mesh_data; - get_geometry_data(mesh, usd_mesh_data); - - if (usd_export_context_.export_params.use_instancing && context.is_instance()) { - // This object data is instanced, just reference the original instead of writing a copy. - if (context.export_path == context.original_export_path) { - printf("USD ref error: export path is reference path: %s\n", context.export_path.c_str()); - BLI_assert(!"USD reference error"); - return; - } - pxr::SdfPath ref_path(context.original_export_path); - if (!usd_mesh.GetPrim().GetReferences().AddInternalReference(ref_path)) { - /* See this URL for a description fo why referencing may fail" - * https://graphics.pixar.com/usd/docs/api/class_usd_references.html#Usd_Failing_References - */ - printf("USD Export warning: unable to add reference from %s to %s, not instancing object\n", - context.export_path.c_str(), - context.original_export_path.c_str()); - return; - } - /* The material path will be of the form , which is outside the - subtree pointed to by ref_path. As a result, the referenced data is not allowed to point out - of its own subtree. It does work when we override the material with exactly the same path, - though.*/ - if (usd_export_context_.export_params.export_materials) { - assign_materials(context, usd_mesh, usd_mesh_data.face_groups); - } - return; - } - - pxr::UsdAttribute attr_points = usd_mesh.CreatePointsAttr(pxr::VtValue(), true); - pxr::UsdAttribute attr_face_vertex_counts = usd_mesh.CreateFaceVertexCountsAttr(pxr::VtValue(), - true); - pxr::UsdAttribute attr_face_vertex_indices = usd_mesh.CreateFaceVertexIndicesAttr(pxr::VtValue(), - true); - - if (!attr_points.HasValue()) { - // Provide the initial value as default. This makes USD write the value as constant if they - // don't change over time. - attr_points.Set(usd_mesh_data.points, defaultTime); - attr_face_vertex_counts.Set(usd_mesh_data.face_vertex_counts, defaultTime); - attr_face_vertex_indices.Set(usd_mesh_data.face_indices, defaultTime); - } - - usd_value_writer_.SetAttribute(attr_points, pxr::VtValue(usd_mesh_data.points), timecode); - usd_value_writer_.SetAttribute( - attr_face_vertex_counts, pxr::VtValue(usd_mesh_data.face_vertex_counts), timecode); - usd_value_writer_.SetAttribute( - attr_face_vertex_indices, pxr::VtValue(usd_mesh_data.face_indices), timecode); - - if (!usd_mesh_data.crease_lengths.empty()) { - pxr::UsdAttribute attr_crease_lengths = usd_mesh.CreateCreaseLengthsAttr(pxr::VtValue(), true); - pxr::UsdAttribute attr_crease_indices = usd_mesh.CreateCreaseIndicesAttr(pxr::VtValue(), true); - pxr::UsdAttribute attr_crease_sharpness = usd_mesh.CreateCreaseSharpnessesAttr(pxr::VtValue(), - true); - - if (!attr_crease_lengths.HasValue()) { - attr_crease_lengths.Set(usd_mesh_data.crease_lengths, defaultTime); - attr_crease_indices.Set(usd_mesh_data.crease_vertex_indices, defaultTime); - attr_crease_sharpness.Set(usd_mesh_data.crease_sharpnesses, defaultTime); - } - - usd_value_writer_.SetAttribute( - attr_crease_lengths, pxr::VtValue(usd_mesh_data.crease_lengths), timecode); - usd_value_writer_.SetAttribute( - attr_crease_indices, pxr::VtValue(usd_mesh_data.crease_vertex_indices), timecode); - usd_value_writer_.SetAttribute( - attr_crease_sharpness, pxr::VtValue(usd_mesh_data.crease_sharpnesses), timecode); - } - - if (usd_export_context_.export_params.export_uvmaps) { - write_uv_maps(mesh, usd_mesh); - } - if (usd_export_context_.export_params.export_normals) { - write_normals(mesh, usd_mesh); - } - write_surface_velocity(context.object, mesh, usd_mesh); - - // TODO(Sybren): figure out what happens when the face groups change. - if (frame_has_been_written_) { - return; - } - - usd_mesh.CreateSubdivisionSchemeAttr().Set(pxr::UsdGeomTokens->none); - - if (usd_export_context_.export_params.export_materials) { - assign_materials(context, usd_mesh, usd_mesh_data.face_groups); - } -} - -static void get_vertices(const Mesh *mesh, USDMeshData &usd_mesh_data) -{ - usd_mesh_data.points.reserve(mesh->totvert); - - const MVert *verts = mesh->mvert; - for (int i = 0; i < mesh->totvert; ++i) { - usd_mesh_data.points.push_back(pxr::GfVec3f(verts[i].co)); - } -} - -static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data) -{ - /* Only construct face groups (a.k.a. geometry subsets) when we need them for material - * assignments. */ - bool construct_face_groups = mesh->totcol > 1; - - usd_mesh_data.face_vertex_counts.reserve(mesh->totpoly); - usd_mesh_data.face_indices.reserve(mesh->totloop); - - MLoop *mloop = mesh->mloop; - MPoly *mpoly = mesh->mpoly; - for (int i = 0; i < mesh->totpoly; ++i, ++mpoly) { - MLoop *loop = mloop + mpoly->loopstart; - usd_mesh_data.face_vertex_counts.push_back(mpoly->totloop); - for (int j = 0; j < mpoly->totloop; ++j, ++loop) { - usd_mesh_data.face_indices.push_back(loop->v); - } - - if (construct_face_groups) { - usd_mesh_data.face_groups[mpoly->mat_nr].push_back(i); - } - } -} - -static void get_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) -{ - const float factor = 1.0f / 255.0f; - - MEdge *edge = mesh->medge; - float sharpness; - for (int edge_idx = 0, totedge = mesh->totedge; edge_idx < totedge; ++edge_idx, ++edge) { - if (edge->crease == 0) { - continue; - } - - if (edge->crease == 255) { - sharpness = pxr::UsdGeomMesh::SHARPNESS_INFINITE; - } - else { - sharpness = static_cast(edge->crease) * factor; - } - - usd_mesh_data.crease_vertex_indices.push_back(edge->v1); - usd_mesh_data.crease_vertex_indices.push_back(edge->v2); - usd_mesh_data.crease_lengths.push_back(2); - usd_mesh_data.crease_sharpnesses.push_back(sharpness); - } -} - -void USDGenericMeshWriter::get_geometry_data(const Mesh *mesh, USDMeshData &usd_mesh_data) -{ - get_vertices(mesh, usd_mesh_data); - get_loops_polys(mesh, usd_mesh_data); - get_creases(mesh, usd_mesh_data); -} - -void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, - pxr::UsdGeomMesh usd_mesh, - const MaterialFaceGroups &usd_face_groups) -{ - if (context.object->totcol == 0) { - return; - } - - /* Binding a material to a geometry subset isn't supported by the Hydra GL viewport yet, - * which is why we always bind the first material to the entire mesh. See - * https://github.com/PixarAnimationStudios/USD/issues/542 for more info. */ - bool mesh_material_bound = false; - for (short mat_num = 0; mat_num < context.object->totcol; mat_num++) { - Material *material = BKE_object_material_get(context.object, mat_num + 1); - if (material == nullptr) { - continue; - } - - pxr::UsdShadeMaterial usd_material = ensure_usd_material(material); - usd_material.Bind(usd_mesh.GetPrim()); - - /* USD seems to support neither per-material nor per-face-group double-sidedness, so we just - * use the flag from the first non-empty material slot. */ - usd_mesh.CreateDoubleSidedAttr( - pxr::VtValue((material->blend_flag & MA_BL_CULL_BACKFACE) == 0)); - - mesh_material_bound = true; - break; - } - - if (!mesh_material_bound) { - /* Blender defaults to double-sided, but USD to single-sided. */ - usd_mesh.CreateDoubleSidedAttr(pxr::VtValue(true)); - } - - if (!mesh_material_bound || usd_face_groups.size() < 2) { - /* Either all material slots were empty or there is only one material in use. As geometry - * subsets are only written when actually used to assign a material, and the mesh already has - * the material assigned, there is no need to continue. */ - return; - } - - // Define a geometry subset per material. - for (const MaterialFaceGroups::value_type &face_group : usd_face_groups) { - short material_number = face_group.first; - const pxr::VtIntArray &face_indices = face_group.second; - - Material *material = BKE_object_material_get(context.object, material_number + 1); - if (material == nullptr) { - continue; - } - - pxr::UsdShadeMaterial usd_material = ensure_usd_material(material); - pxr::TfToken material_name = usd_material.GetPath().GetNameToken(); - - pxr::UsdShadeMaterialBindingAPI api = pxr::UsdShadeMaterialBindingAPI(usd_mesh); - pxr::UsdGeomSubset usd_face_subset = api.CreateMaterialBindSubset(material_name, face_indices); - usd_material.Bind(usd_face_subset.GetPrim()); - } -} - -void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) -{ - pxr::UsdTimeCode timecode = get_export_time_code(); - const float(*lnors)[3] = static_cast(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); - - pxr::VtVec3fArray loop_normals; - loop_normals.reserve(mesh->totloop); - - if (lnors != nullptr) { - /* Export custom loop normals. */ - for (int loop_idx = 0, totloop = mesh->totloop; loop_idx < totloop; ++loop_idx) { - loop_normals.push_back(pxr::GfVec3f(lnors[loop_idx])); - } - } - else { - /* Compute the loop normals based on the 'smooth' flag. */ - float normal[3]; - MPoly *mpoly = mesh->mpoly; - const MVert *mvert = mesh->mvert; - for (int poly_idx = 0, totpoly = mesh->totpoly; poly_idx < totpoly; ++poly_idx, ++mpoly) { - MLoop *mloop = mesh->mloop + mpoly->loopstart; - - if ((mpoly->flag & ME_SMOOTH) == 0) { - /* Flat shaded, use common normal for all verts. */ - BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, normal); - pxr::GfVec3f pxr_normal(normal); - for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx) { - loop_normals.push_back(pxr_normal); - } - } - else { - /* Smooth shaded, use individual vert normals. */ - for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx, ++mloop) { - normal_short_to_float_v3(normal, mvert[mloop->v].no); - loop_normals.push_back(pxr::GfVec3f(normal)); - } - } - } - } - - pxr::UsdAttribute attr_normals = usd_mesh.CreateNormalsAttr(pxr::VtValue(), true); - if (!attr_normals.HasValue()) { - attr_normals.Set(loop_normals, pxr::UsdTimeCode::Default()); - } - usd_value_writer_.SetAttribute(attr_normals, pxr::VtValue(loop_normals), timecode); - usd_mesh.SetNormalsInterpolation(pxr::UsdGeomTokens->faceVarying); -} - -void USDGenericMeshWriter::write_surface_velocity(Object *object, - const Mesh *mesh, - pxr::UsdGeomMesh usd_mesh) -{ - /* Only velocities from the fluid simulation are exported. This is the most important case, - * though, as the baked mesh changes topology all the time, and thus computing the velocities - * at import time in a post-processing step is hard. */ - ModifierData *md = modifiers_findByType(object, eModifierType_Fluidsim); - if (md == nullptr) { - return; - } - - /* Check that the fluid sim modifier is enabled and has useful data. */ - const bool use_render = (DEG_get_mode(usd_export_context_.depsgraph) == DAG_EVAL_RENDER); - const ModifierMode required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; - const Scene *scene = DEG_get_evaluated_scene(usd_export_context_.depsgraph); - if (!modifier_isEnabled(scene, md, required_mode)) { - return; - } - FluidsimModifierData *fsmd = reinterpret_cast(md); - if (!fsmd->fss || fsmd->fss->type != OB_FLUIDSIM_DOMAIN) { - return; - } - FluidsimSettings *fss = fsmd->fss; - if (!fss->meshVelocities) { - return; - } - - /* Export per-vertex velocity vectors. */ - pxr::VtVec3fArray usd_velocities; - usd_velocities.reserve(mesh->totvert); - - FluidVertexVelocity *mesh_velocities = fss->meshVelocities; - for (int vertex_idx = 0, totvert = mesh->totvert; vertex_idx < totvert; - ++vertex_idx, ++mesh_velocities) { - usd_velocities.push_back(pxr::GfVec3f(mesh_velocities->vel)); - } - - pxr::UsdTimeCode timecode = get_export_time_code(); - usd_mesh.CreateVelocitiesAttr().Set(usd_velocities, timecode); -} - -USDMeshWriter::USDMeshWriter(const USDExporterContext &ctx) : USDGenericMeshWriter(ctx) -{ -} - -Mesh *USDMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/) -{ - return BKE_object_get_evaluated_mesh(object_eval); -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_mesh.h b/source/blender/usd/intern/usd_writer_mesh.h deleted file mode 100644 index 4175e2b7e27..00000000000 --- a/source/blender/usd/intern/usd_writer_mesh.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_MESH_H__ -#define __USD_WRITER_MESH_H__ - -#include "usd_writer_abstract.h" - -#include - -namespace USD { - -struct USDMeshData; - -/* Writer for USD geometry. Does not assume the object is a mesh object. */ -class USDGenericMeshWriter : public USDAbstractWriter { - public: - USDGenericMeshWriter(const USDExporterContext &ctx); - - protected: - virtual bool is_supported(const HierarchyContext *context) const override; - virtual void do_write(HierarchyContext &context) override; - - virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) = 0; - virtual void free_export_mesh(Mesh *mesh); - - private: - /* Mapping from material slot number to array of face indices with that material. */ - typedef std::map MaterialFaceGroups; - - void write_mesh(HierarchyContext &context, Mesh *mesh); - void get_geometry_data(const Mesh *mesh, struct USDMeshData &usd_mesh_data); - void assign_materials(const HierarchyContext &context, - pxr::UsdGeomMesh usd_mesh, - const MaterialFaceGroups &usd_face_groups); - void write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); - void write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); - void write_surface_velocity(Object *object, const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); -}; - -class USDMeshWriter : public USDGenericMeshWriter { - public: - USDMeshWriter(const USDExporterContext &ctx); - - protected: - virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override; -}; - -} // namespace USD - -#endif /* __USD_WRITER_MESH_H__ */ diff --git a/source/blender/usd/intern/usd_writer_metaball.cc b/source/blender/usd/intern/usd_writer_metaball.cc deleted file mode 100644 index 25b216d20f3..00000000000 --- a/source/blender/usd/intern/usd_writer_metaball.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2020 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_metaball.h" -#include "usd_hierarchy_iterator.h" - -#include -#include -#include - -extern "C" { -#include "BLI_assert.h" - -#include "BKE_displist.h" -#include "BKE_lib_id.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_object.h" - -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" -} - -namespace USD { - -USDMetaballWriter::USDMetaballWriter(const USDExporterContext &ctx) : USDGenericMeshWriter(ctx) -{ -} - -bool USDMetaballWriter::is_supported(const HierarchyContext *context) const -{ - Scene *scene = DEG_get_input_scene(usd_export_context_.depsgraph); - return is_basis_ball(scene, context->object) && USDGenericMeshWriter::is_supported(context); -} - -bool USDMetaballWriter::check_is_animated(const HierarchyContext & /*context*/) const -{ - /* We assume that metaballs are always animated, as the current object may - * not be animated but another ball in the same group may be. */ - return true; -} - -Mesh *USDMetaballWriter::get_export_mesh(Object *object_eval, bool &r_needsfree) -{ - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object_eval); - if (mesh_eval != nullptr) { - /* Mesh_eval only exists when generative modifiers are in use. */ - r_needsfree = false; - return mesh_eval; - } - r_needsfree = true; - return BKE_mesh_new_from_object(usd_export_context_.depsgraph, object_eval, false); -} - -void USDMetaballWriter::free_export_mesh(Mesh *mesh) -{ - BKE_id_free(nullptr, mesh); -} - -bool USDMetaballWriter::is_basis_ball(Scene *scene, Object *ob) const -{ - Object *basis_ob = BKE_mball_basis_find(scene, ob); - return ob == basis_ob; -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_metaball.h b/source/blender/usd/intern/usd_writer_metaball.h deleted file mode 100644 index 1a86daae2ae..00000000000 --- a/source/blender/usd/intern/usd_writer_metaball.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2020 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_METABALL_H__ -#define __USD_WRITER_METABALL_H__ - -#include "usd_writer_mesh.h" - -namespace USD { - -class USDMetaballWriter : public USDGenericMeshWriter { - public: - USDMetaballWriter(const USDExporterContext &ctx); - - protected: - virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override; - virtual void free_export_mesh(Mesh *mesh) override; - virtual bool is_supported(const HierarchyContext *context) const override; - virtual bool check_is_animated(const HierarchyContext &context) const override; - - private: - bool is_basis_ball(Scene *scene, Object *ob) const; -}; - -} // namespace USD - -#endif /* __USD_WRITER_METABALL_H__ */ diff --git a/source/blender/usd/intern/usd_writer_transform.cc b/source/blender/usd/intern/usd_writer_transform.cc deleted file mode 100644 index 321b516221a..00000000000 --- a/source/blender/usd/intern/usd_writer_transform.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#include "usd_writer_transform.h" -#include "usd_hierarchy_iterator.h" - -#include -#include - -extern "C" { -#include "BKE_object.h" - -#include "BLI_math_matrix.h" - -#include "DNA_layer_types.h" -} - -namespace USD { - -USDTransformWriter::USDTransformWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx) -{ -} - -void USDTransformWriter::do_write(HierarchyContext &context) -{ - float parent_relative_matrix[4][4]; // The object matrix relative to the parent. - mul_m4_m4m4(parent_relative_matrix, context.parent_matrix_inv_world, context.matrix_world); - - // Write the transform relative to the parent. - pxr::UsdGeomXform xform = pxr::UsdGeomXform::Define(usd_export_context_.stage, - usd_export_context_.usd_path); - if (!xformOp_) { - xformOp_ = xform.AddTransformOp(); - } - xformOp_.Set(pxr::GfMatrix4d(parent_relative_matrix), get_export_time_code()); -} - -bool USDTransformWriter::check_is_animated(const HierarchyContext &context) const -{ - if (context.duplicator != NULL) { - /* This object is being duplicated, so could be emitted by a particle system and thus - * influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the - * depsgraph whether this object instance has a time source. */ - return true; - } - return BKE_object_moves_in_time(context.object, context.animation_check_include_parent); -} - -} // namespace USD diff --git a/source/blender/usd/intern/usd_writer_transform.h b/source/blender/usd/intern/usd_writer_transform.h deleted file mode 100644 index 52c4a657f33..00000000000 --- a/source/blender/usd/intern/usd_writer_transform.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ -#ifndef __USD_WRITER_TRANSFORM_H__ -#define __USD_WRITER_TRANSFORM_H__ - -#include "usd_writer_abstract.h" - -#include - -namespace USD { - -class USDTransformWriter : public USDAbstractWriter { - private: - pxr::UsdGeomXformOp xformOp_; - - public: - USDTransformWriter(const USDExporterContext &ctx); - - protected: - void do_write(HierarchyContext &context) override; - bool check_is_animated(const HierarchyContext &context) const override; -}; - -} // namespace USD - -#endif /* __USD_WRITER_TRANSFORM_H__ */ diff --git a/source/blender/usd/usd.h b/source/blender/usd/usd.h deleted file mode 100644 index 8a5575d53cf..00000000000 --- a/source/blender/usd/usd.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2019 Blender Foundation. - * All rights reserved. - */ - -#ifndef __USD_H__ -#define __USD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "DEG_depsgraph.h" - -struct Scene; -struct bContext; - -struct USDExportParams { - bool export_animation; - bool export_hair; - bool export_uvmaps; - bool export_normals; - bool export_materials; - bool selected_objects_only; - bool use_instancing; - enum eEvaluationMode evaluation_mode; -}; - -/* The USD_export takes a as_background_job parameter, and returns a boolean. - * - * When as_background_job=true, returns false immediately after scheduling - * a background job. - * - * When as_background_job=false, performs the export synchronously, and returns - * true when the export was ok, and false if there were any errors. - */ - -bool USD_export(struct bContext *C, - const char *filepath, - const struct USDExportParams *params, - bool as_background_job); - -int USD_get_version(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __USD_H__ */ -- cgit v1.2.3