[Bf-blender-cvs] [50a30043283] universal-scene-description: USD Import: support reading USD shapes.

Michael Kowalski noreply at git.blender.org
Mon Oct 17 21:12:37 CEST 2022


Commit: 50a300432838d8f731bf567d6914fff5fc140080
Author: Michael Kowalski
Date:   Mon Oct 17 15:11:42 2022 -0400
Branches: universal-scene-description
https://developer.blender.org/rB50a300432838d8f731bf567d6914fff5fc140080

USD Import: support reading USD shapes.

Added readers for importing USD shapes (capsule, cylinder,
cone, cube and sphere) as meshes.  Implemented by Charles
Wardlaw.

===================================================================

M	source/blender/editors/io/io_usd.c
M	source/blender/io/usd/CMakeLists.txt
M	source/blender/io/usd/intern/usd_capi_import.cc
A	source/blender/io/usd/intern/usd_reader_shape.cc
A	source/blender/io/usd/intern/usd_reader_shape.h
M	source/blender/io/usd/intern/usd_reader_stage.cc
M	source/blender/io/usd/intern/usd_reader_stage.h
M	source/blender/io/usd/usd.h

===================================================================

diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index ca0df20a45e..0998fc77b01 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -1060,6 +1060,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
   const bool import_blendshapes = RNA_boolean_get(op->ptr, "import_blendshapes");
   const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes");
   const bool import_skeletons = RNA_boolean_get(op->ptr, "import_skeletons");
+  const bool import_shapes = RNA_boolean_get(op->ptr, "import_shapes");
 
   const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv");
 
@@ -1144,7 +1145,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
                                    .scale_light_radius = scale_light_radius,
                                    .create_background_shader = create_background_shader,
                                    .mtl_name_collision_mode = mtl_name_collision_mode,
-                                   .attr_import_mode = attr_import_mode};
+                                   .attr_import_mode = attr_import_mode,
+                                   .import_shapes = import_shapes};
 
   const bool ok = USD_import(C, filename, &params, as_background_job);
 
@@ -1169,6 +1171,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
   uiItemR(col, ptr, "import_blendshapes", 0, NULL, ICON_NONE);
   uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE);
   uiItemR(col, ptr, "import_skeletons", 0, NULL, ICON_NONE);
+  uiItemR(col, ptr, "import_shapes", 0, NULL, ICON_NONE);
   uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE);
   uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE);
   uiItemR(box, ptr, "apply_unit_conversion_scale", 0, NULL, ICON_NONE);
@@ -1267,6 +1270,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
   RNA_def_boolean(ot->srna, "import_blendshapes", true, "Blend Shapes", "");
   RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", "");
   RNA_def_boolean(ot->srna, "import_skeletons", true, "Skeletons", "");
+  RNA_def_boolean(ot->srna, "import_shapes", true, "USD Shapes", "");
 
   RNA_def_boolean(ot->srna,
                   "import_subdiv",
diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt
index 4a77bb32544..28cbf158a01 100644
--- a/source/blender/io/usd/CMakeLists.txt
+++ b/source/blender/io/usd/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC
   intern/usd_reader_camera.cc
   intern/usd_reader_curve.cc
   intern/usd_reader_geom.cc
+		intern/usd_reader_shape.cc
   intern/usd_reader_instance.cc
   intern/usd_reader_light.cc
   intern/usd_reader_material.cc
@@ -114,6 +115,7 @@ set(SRC
   intern/usd_reader_camera.h
   intern/usd_reader_curve.h
   intern/usd_reader_geom.h
+		intern/usd_reader_shape.h
   intern/usd_reader_instance.h
   intern/usd_reader_light.h
   intern/usd_reader_material.h
@@ -179,6 +181,7 @@ endif()
 # Source: https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives
 if(WIN32)
   target_link_libraries(bf_usd INTERFACE ${USD_LIBRARIES})
+  target_compile_options(bf_usd PRIVATE /w34101)
 elseif(APPLE)
   target_link_libraries(bf_usd INTERFACE -Wl,-force_load ${USD_LIBRARIES})
 elseif(UNIX)
diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc
index 1d005f92116..791ddc351e8 100644
--- a/source/blender/io/usd/intern/usd_capi_import.cc
+++ b/source/blender/io/usd/intern/usd_capi_import.cc
@@ -339,6 +339,7 @@ static void report_job_duration(const ImportJobData *data)
   std::cout << '\n';
 }
 
+
 static void import_startjob(void *customdata, short *stop, short *do_update, float *progress)
 {
   ImportJobData *data = static_cast<ImportJobData *>(customdata);
diff --git a/source/blender/io/usd/intern/usd_reader_shape.cc b/source/blender/io/usd/intern/usd_reader_shape.cc
new file mode 100644
index 00000000000..92597c290ee
--- /dev/null
+++ b/source/blender/io/usd/intern/usd_reader_shape.cc
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2021 Tangent Animation. All rights reserved. */
+
+#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+
+#include "DNA_cachefile_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h" /* for FILE_MAX */
+#include "DNA_windowmanager_types.h"
+
+#include "WM_api.h"
+
+#include "usd_reader_shape.h"
+
+#include <pxr/usd/usdGeom/capsule.h>
+#include <pxr/usd/usdGeom/cone.h>
+#include <pxr/usd/usdGeom/cube.h>
+#include <pxr/usd/usdGeom/cylinder.h>
+#include <pxr/usd/usdGeom/sphere.h>
+#include <pxr/usdImaging/usdImaging/capsuleAdapter.h>
+#include <pxr/usdImaging/usdImaging/coneAdapter.h>
+#include <pxr/usdImaging/usdImaging/cubeAdapter.h>
+#include <pxr/usdImaging/usdImaging/cylinderAdapter.h>
+#include <pxr/usdImaging/usdImaging/sphereAdapter.h>
+
+namespace blender::io::usd {
+
+USDShapeReader::USDShapeReader(const pxr::UsdPrim &prim,
+                               const USDImportParams &import_params,
+                               const ImportSettings &settings)
+    : USDGeomReader(prim, import_params, settings)
+{
+}
+
+void USDShapeReader::create_object(Main *bmain, double motionSampleTime)
+{
+  Mesh *mesh = BKE_mesh_add(bmain, name_.c_str());
+  object_ = BKE_object_add_only_object(bmain, OB_MESH, name_.c_str());
+  object_->data = mesh;
+}
+
+void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime)
+{
+  Mesh *mesh = (Mesh *)object_->data;
+  Mesh *read_mesh = this->read_mesh(
+      mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
+
+  if (read_mesh != mesh) {
+    /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */
+    /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */
+    uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH);
+    BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true);
+    mesh->flag |= autosmooth;
+
+    if (is_time_varying()) {
+      USDGeomReader::add_cache_modifier();
+    }
+  }
+
+  USDXformReader::read_object_data(bmain, motionSampleTime);
+}
+
+template<typename Adapter>
+void USDShapeReader::read_values(const double motionSampleTime,
+                                 pxr::VtVec3fArray &positions,
+                                 pxr::VtIntArray &face_indices,
+                                 pxr::VtIntArray &face_counts)
+{
+  pxr::VtValue meshPoints = Adapter::GetMeshPoints(prim_, motionSampleTime);
+  positions = meshPoints.Get<pxr::VtArray<pxr::GfVec3f>>();
+  pxr::HdMeshTopology meshTopologyValue = Adapter::GetMeshTopology().Get<pxr::HdMeshTopology>();
+  face_counts = meshTopologyValue.GetFaceVertexCounts();
+  face_indices = meshTopologyValue.GetFaceVertexIndices();
+}
+
+struct Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
+                                       double motionSampleTime,
+                                       int read_flag,
+                                       const char **err_str)
+{
+  if (!prim_) {
+    return existing_mesh;
+  }
+
+  pxr::VtVec3fArray positions;
+  pxr::VtIntArray face_indices;
+  pxr::VtIntArray face_counts;
+
+  Mesh *active_mesh = existing_mesh;
+
+  const bool is_capsule = prim_.IsA<pxr::UsdGeomCapsule>();
+  const bool is_cylinder = prim_.IsA<pxr::UsdGeomCylinder>();
+  const bool is_cone = prim_.IsA<pxr::UsdGeomCone>();
+  const bool is_cube = prim_.IsA<pxr::UsdGeomCube>();
+  const bool is_sphere = prim_.IsA<pxr::UsdGeomSphere>();
+
+  if (is_capsule) {
+    read_values<pxr::UsdImagingCapsuleAdapter>(motionSampleTime, positions, face_indices, face_counts);
+  }
+  else if (is_cylinder) {
+    read_values<pxr::UsdImagingCylinderAdapter>(motionSampleTime, positions, face_indices, face_counts);
+  }
+  else if (is_cone) {
+    read_values<pxr::UsdImagingConeAdapter>(motionSampleTime, positions, face_indices, face_counts);
+  }
+  else if (is_cube) {
+    read_values<pxr::UsdImagingCubeAdapter>(motionSampleTime, positions, face_indices, face_counts);
+  }
+  else if (is_sphere) {
+    read_values<pxr::UsdImagingSphereAdapter>(motionSampleTime, positions, face_indices, face_counts);
+  }
+  else {
+    WM_reportf(RPT_ERROR,
+               "Unhandled Gprim type: %s (%s)",
+               prim_.GetTypeName().GetText(),
+               prim_.GetPath().GetText());
+    return existing_mesh;
+  }
+
+  /* Should be guaranteed to have a good set of data by this point-- copy over. */
+  const bool position_counts_match = active_mesh ? positions.size() == active_mesh->totvert :
+                                                   false;
+  const bool poly_counts_match = active_mesh ? face_counts.size() == active_mesh->totpoly : false;
+
+  if (!position_counts_match || !poly_counts_match) {
+    active_mesh = BKE_mesh_new_nomain_from_template(
+        existing_mesh, positions.size(), 0, 0, face_indices.size(), face_counts.size());
+  }
+
+  for (int i = 0; i < positions.size(); i++) {
+    MVert &mvert = active_mesh->mvert[i];
+    mvert.co[0] = positions[i][0];
+    mvert.co[1] = positions[i][1];
+    mvert.co[2] = positions[i][2];
+  }
+
+  MPoly *mpolys = active_mesh->mpoly;
+  MLoop *mloops = active_mesh->mloop;
+
+  int loop_index = 0;
+
+  if (!poly_counts_match) {
+    for (int i = 0; i < face_counts.size(); i++) {
+      const int face_size = face_counts[i];
+
+      MPoly &poly = mpolys[i];
+      poly.loopstart = loop_index;
+      poly.totloop = face_size;
+      poly.mat_nr = 0;
+
+      /* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */
+      poly.flag |= is_cube ? 0 : ME_SMOOTH;
+
+      for (int f = 0; f < face_size; ++f, ++loop_index) {
+        mloops[loop_index].v = face_indices[loop_index];
+      }
+    }
+  }
+
+  BKE_mesh_calc_edges(active_mesh, false, false);
+  BKE_mesh_normals_tag_dirty(active_mesh);
+
+  return active_mesh;
+}
+
+bool USDShapeReader::is_time_varying()
+{
+  bool result;
+
+  const bool is_capsule = prim_.IsA<pxr::UsdGeomCapsule>();
+  const bool is_cylinder = prim_.IsA

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list