[Bf-blender-cvs] [66518ce11b1] sybren-usd: USD: Write edge creases to USD mesh

Sybren A. Stüvel noreply at git.blender.org
Fri Jul 12 14:16:27 CEST 2019


Commit: 66518ce11b1889fcde1df829cfab3605c023a447
Author: Sybren A. Stüvel
Date:   Fri Jul 12 12:21:01 2019 +0200
Branches: sybren-usd
https://developer.blender.org/rB66518ce11b1889fcde1df829cfab3605c023a447

USD: Write edge creases to USD mesh

Only the crease is written to USD. The "Sharp" edge flag doesn't seem to
be supported by USD, or at least I couldn't find it in the API docs.

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

M	source/blender/usd/intern/usd_writer_mesh.cc

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

diff --git a/source/blender/usd/intern/usd_writer_mesh.cc b/source/blender/usd/intern/usd_writer_mesh.cc
index c6c7f51c7c9..7ce3102d864 100644
--- a/source/blender/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/usd/intern/usd_writer_mesh.cc
@@ -56,6 +56,22 @@ struct USDMeshData {
   pxr::VtIntArray face_vertex_counts;
   pxr::VtIntArray face_indices;
   std::map<short, pxr::VtIntArray> 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_mesh(HierarchyContext &context, Mesh *mesh)
@@ -75,6 +91,12 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
   usd_mesh.CreateFaceVertexCountsAttr().Set(usd_mesh_data.face_vertex_counts, timecode);
   usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_mesh_data.face_indices, timecode);
 
+  if (!usd_mesh_data.crease_lengths.empty()) {
+    usd_mesh.CreateCreaseLengthsAttr().Set(usd_mesh_data.crease_lengths, timecode);
+    usd_mesh.CreateCreaseIndicesAttr().Set(usd_mesh_data.crease_vertex_indices, timecode);
+    usd_mesh.CreateCreaseSharpnessesAttr().Set(usd_mesh_data.crease_sharpnesses, timecode);
+  }
+
   // TODO(Sybren): figure out what happens when the face groups change.
   if (frame_has_been_written_) {
     return;
@@ -83,23 +105,24 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
   assign_materials(context, usd_mesh, usd_mesh_data.face_groups);
 }
 
-void USDGenericMeshWriter::get_geometry_data(const Mesh *mesh, struct USDMeshData &usd_mesh_data)
+static void get_vertices(const Mesh *mesh, struct 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.points.reserve(mesh->totvert);
-  usd_mesh_data.face_vertex_counts.reserve(mesh->totpoly);
-  usd_mesh_data.face_indices.reserve(mesh->totloop);
 
-  // TODO(Sybren): there is probably a more C++-y way to do this, which avoids copying the entire
-  // mesh to a different structure. I haven't seen the approach below in the USD exporters for
-  // Maya/Houdini, but it's simple and it works for now.
   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, struct 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;
@@ -116,6 +139,38 @@ void USDGenericMeshWriter::get_geometry_data(const Mesh *mesh, struct USDMeshDat
   }
 }
 
+static void get_creases(const Mesh *mesh, struct 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<float>(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, struct 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,



More information about the Bf-blender-cvs mailing list