Alembic export: fixed curve type and order.
[blender.git] / source / blender / alembic / intern / abc_curves.cc
index 2b54741a5c5c5dd8a07e29c366f88cd80d3b6b7f..58b8d7e05cd03838b8095c07f13954a282d0a5d9 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 
 #include "BLI_listbase.h"
 
+#include "BKE_cdderivedmesh.h"
 #include "BKE_curve.h"
 #include "BKE_object.h"
 
@@ -94,14 +95,14 @@ void AbcCurveWriter::do_write()
        for (; nurbs; nurbs = nurbs->next) {
                if (nurbs->bp) {
                        curve_basis = Alembic::AbcGeom::kNoBasis;
-                       curve_type = Alembic::AbcGeom::kLinear;
+                       curve_type = Alembic::AbcGeom::kVariableOrder;
 
                        const int totpoint = nurbs->pntsu * nurbs->pntsv;
 
                        const BPoint *point = nurbs->bp;
 
                        for (int i = 0; i < totpoint; ++i, ++point) {
-                               copy_zup_yup(temp_vert.getValue(), point->vec);
+                               copy_yup_from_zup(temp_vert.getValue(), point->vec);
                                verts.push_back(temp_vert);
                                weights.push_back(point->vec[3]);
                                widths.push_back(point->radius);
@@ -117,7 +118,7 @@ void AbcCurveWriter::do_write()
 
                        /* TODO(kevin): store info about handles, Alembic doesn't have this. */
                        for (int i = 0; i < totpoint; ++i, ++bezier) {
-                               copy_zup_yup(temp_vert.getValue(), bezier->vec[1]);
+                               copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]);
                                verts.push_back(temp_vert);
                                widths.push_back(bezier->radius);
                        }
@@ -159,7 +160,7 @@ void AbcCurveWriter::do_write()
                        }
                }
 
-               orders.push_back(nurbs->orderu + 1);
+               orders.push_back(nurbs->orderu);
                vert_counts.push_back(verts.size());
        }
 
@@ -204,6 +205,7 @@ void AbcCurveReader::readObjectData(Main *bmain, float time)
 
        cu->flag |= CU_DEFORM_FILL | CU_3D;
        cu->actvert = CU_ACT_NONE;
+       cu->resolu = 1;
 
        m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str());
        m_object->data = cu;
@@ -249,13 +251,18 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
                nu->pntsv = 1;
                nu->flag |= CU_SMOOTH;
 
-               nu->orderu = num_verts;
-
-               if (smp.getType() == Alembic::AbcGeom::kCubic) {
-                       nu->orderu = 3;
-               }
-               else if (orders && orders->size() > i) {
-                       nu->orderu = static_cast<short>((*orders)[i] - 1);
+               switch (smp.getType()) {
+                       case Alembic::AbcGeom::kCubic:
+                               nu->orderu = 4;
+                               break;
+                       case Alembic::AbcGeom::kVariableOrder:
+                               if (orders && orders->size() > i) {
+                                       nu->orderu = static_cast<short>((*orders)[i]);
+                               }
+                               break;
+                       case Alembic::AbcGeom::kLinear:
+                       default:
+                               nu->orderu = 2;
                }
 
                if (periodicity == Alembic::AbcGeom::kNonPeriodic) {
@@ -321,7 +328,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
                                weight = (*weights)[idx];
                        }
 
-                       copy_yup_zup(bp->vec, pos.getValue());
+                       copy_zup_from_yup(bp->vec, pos.getValue());
                        bp->vec[3] = weight;
                        bp->f1 = SELECT;
                        bp->radius = radius;
@@ -353,3 +360,54 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
                BLI_addtail(BKE_curve_nurbs_get(cu), nu);
        }
 }
+
+/* NOTE: Alembic only stores data about control points, but the DerivedMesh
+ * passed from the cache modifier contains the displist, which has more data
+ * than the control points, so to avoid corrupting the displist we modify the
+ * object directly and create a new DerivedMesh from that. Also we might need to
+ * create new or delete existing NURBS in the curve.
+ */
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/)
+{
+       ISampleSelector sample_sel(time);
+       const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
+
+       const P3fArraySamplePtr &positions = sample.getPositions();
+       const Int32ArraySamplePtr num_vertices = sample.getCurvesNumVertices();
+
+       int vertex_idx = 0;
+       int curve_idx = 0;
+       Curve *curve = static_cast<Curve *>(m_object->data);
+
+       const int curve_count = BLI_listbase_count(&curve->nurb);
+
+       if (curve_count != num_vertices->size()) {
+               BKE_nurbList_free(&curve->nurb);
+               read_curve_sample(curve, m_curves_schema, time);
+       }
+       else {
+               Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
+               for (; nurbs; nurbs = nurbs->next, ++curve_idx) {
+                       const int totpoint = (*num_vertices)[curve_idx];
+
+                       if (nurbs->bp) {
+                               BPoint *point = nurbs->bp;
+
+                               for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) {
+                                       const Imath::V3f &pos = (*positions)[vertex_idx];
+                                       copy_zup_from_yup(point->vec, pos.getValue());
+                               }
+                       }
+                       else if (nurbs->bezt) {
+                               BezTriple *bezier = nurbs->bezt;
+
+                               for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) {
+                                       const Imath::V3f &pos = (*positions)[vertex_idx];
+                                       copy_zup_from_yup(bezier->vec[1], pos.getValue());
+                               }
+                       }
+               }
+       }
+
+       return CDDM_from_curve(m_object);
+}