Alembic export: support simple child hairs (Fix T51144)
[blender.git] / source / blender / alembic / intern / abc_hair.cc
index 45bf9b7ab8a1ebfa52d9649d6acb1aed12d90f7b..2d42c532c9bce0dd7a5eb3b1e5c0ba4b0cc283e6 100644 (file)
@@ -56,10 +56,11 @@ AbcHairWriter::AbcHairWriter(Scene *scene,
                              ExportSettings &settings,
                              ParticleSystem *psys)
     : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+    , m_uv_warning_shown(false)
 {
        m_psys = psys;
 
-       OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
+       OCurves curves(parent->alembicXform(), psys->name, m_time_sampling);
        m_schema = curves.getSchema();
 }
 
@@ -77,7 +78,6 @@ void AbcHairWriter::do_write()
 
        DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH);
        DM_ensure_tessface(dm);
-       DM_update_tessface_data(dm);
 
        std::vector<Imath::V3f> verts;
        std::vector<int32_t> hvertices;
@@ -133,8 +133,10 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
        MFace *mface = dm->getTessFaceArray(dm);
        MVert *mverts = dm->getVertArray(dm);
 
-       if (!mtface || !mface) {
-               std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
+       if ((!mtface || !mface) && !m_uv_warning_shown) {
+               std::fprintf(stderr, "Warning, no UV set found for underlying geometry of %s.\n",
+                            m_object->id.name + 2);
+               m_uv_warning_shown = true;
        }
 
        ParticleData * pa = m_psys->particles;
@@ -164,7 +166,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
 
                                        psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL);
 
-                                       copy_zup_yup(tmp_nor.getValue(), normal);
+                                       copy_yup_from_zup(tmp_nor.getValue(), normal);
                                        norm_values.push_back(tmp_nor);
                                }
                        }
@@ -198,7 +200,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
                                                MVert *mv = mverts + vtx[o];
 
                                                normal_short_to_float_v3(normal, mv->no);
-                                               copy_zup_yup(tmp_nor.getValue(), normal);
+                                               copy_yup_from_zup(tmp_nor.getValue(), normal);
                                                norm_values.push_back(tmp_nor);
                                                found = true;
                                                break;
@@ -239,13 +241,8 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
        invert_m4_m4_safe(inv_mat, m_object->obmat);
 
        MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE));
-       MFace *mface = dm->getTessFaceArray(dm);
        MVert *mverts = dm->getVertArray(dm);
 
-       if (!mtface || !mface) {
-               std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
-       }
-
        ParticleCacheKey **cache = m_psys->childcache;
        ParticleCacheKey *path;
 
@@ -255,12 +252,25 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
                path = cache[p];
 
                if (part->from == PART_FROM_FACE) {
-                       const int num = pc->num;
+                       if (part->childtype == PART_CHILD_PARTICLES || !mtface) {
+                               /* Face index is unknown for these particles, so just take info
+                                * from the parent. */
+                               uv_values.push_back(uv_values[pc->parent]);
+                               norm_values.push_back(norm_values[pc->parent]);
+                       }
+                       else {
+                               const int num = pc->num;
+                               if (num < 0) {
+                                       ABC_LOG(m_settings.logger)
+                                               << "Warning, child particle of hair system " << m_psys->name
+                                               << " has unknown face index of geometry of "<< (m_object->id.name + 2)
+                                               << ", skipping child hair." << std::endl;
+                                       continue;
+                               }
 
-                       MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
-                       MTFace *tface = mtface + num;
+                               MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
+                               MTFace *tface = mtface + num;
 
-                       if (mface && mtface) {
                                float r_uv[2], tmpnor[3], mapfw[4], vec[3];
 
                                psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
@@ -272,6 +282,14 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
                                norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1]));
                        }
                }
+               else {
+                       ABC_LOG(m_settings.logger)
+                               << "Unknown particle type " << part->from
+                               << " for child hair of system " << m_psys->name
+                               << std::endl;
+                       uv_values.push_back(uv_values[pc->parent]);
+                       norm_values.push_back(norm_values[pc->parent]);
+               }
 
                int steps = path->segments + 1;
                hvertices.push_back(steps);