[Bf-blender-cvs] [c5a49168ed3] temp-alembic-exporter-T73363-ms2: Alembic: added exporting of hair

Sybren A. Stüvel noreply at git.blender.org
Tue Apr 28 18:57:33 CEST 2020


Commit: c5a49168ed31604313df8c0da5a8820f7d640b09
Author: Sybren A. Stüvel
Date:   Tue Apr 28 18:36:55 2020 +0200
Branches: temp-alembic-exporter-T73363-ms2
https://developer.blender.org/rBc5a49168ed31604313df8c0da5a8820f7d640b09

Alembic: added exporting of hair

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

M	source/blender/io/alembic/CMakeLists.txt
M	source/blender/io/alembic/intern/export/abc_hierarchy_iterator.cc
M	source/blender/io/alembic/intern/export/abc_writer_curve.h
A	source/blender/io/alembic/intern/export/abc_writer_hair.cc
A	source/blender/io/alembic/intern/export/abc_writer_hair.h

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

diff --git a/source/blender/io/alembic/CMakeLists.txt b/source/blender/io/alembic/CMakeLists.txt
index 2b7da937d64..a11302f2fad 100644
--- a/source/blender/io/alembic/CMakeLists.txt
+++ b/source/blender/io/alembic/CMakeLists.txt
@@ -98,6 +98,7 @@ set(SRC
   intern/export/abc_writer_abstract.cc
   intern/export/abc_writer_camera.cc
   intern/export/abc_writer_curve.cc
+  intern/export/abc_writer_hair.cc
   intern/export/abc_writer_mesh.cc
   intern/export/abc_writer_metaball.cc
   intern/export/abc_writer_nurbs.cc
@@ -110,6 +111,7 @@ set(SRC
   intern/export/abc_writer_abstract.h
   intern/export/abc_writer_camera.h
   intern/export/abc_writer_curve.h
+  intern/export/abc_writer_hair.h
   intern/export/abc_writer_mesh.h
   intern/export/abc_writer_metaball.h
   intern/export/abc_writer_nurbs.h
diff --git a/source/blender/io/alembic/intern/export/abc_hierarchy_iterator.cc b/source/blender/io/alembic/intern/export/abc_hierarchy_iterator.cc
index fcfed3ebd56..e78afdb31f1 100644
--- a/source/blender/io/alembic/intern/export/abc_hierarchy_iterator.cc
+++ b/source/blender/io/alembic/intern/export/abc_hierarchy_iterator.cc
@@ -21,6 +21,7 @@
 #include "abc_writer_abstract.h"
 #include "abc_writer_camera.h"
 #include "abc_writer_curve.h"
+#include "abc_writer_hair.h"
 #include "abc_writer_mesh.h"
 #include "abc_writer_metaball.h"
 #include "abc_writer_nurbs.h"
@@ -167,21 +168,31 @@ AbstractHierarchyWriter *ABCHierarchyIterator::create_data_writer(const Hierarch
   return data_writer;
 }
 
-AbstractHierarchyWriter *ABCHierarchyIterator::create_hair_writer(
-    const HierarchyContext * /*context*/)
+AbstractHierarchyWriter *ABCHierarchyIterator::create_hair_writer(const HierarchyContext *context)
 {
   if (!params_.export_hair) {
     return nullptr;
   }
-  // ABCAbstractWriter *hair_writer = new ABCHairWriter(writer_constructor_args(context));
-  // hair_writer->create_alembic_objects();
-  // return hair_writer;
-  return nullptr;
+
+  ABCWriterConstructorArgs writer_args = writer_constructor_args(context);
+  ABCAbstractWriter *hair_writer = new ABCHairWriter(writer_args);
+
+  if (!hair_writer->is_supported(context)) {
+    delete hair_writer;
+    return nullptr;
+  }
+
+  hair_writer->create_alembic_objects(context);
+  return hair_writer;
 }
 
 AbstractHierarchyWriter *ABCHierarchyIterator::create_particle_writer(
     const HierarchyContext *context)
 {
+  if (!params_.export_particles) {
+    return nullptr;
+  }
+
   ABCWriterConstructorArgs writer_args = writer_constructor_args(context);
   ABCAbstractWriter *particle_writer = new ABCPointsWriter(writer_args);
 
diff --git a/source/blender/io/alembic/intern/export/abc_writer_curve.h b/source/blender/io/alembic/intern/export/abc_writer_curve.h
index 838b51433a0..b3903e578f8 100644
--- a/source/blender/io/alembic/intern/export/abc_writer_curve.h
+++ b/source/blender/io/alembic/intern/export/abc_writer_curve.h
@@ -21,7 +21,7 @@
 #include "abc_writer_abstract.h"
 #include "abc_writer_mesh.h"
 
-#include <Alembic/AbcGeom/CurveType.h>
+#include <Alembic/AbcGeom/OCurves.h>
 
 namespace ABC {
 
diff --git a/source/blender/io/alembic/intern/export/abc_writer_hair.cc b/source/blender/io/alembic/intern/export/abc_writer_hair.cc
new file mode 100644
index 00000000000..2a3aa217c50
--- /dev/null
+++ b/source/blender/io/alembic/intern/export/abc_writer_hair.cc
@@ -0,0 +1,309 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_hair.h"
+#include "intern/abc_axis_conversion.h"
+
+#include <cstdio>
+
+extern "C" {
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math_geom.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_particle.h"
+}
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+using Alembic::Abc::P3fArraySamplePtr;
+using Alembic::AbcGeom::OCurves;
+using Alembic::AbcGeom::OCurvesSchema;
+using Alembic::AbcGeom::ON3fGeomParam;
+using Alembic::AbcGeom::OV2fGeomParam;
+
+namespace ABC {
+
+ABCHairWriter::ABCHairWriter(const ABCWriterConstructorArgs &args)
+    : ABCAbstractWriter(args), uv_warning_shown_(false)
+{
+}
+
+void ABCHairWriter::create_alembic_objects(const HierarchyContext * /*context*/)
+{
+  CLOG_INFO(&LOG, 2, "exporting %s", args_.abc_path.c_str());
+  abc_curves_ = OCurves(args_.abc_parent, args_.abc_name, timesample_index_);
+  abc_curves_schema_ = abc_curves_.getSchema();
+}
+
+const Alembic::Abc::OObject ABCHairWriter::get_alembic_object() const
+{
+  return abc_curves_;
+}
+
+bool ABCHairWriter::check_is_animated(const HierarchyContext & /*context*/) const
+{
+  /* We assume that hair particles are always animated. */
+  return true;
+}
+
+void ABCHairWriter::do_write(HierarchyContext &context)
+{
+  Scene *scene_eval = DEG_get_evaluated_scene(args_.depsgraph);
+  Mesh *mesh = mesh_get_eval_final(args_.depsgraph, scene_eval, context.object, &CD_MASK_MESH);
+  BKE_mesh_tessface_ensure(mesh);
+
+  std::vector<Imath::V3f> verts;
+  std::vector<int32_t> hvertices;
+  std::vector<Imath::V2f> uv_values;
+  std::vector<Imath::V3f> norm_values;
+
+  ParticleSystem *psys = context.particle_system;
+  if (psys->pathcache) {
+    ParticleSettings *part = psys->part;
+    bool export_children = psys->childcache && part->childtype != 0;
+
+    if (!export_children || part->draw & PART_DRAW_PARENT) {
+      write_hair_sample(context, mesh, verts, norm_values, uv_values, hvertices);
+    }
+
+    if (export_children) {
+      write_hair_child_sample(context, mesh, verts, norm_values, uv_values, hvertices);
+    }
+  }
+
+  Alembic::Abc::P3fArraySample iPos(verts);
+  OCurvesSchema::Sample sample(iPos, hvertices);
+  sample.setBasis(Alembic::AbcGeom::kNoBasis);
+  sample.setType(Alembic::AbcGeom::kLinear);
+  sample.setWrap(Alembic::AbcGeom::kNonPeriodic);
+
+  if (!uv_values.empty()) {
+    OV2fGeomParam::Sample uv_smp;
+    uv_smp.setVals(uv_values);
+    sample.setUVs(uv_smp);
+  }
+
+  if (!norm_values.empty()) {
+    ON3fGeomParam::Sample norm_smp;
+    norm_smp.setVals(norm_values);
+    sample.setNormals(norm_smp);
+  }
+
+  update_bounding_box(context.object);
+  sample.setSelfBounds(bounding_box_);
+  abc_curves_schema_.set(sample);
+}
+
+void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
+                                      Mesh *mesh,
+                                      std::vector<Imath::V3f> &verts,
+                                      std::vector<Imath::V3f> &norm_values,
+                                      std::vector<Imath::V2f> &uv_values,
+                                      std::vector<int32_t> &hvertices)
+{
+  /* Get untransformed vertices, there's a xform under the hair. */
+  float inv_mat[4][4];
+  invert_m4_m4_safe(inv_mat, context.object->obmat);
+
+  MTFace *mtface = mesh->mtface;
+  MFace *mface = mesh->mface;
+  MVert *mverts = mesh->mvert;
+
+  if ((!mtface || !mface) && !uv_warning_shown_) {
+    std::fprintf(stderr,
+                 "Warning, no UV set found for underlying geometry of %s.\n",
+                 context.object->id.name + 2);
+    uv_warning_shown_ = true;
+  }
+
+  ParticleSystem *psys = context.particle_system;
+  ParticleSettings *part = psys->part;
+  ParticleData *pa = psys->particles;
+  int k;
+
+  ParticleCacheKey **cache = psys->pathcache;
+  ParticleCacheKey *path;
+  float normal[3];
+  Imath::V3f tmp_nor;
+
+  for (int p = 0; p < psys->totpart; p++, pa++) {
+    /* underlying info for faces-only emission */
+    path = cache[p];
+
+    /* Write UV and normal vectors */
+    if (part->from == PART_FROM_FACE && mtface) {
+      const int num = pa->num_dmcache >= 0 ? pa->num_dmcache : pa->num;
+
+      if (num < mesh->totface) {
+        /* TODO(Sybren): check whether the NULL check here and if(mface) are actually required */
+        MFace *face = mface == NULL ? NULL : &mface[num];
+        MTFace *tface = mtface + num;
+
+        if (mface) {
+          float r_uv[2], mapfw[4], vec[3];
+
+          psys_interpolate_uvs(tface, face->v4, pa->fuv, r_uv);
+          uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1]));
+
+          psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL);
+
+          copy_yup_from_zup(tmp_nor.getValue(), normal);
+          norm_values.push_back(tmp_nor);
+        }
+      }
+      else {
+        std::fprintf(stderr, "Particle to faces overflow (%d/%d)\n", num, mesh->totface);
+      }
+    }
+    else if (part->from == PART_FROM_VERT && mtface) {
+      /* vertex id */
+      const int num = (pa->num_dmcache >= 0) ? pa->num_dmcache : pa->num;
+
+      /* iterate over all faces to find a corresponding underlying UV */
+      for (int n = 0; n < mesh->totface; n++) {
+        MFace *face = &mface[n];
+        MTFace *tface = mtface + n;
+        unsigned int vtx[4];
+        vtx[0] = face->v1;
+        vtx[1] = face->v2;
+        vtx[2] = face->v3;
+        vtx[3] = face->v4;
+        bool found = false;
+
+        for (int o = 0; o < 4; o++) {
+          if (o > 2 && vtx[o] == 0) {
+            break;
+          }
+
+          if (vtx[o] == num) {
+            uv_values.push_back(Imath::V2f(tface->uv[o][0], tface->uv[o][1]));
+
+            MVert *mv = mverts + vtx[o];
+
+            normal_short_to_float_v3(normal, mv->no);
+            copy_yup_from_zup(tmp_nor.getValue(), normal);
+            norm_values.push_back(tmp_nor);
+            found = true;
+            break;
+      

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list