[Bf-blender-cvs] [6adbae02ef5] usd-importer-T81257: USD importer: added logic to read normals.

Michael A. Kowalski noreply at git.blender.org
Sat Oct 10 21:11:27 CEST 2020


Commit: 6adbae02ef5dc20ed6ef062f9c08d813adb514f8
Author: Michael A. Kowalski
Date:   Fri Oct 9 22:01:06 2020 -0400
Branches: usd-importer-T81257
https://developer.blender.org/rB6adbae02ef5dc20ed6ef062f9c08d813adb514f8

USD importer: added logic to read normals.

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

M	source/blender/editors/io/io_usd.c
M	source/blender/io/usd/intern/usd_reader_mesh.cc
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 9f39057b0e1..f6c8062e96c 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -269,6 +269,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
 
   const bool import_uvs = RNA_boolean_get(op->ptr, "import_uvs");
 
+  const bool import_normals = RNA_boolean_get(op->ptr, "import_normals");
+
   const float scale = RNA_float_get(op->ptr, "scale");
 
   const bool debug = RNA_boolean_get(op->ptr, "debug");
@@ -279,7 +281,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
     ED_object_mode_set(C, OB_MODE_OBJECT);
   }
 
-  struct USDImportParams params = {import_uvs, scale, debug};
+  struct USDImportParams params = {import_uvs, import_normals, scale, debug};
 
   bool ok = USD_import(C, filename, &params, as_background_job);
 
@@ -300,6 +302,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
 
   col = uiLayoutColumn(box, true);
   uiItemR(col, ptr, "import_uvs", 0, NULL, ICON_NONE);
+  uiItemR(col, ptr, "import_normals", 0, NULL, ICON_NONE);
   uiItemR(col, ptr, "debug", 0, NULL, ICON_NONE);
 }
 
@@ -325,6 +328,8 @@ void WM_OT_usd_import(wmOperatorType *ot)
 
   RNA_def_boolean(ot->srna, "import_uvs", true, "uvs", "When checked, import mesh uvs.");
 
+  RNA_def_boolean(ot->srna, "import_normals", true, "normals", "When checked, import mesh normals.");
+
   RNA_def_float(
       ot->srna,
       "scale",
diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc
index c5780c496fe..173293e929d 100644
--- a/source/blender/io/usd/intern/usd_reader_mesh.cc
+++ b/source/blender/io/usd/intern/usd_reader_mesh.cc
@@ -47,6 +47,8 @@ struct MeshSampleData {
   pxr::VtVec2fArray uv_values;
   pxr::VtArray<int> uv_indices;
   pxr::TfToken uv_interpolation;
+  pxr::VtArray<pxr::GfVec3f> normals;
+  pxr::TfToken normals_interpolation;
 
   bool y_up;
   bool reverse_vert_order;
@@ -196,6 +198,116 @@ static void read_mpolys(Mesh *mesh, const MeshSampleData &mesh_data)
   /* TODO(makowalski):  Possibly check for invalid geometry. */
 }
 
+static void process_no_normals(Mesh *mesh)
+{
+  /* Absense of normals in the USD mesh is interpreted as 'smooth'. */
+  BKE_mesh_calc_normals(mesh);
+}
+
+static void process_loop_normals(Mesh *mesh, const MeshSampleData &mesh_data)
+{
+  if (!mesh) {
+    return;
+  }
+
+  size_t loop_count = mesh_data.normals.size();
+
+  if (loop_count == 0) {
+    process_no_normals(mesh);
+    return;
+  }
+
+  if (loop_count != mesh->totloop) {
+    std::cerr << "WARNING: loop normal count mismatch." << std::endl;
+    process_no_normals(mesh);
+    return;
+  }
+
+  float(*lnors)[3] = static_cast<float(*)[3]>(
+    MEM_malloc_arrayN(loop_count, sizeof(float[3]), "USD::FaceNormals"));
+
+  for (int i = 0; i < loop_count; ++i) {
+
+     if (mesh_data.y_up)
+     {
+       blender::io::usd::copy_zup_from_yup(lnors[i], mesh_data.normals[i].data());
+     }
+     else {
+       lnors[i][0] = mesh_data.normals[i].data()[0];
+       lnors[i][1] = mesh_data.normals[i].data()[1];
+       lnors[i][2] = mesh_data.normals[i].data()[2];
+     }
+
+     if (mesh_data.reverse_vert_order) {
+       lnors[i][0] = -lnors[i][0];
+       lnors[i][1] = -lnors[i][1];
+       lnors[i][2] = -lnors[i][2];
+     }
+  }
+
+  mesh->flag |= ME_AUTOSMOOTH;
+  BKE_mesh_set_custom_normals(mesh, lnors);
+
+  MEM_freeN(lnors);
+}
+
+static void process_vertex_normals(Mesh *mesh, const MeshSampleData &mesh_data)
+{
+  if (!mesh) {
+    return;
+  }
+
+  size_t normals_count = mesh_data.normals.size();
+  if (normals_count == 0) {
+    std::cerr << "WARNING: vertex normal count mismatch." << std::endl;
+    process_no_normals(mesh);
+    return;
+  }
+
+  float(*vnors)[3] = static_cast<float(*)[3]>(
+    MEM_malloc_arrayN(normals_count, sizeof(float[3]), "USD::VertexNormals"));
+
+  for (int i = 0; i < normals_count; ++i) {
+
+    if (mesh_data.y_up)
+    {
+      blender::io::usd::copy_zup_from_yup(vnors[i], mesh_data.normals[i].data());
+    }
+    else {
+      vnors[i][0] = mesh_data.normals[i].data()[0];
+      vnors[i][1] = mesh_data.normals[i].data()[1];
+      vnors[i][2] = mesh_data.normals[i].data()[2];
+    }
+
+    if (mesh_data.reverse_vert_order) {
+      vnors[i][0] = -vnors[i][0];
+      vnors[i][1] = -vnors[i][1];
+      vnors[i][2] = -vnors[i][2];
+    }
+  }
+
+  mesh->flag |= ME_AUTOSMOOTH;
+  BKE_mesh_set_custom_normals_from_vertices(mesh, vnors);
+  MEM_freeN(vnors);
+}
+
+static void process_normals(Mesh *mesh, const MeshSampleData &mesh_data)
+{
+  if (!mesh || mesh_data.normals.empty() ) {
+    process_no_normals(mesh);
+    return;
+  }
+
+  if (mesh_data.normals_interpolation == pxr::UsdGeomTokens->faceVarying) {
+    process_loop_normals(mesh, mesh_data);  /* 'vertex normals' in Houdini. */
+  } else if (mesh_data.normals_interpolation == pxr::UsdGeomTokens->vertex) {
+    process_vertex_normals(mesh, mesh_data); /* 'point normals' in Houdini. */
+  } else {
+    process_no_normals(mesh);
+  }
+}
+
+
 namespace blender::io::usd {
 
 UsdMeshReader::UsdMeshReader(const pxr::UsdPrim &prim, const USDImporterContext &context)
@@ -261,7 +373,15 @@ Mesh *UsdMeshReader::read_mesh(Mesh *existing_mesh,
     }
 
     read_mpolys(new_mesh, mesh_data);
-    BKE_mesh_calc_normals(new_mesh);
+
+    if (this->context_.import_params.import_normals) {
+      mesh_.GetNormalsAttr().Get(&mesh_data.normals, time);
+      mesh_data.normals_interpolation = mesh_.GetNormalsInterpolation();
+
+      process_normals(new_mesh, mesh_data);
+    } else {
+      process_no_normals(new_mesh);
+    }
   }
 
   /* TODO(makowalski):  Handle case where topology hasn't changed. */
diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h
index 9dadbb1c02b..c72952dd0bf 100644
--- a/source/blender/io/usd/usd.h
+++ b/source/blender/io/usd/usd.h
@@ -56,6 +56,7 @@ bool USD_export(struct bContext *C,
 
 struct USDImportParams {
   bool import_uvs;
+  bool import_normals;
   float scale;
   bool debug;
 };



More information about the Bf-blender-cvs mailing list