From ea54cbe1b42efb3107285c89685f555c06997062 Mon Sep 17 00:00:00 2001 From: Michael Kowalski Date: Tue, 3 Aug 2021 11:55:53 +0200 Subject: USD: add USD importer This is an initial implementation of a USD importer. This work is comprised of Tangent Animation's open source USD importer, combined with features @makowalski had implemented. The design is very similar to the approach taken in the Alembic importer. The core functionality resides in a collection of "reader" classes, each of which is responsible for converting an instance of a USD prim to the corresponding Blender Object representation. The flow of control for the conversion can be followed in the `import_startjob()` and `import_endjob()` functions in `usd_capi.cc`. The `USDStageReader` class is responsible for traversing the USD stage and instantiating the appropriate readers. Reviewed By: sybren, HooglyBoogly Differential Revision: https://developer.blender.org/D10700 --- source/blender/editors/io/io_ops.c | 1 + source/blender/editors/io/io_usd.c | 279 +++++++++++++++++++++++++++++++++++++ source/blender/editors/io/io_usd.h | 2 + 3 files changed, 282 insertions(+) (limited to 'source/blender/editors/io') diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c index 9fa34a1c55d..b2788ee49a2 100644 --- a/source/blender/editors/io/io_ops.c +++ b/source/blender/editors/io/io_ops.c @@ -52,6 +52,7 @@ void ED_operatortypes_io(void) WM_operatortype_append(WM_OT_alembic_export); #endif #ifdef WITH_USD + WM_operatortype_append(WM_OT_usd_import); WM_operatortype_append(WM_OT_usd_export); #endif diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index 0eadb38abb5..d0007d9e5be 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -22,23 +22,30 @@ */ #ifdef WITH_USD +# include "DNA_modifier_types.h" # include "DNA_space_types.h" +# include # include "BKE_context.h" # include "BKE_main.h" # include "BKE_report.h" +# include "BLI_blenlib.h" # include "BLI_path_util.h" # include "BLI_string.h" # include "BLI_utildefines.h" # include "BLT_translation.h" +# include "ED_object.h" + # include "MEM_guardedalloc.h" # include "RNA_access.h" # include "RNA_define.h" +# include "RNA_enum_types.h" + # include "UI_interface.h" # include "UI_resources.h" @@ -50,6 +57,8 @@ # include "io_usd.h" # include "usd.h" +# include "stdio.h" + const EnumPropertyItem rna_enum_usd_export_evaluation_mode_items[] = { {DAG_EVAL_RENDER, "RENDER", @@ -242,4 +251,274 @@ void WM_OT_usd_export(struct wmOperatorType *ot) "are different settings for viewport and rendering"); } +/* ====== USD Import ====== */ + +static int wm_usd_import_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + eUSDOperatorOptions *options = MEM_callocN(sizeof(eUSDOperatorOptions), "eUSDOperatorOptions"); + options->as_background_job = true; + op->customdata = options; + + return WM_operator_filesel(C, op, event); +} + +static int wm_usd_import_exec(bContext *C, wmOperator *op) +{ + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + BKE_report(op->reports, RPT_ERROR, "No filename given"); + return OPERATOR_CANCELLED; + } + + char filename[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filename); + + eUSDOperatorOptions *options = (eUSDOperatorOptions *)op->customdata; + const bool as_background_job = (options != NULL && options->as_background_job); + MEM_SAFE_FREE(op->customdata); + + const float scale = RNA_float_get(op->ptr, "scale"); + + const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range"); + + const bool read_mesh_uvs = RNA_boolean_get(op->ptr, "read_mesh_uvs"); + const bool read_mesh_colors = RNA_boolean_get(op->ptr, "read_mesh_colors"); + + char mesh_read_flag = MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY; + if (read_mesh_uvs) { + mesh_read_flag |= MOD_MESHSEQ_READ_UV; + } + if (read_mesh_colors) { + mesh_read_flag |= MOD_MESHSEQ_READ_COLOR; + } + + const bool import_cameras = RNA_boolean_get(op->ptr, "import_cameras"); + const bool import_curves = RNA_boolean_get(op->ptr, "import_curves"); + const bool import_lights = RNA_boolean_get(op->ptr, "import_lights"); + const bool import_materials = RNA_boolean_get(op->ptr, "import_materials"); + const bool import_meshes = RNA_boolean_get(op->ptr, "import_meshes"); + const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes"); + + const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv"); + + const bool import_instance_proxies = RNA_boolean_get(op->ptr, "import_instance_proxies"); + + const bool import_visible_only = RNA_boolean_get(op->ptr, "import_visible_only"); + + const bool create_collection = RNA_boolean_get(op->ptr, "create_collection"); + + char *prim_path_mask = malloc(1024); + RNA_string_get(op->ptr, "prim_path_mask", prim_path_mask); + + const bool import_guide = RNA_boolean_get(op->ptr, "import_guide"); + const bool import_proxy = RNA_boolean_get(op->ptr, "import_proxy"); + const bool import_render = RNA_boolean_get(op->ptr, "import_render"); + + const bool import_usd_preview = RNA_boolean_get(op->ptr, "import_usd_preview"); + const bool set_material_blend = RNA_boolean_get(op->ptr, "set_material_blend"); + + const float light_intensity_scale = RNA_float_get(op->ptr, "light_intensity_scale"); + + /* TODO(makowalski): Add support for sequences. */ + const bool is_sequence = false; + int offset = 0; + int sequence_len = 1; + + /* Switch out of edit mode to avoid being stuck in it (T54326). */ + Object *obedit = CTX_data_edit_object(C); + if (obedit) { + ED_object_mode_set(C, OB_MODE_EDIT); + } + + const bool validate_meshes = false; + const bool use_instancing = false; + + struct USDImportParams params = {.scale = scale, + .is_sequence = is_sequence, + .set_frame_range = set_frame_range, + .sequence_len = sequence_len, + .offset = offset, + .validate_meshes = validate_meshes, + .mesh_read_flag = mesh_read_flag, + .import_cameras = import_cameras, + .import_curves = import_curves, + .import_lights = import_lights, + .import_materials = import_materials, + .import_meshes = import_meshes, + .import_volumes = import_volumes, + .prim_path_mask = prim_path_mask, + .import_subdiv = import_subdiv, + .import_instance_proxies = import_instance_proxies, + .create_collection = create_collection, + .import_guide = import_guide, + .import_proxy = import_proxy, + .import_render = import_render, + .import_visible_only = import_visible_only, + .use_instancing = use_instancing, + .import_usd_preview = import_usd_preview, + .set_material_blend = set_material_blend, + .light_intensity_scale = light_intensity_scale}; + + const bool ok = USD_import(C, filename, ¶ms, as_background_job); + + return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + struct PointerRNA *ptr = op->ptr; + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + uiLayout *box = uiLayoutBox(layout); + uiLayout *col = uiLayoutColumnWithHeading(box, true, IFACE_("Data Types")); + uiItemR(col, ptr, "import_cameras", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_curves", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_lights", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_meshes", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE); + uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE); + uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE); + + box = uiLayoutBox(layout); + col = uiLayoutColumnWithHeading(box, true, IFACE_("Mesh Data")); + uiItemR(col, ptr, "read_mesh_uvs", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "read_mesh_colors", 0, NULL, ICON_NONE); + col = uiLayoutColumnWithHeading(box, true, IFACE_("Include")); + uiItemR(col, ptr, "import_subdiv", 0, IFACE_("Subdivision"), ICON_NONE); + uiItemR(col, ptr, "import_instance_proxies", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_visible_only", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_guide", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_proxy", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_render", 0, NULL, ICON_NONE); + + col = uiLayoutColumnWithHeading(box, true, IFACE_("Options")); + uiItemR(col, ptr, "set_frame_range", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "relative_path", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "create_collection", 0, NULL, ICON_NONE); + uiItemR(box, ptr, "light_intensity_scale", 0, NULL, ICON_NONE); + + box = uiLayoutBox(layout); + col = uiLayoutColumnWithHeading(box, true, IFACE_("Experimental")); + uiItemR(col, ptr, "import_usd_preview", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(col, RNA_boolean_get(ptr, "import_materials")); + uiLayout *row = uiLayoutRow(col, true); + uiItemR(row, ptr, "set_material_blend", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, RNA_boolean_get(ptr, "import_usd_preview")); +} + +void WM_OT_usd_import(struct wmOperatorType *ot) +{ + ot->name = "Import USD"; + ot->description = "Import USD stage into current scene"; + ot->idname = "WM_OT_usd_import"; + + ot->invoke = wm_usd_import_invoke; + ot->exec = wm_usd_import_exec; + ot->poll = WM_operator_winactive; + ot->ui = wm_usd_import_draw; + + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_USD, + FILE_BLENDER, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); + + RNA_def_float( + ot->srna, + "scale", + 1.0f, + 0.0001f, + 1000.0f, + "Scale", + "Value by which to enlarge or shrink the objects with respect to the world's origin", + 0.0001f, + 1000.0f); + + RNA_def_boolean(ot->srna, + "set_frame_range", + true, + "Set Frame Range", + "Update the scene's start and end frame to match those of the USD archive"); + + RNA_def_boolean(ot->srna, "import_cameras", true, "Cameras", ""); + RNA_def_boolean(ot->srna, "import_curves", true, "Curves", ""); + RNA_def_boolean(ot->srna, "import_lights", true, "Lights", ""); + RNA_def_boolean(ot->srna, "import_materials", true, "Materials", ""); + RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", ""); + RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", ""); + + RNA_def_boolean(ot->srna, + "import_subdiv", + false, + "Import Subdivision Scheme", + "Create subdivision surface modifiers based on the USD " + "SubdivisionScheme attribute"); + + RNA_def_boolean(ot->srna, + "import_instance_proxies", + true, + "Import Instance Proxies", + "Create unique Blender objects for USD instances"); + + RNA_def_boolean(ot->srna, + "import_visible_only", + true, + "Visible Primitives Only", + "Do not import invisible USD primitives. " + "Only applies to primitives with a non-animated visibility attribute. " + "Primitives with animated visibility will always be imported"); + + RNA_def_boolean(ot->srna, + "create_collection", + false, + "Create Collection", + "Add all imported objects to a new collection"); + + RNA_def_boolean(ot->srna, "read_mesh_uvs", true, "UV Coordinates", "Read mesh UV coordinates"); + + RNA_def_boolean(ot->srna, "read_mesh_colors", false, "Vertex Colors", "Read mesh vertex colors"); + + RNA_def_string(ot->srna, + "prim_path_mask", + NULL, + 1024, + "Path Mask", + "Import only the subset of the USD scene rooted at the given primitive"); + + RNA_def_boolean(ot->srna, "import_guide", false, "Guide", "Import guide geometry"); + + RNA_def_boolean(ot->srna, "import_proxy", true, "Proxy", "Import proxy geometry"); + + RNA_def_boolean(ot->srna, "import_render", true, "Render", "Import final render geometry"); + + RNA_def_boolean(ot->srna, + "import_usd_preview", + false, + "Import USD Preview", + "Convert UsdPreviewSurface shaders to Principled BSDF shader networks"); + + RNA_def_boolean(ot->srna, + "set_material_blend", + true, + "Set Material Blend", + "If the Import USD Preview option is enabled, " + "the material blend method will automatically be set based on the " + "shader's opacity and opacityThreshold inputs"); + + RNA_def_float(ot->srna, + "light_intensity_scale", + 1.0f, + 0.0001f, + 10000.0f, + "Light Intensity Scale", + "Scale for the intensity of imported lights", + 0.0001f, + 1000.0f); +} + #endif /* WITH_USD */ diff --git a/source/blender/editors/io/io_usd.h b/source/blender/editors/io/io_usd.h index 671984b6f34..7424cc0df32 100644 --- a/source/blender/editors/io/io_usd.h +++ b/source/blender/editors/io/io_usd.h @@ -26,3 +26,5 @@ struct wmOperatorType; void WM_OT_usd_export(struct wmOperatorType *ot); + +void WM_OT_usd_import(struct wmOperatorType *ot); -- cgit v1.2.3