[Bf-blender-cvs] [60090d61ead] sybren-usd: USD: support for simple preview materials

Sybren A. Stüvel noreply at git.blender.org
Thu Jun 27 17:10:51 CEST 2019


Commit: 60090d61eadb7daadf10f12c3387b2c118499736
Author: Sybren A. Stüvel
Date:   Thu Jun 27 16:45:36 2019 +0200
Branches: sybren-usd
https://developer.blender.org/rB60090d61eadb7daadf10f12c3387b2c118499736

USD: support for simple preview materials

Very simple versions of the materials are now exported, using only the
viewport diffuse RGB, metallic, and roughness.

When there are multiple materials, the mesh faces are stored as geometry
subset and each material is assigned to the appropriate subset. If there
is only one material this is skipped.

The first material if any) is always applied to the mesh itself
(regardless of the existence of geometry subsets), because the Hydra
viewport doesn't support materials on subsets. See
https://github.com/PixarAnimationStudios/USD/issues/542 for more info.

Note that the geometry subsets are not yet time-sampled, so it will
break when an animated mesh changes topology.

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

M	source/blender/usd/intern/abstract_hierarchy_iterator.h
M	source/blender/usd/intern/usd_hierarchy_iterator.h
M	source/blender/usd/intern/usd_writer_abstract.cc
M	source/blender/usd/intern/usd_writer_abstract.h
M	source/blender/usd/intern/usd_writer_mesh.cc
M	source/blender/usd/intern/usd_writer_mesh.h

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

diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.h b/source/blender/usd/intern/abstract_hierarchy_iterator.h
index 4d39778b0bd..fa5661adb3d 100644
--- a/source/blender/usd/intern/abstract_hierarchy_iterator.h
+++ b/source/blender/usd/intern/abstract_hierarchy_iterator.h
@@ -70,6 +70,8 @@ class AbstractHierarchyIterator {
   const WriterMap &writer_map() const;
   void release_writers();
 
+  virtual std::string get_id_name(const ID *id) const = 0;
+
  private:
   void construct_export_graph();
   void visit_object(Object *object, Object *export_parent, bool weak_export);
@@ -96,7 +98,6 @@ class AbstractHierarchyIterator {
 
   virtual void delete_object_writer(AbstractHierarchyWriter *writer) = 0;
 
-  virtual std::string get_id_name(const ID *id) const = 0;
   virtual std::string path_concatenate(const std::string &parent_path,
                                        const std::string &child_path) const;
 };
diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.h b/source/blender/usd/intern/usd_hierarchy_iterator.h
index c52bdec6471..7c4df467da3 100644
--- a/source/blender/usd/intern/usd_hierarchy_iterator.h
+++ b/source/blender/usd/intern/usd_hierarchy_iterator.h
@@ -28,13 +28,14 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
   void set_export_frame(float frame_nr);
   const pxr::UsdTimeCode &get_export_time_code() const;
 
+  virtual std::string get_id_name(const ID *const id) const override;
+
  protected:
   virtual bool should_export_object(const Object *object) const override;
 
   virtual AbstractHierarchyWriter *create_xform_writer(const HierarchyContext &context) override;
   virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext &context) override;
 
-  virtual std::string get_id_name(const ID *const id) const override;
   virtual void delete_object_writer(AbstractHierarchyWriter *writer) override;
 };
 
diff --git a/source/blender/usd/intern/usd_writer_abstract.cc b/source/blender/usd/intern/usd_writer_abstract.cc
index 59e3a34d6ef..86143b1d035 100644
--- a/source/blender/usd/intern/usd_writer_abstract.cc
+++ b/source/blender/usd/intern/usd_writer_abstract.cc
@@ -94,3 +94,33 @@ const pxr::SdfPath &USDAbstractWriter::usd_path() const
 {
   return usd_path_;
 }
+
+pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(Material *material)
+{
+  static pxr::SdfPath material_library_path("/_materials");
+
+  // Construct the material.
+  pxr::TfToken material_name(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(pxr::TfToken("previewShader"));
+  pxr::UsdShadeShader shader = pxr::UsdShadeShader::Define(stage, shader_path);
+  shader.CreateIdAttr(pxr::VtValue(pxr::TfToken("UsdPreviewSurface")));
+  shader.CreateInput(pxr::TfToken("diffuseColor"), pxr::SdfValueTypeNames->Color3f)
+      .Set(pxr::GfVec3f(material->r, material->g, material->b));
+  shader.CreateInput(pxr::TfToken("roughness"), pxr::SdfValueTypeNames->Float)
+      .Set(material->roughness);
+  shader.CreateInput(pxr::TfToken("metallic"), pxr::SdfValueTypeNames->Float)
+      .Set(material->metallic);
+
+  // Connect the shader and the material together.
+  usd_material.CreateSurfaceOutput().ConnectToSource(shader, pxr::TfToken("surface"));
+
+  return usd_material;
+}
diff --git a/source/blender/usd/intern/usd_writer_abstract.h b/source/blender/usd/intern/usd_writer_abstract.h
index 2a67f878737..3e2feb3faf9 100644
--- a/source/blender/usd/intern/usd_writer_abstract.h
+++ b/source/blender/usd/intern/usd_writer_abstract.h
@@ -4,14 +4,19 @@
 #include "usd_exporter_context.h"
 #include "abstract_hierarchy_iterator.h"
 
-#include "DEG_depsgraph_query.h"
-
 #include <pxr/usd/sdf/path.h>
 #include <pxr/usd/usd/stage.h>
+#include <pxr/usd/usdShade/material.h>
 
 #include <vector>
 
+extern "C" {
+#include "DEG_depsgraph_query.h"
+#include "DNA_material_types.h"
+}
+
 struct Main;
+struct Material;
 struct Object;
 
 class USDAbstractWriter : public AbstractHierarchyWriter {
@@ -40,6 +45,8 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
   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);
 };
 
 #endif /* __USD__USD_WRITER_ABSTRACT_H__ */
diff --git a/source/blender/usd/intern/usd_writer_mesh.cc b/source/blender/usd/intern/usd_writer_mesh.cc
index 3ab72fbf723..42e46d9f934 100644
--- a/source/blender/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/usd/intern/usd_writer_mesh.cc
@@ -2,10 +2,13 @@
 #include "usd_hierarchy_iterator.h"
 
 #include <pxr/usd/usdGeom/mesh.h>
+#include <pxr/usd/usdShade/material.h>
+#include <pxr/usd/usdShade/materialBindingAPI.h>
 
 extern "C" {
 #include "BKE_anim.h"
 #include "BKE_library.h"
+#include "BKE_material.h"
 
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -29,7 +32,7 @@ void USDGenericMeshWriter::do_write(HierarchyContext &context)
   }
 
   try {
-    write_mesh(mesh);
+    write_mesh(context, mesh);
 
     if (needsfree) {
       free_export_mesh(mesh);
@@ -48,7 +51,7 @@ void USDGenericMeshWriter::free_export_mesh(struct Mesh *mesh)
   BKE_id_free(NULL, mesh);
 }
 
-void USDGenericMeshWriter::write_mesh(struct Mesh *mesh)
+void USDGenericMeshWriter::write_mesh(HierarchyContext &context, struct Mesh *mesh)
 {
   pxr::UsdTimeCode timecode = get_export_time_code();
   // printf("USD-\033[32mexporting\033[0m mesh  %s → %s  mesh = %p\n",
@@ -77,15 +80,54 @@ void USDGenericMeshWriter::write_mesh(struct Mesh *mesh)
   MLoop *mloop = mesh->mloop;
   MPoly *mpoly = mesh->mpoly;
 
+  std::map<short, pxr::VtIntArray> face_groups;
   for (int i = 0; i < mesh->totpoly; ++i, ++mpoly) {
     MLoop *loop = mloop + mpoly->loopstart;
     usd_face_vertex_counts.push_back(mpoly->totloop);
     for (int j = 0; j < mpoly->totloop; ++j, ++loop) {
       usd_face_indices.push_back(loop->v);
     }
+
+    face_groups[mpoly->mat_nr].push_back(i);
   }
   usd_mesh.CreateFaceVertexCountsAttr().Set(usd_face_vertex_counts, timecode);
   usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_face_indices, timecode);
+
+  // TODO(Sybren): figure out what happens when the face groups change.
+  if (frame_has_been_written_) {
+    return;
+  }
+
+  // Define a geometry subset per material.
+  bool mesh_material_bound = false;
+  for (auto face_group_iter : face_groups) {
+    short material_number = face_group_iter.first;
+    const pxr::VtIntArray &face_indices = face_group_iter.second;
+
+    Material *material = give_current_material(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();
+
+    if (face_groups.size() > 1) {
+      // Only bother with writing face groups if the object has multiple materials.
+      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());
+    }
+
+    /* Binding a material to a geometry subset isn't supported by the Hydra GL viewport yet, which
+     * is why we also bind the first material to the entire mesh. See
+     * https://github.com/PixarAnimationStudios/USD/issues/542 for more info. */
+    if (!mesh_material_bound) {
+      usd_material.Bind(usd_mesh.GetPrim());
+      mesh_material_bound = true;
+    }
+  }
 }
 
 USDMeshWriter::USDMeshWriter(const USDExporterContext &ctx) : USDGenericMeshWriter(ctx)
diff --git a/source/blender/usd/intern/usd_writer_mesh.h b/source/blender/usd/intern/usd_writer_mesh.h
index fc7138cabd9..001a09a1a88 100644
--- a/source/blender/usd/intern/usd_writer_mesh.h
+++ b/source/blender/usd/intern/usd_writer_mesh.h
@@ -15,7 +15,7 @@ class USDGenericMeshWriter : public USDAbstractWriter {
   virtual void free_export_mesh(Mesh *mesh);
 
  private:
-  void write_mesh(Mesh *mesh);
+  void write_mesh(HierarchyContext &context, Mesh *mesh);
 };
 
 class USDMeshWriter : public USDGenericMeshWriter {



More information about the Bf-blender-cvs mailing list