[Bf-blender-cvs] [31d480174a8] soc-2020-io-performance: Add support for exporting nurbs curves & surfaces

Ankit Meel noreply at git.blender.org
Thu Jun 25 14:25:51 CEST 2020


Commit: 31d480174a8caebeeacac14902b02aa5df505a8d
Author: Ankit Meel
Date:   Wed Jun 24 15:38:42 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rB31d480174a8caebeeacac14902b02aa5df505a8d

Add support for exporting nurbs curves & surfaces

Added functionality in OBJNurbs & OBJWriter to export nurbs curve, not
as vertices and edges, but rather control points.

Nurbs surfaces are always converted to mesh and then exported as a
regular mesh with vertices, normals, UV (if it has any), and edges
(if it has no polygons) etc.

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

M	source/blender/io/wavefront_obj/intern/wavefront_obj.hh
M	source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
M	source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
M	source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.hh

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

diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj.hh b/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
index e9e67712452..799653e435c 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj.hh
@@ -22,8 +22,8 @@
 #define __WAVEFRONT_OBJ_HH__
 
 #include "BKE_context.h"
-#include "BKE_lib_id.h"
 #include "BKE_curve.h"
+#include "BKE_lib_id.h"
 #include "BKE_mesh.h"
 #include "BKE_object.h"
 
@@ -161,13 +161,26 @@ class OBJMesh {
 
 class OBJNurbs {
  public:
-  bContext *C;
-  const OBJExportParams *export_params;
+  OBJNurbs(bContext *C, Object *export_object) : _C(C), _export_object_eval(export_object)
+  {
+    init_nurbs_curve(export_object);
+  }
+  void get_curve_name(const char **r_object_name);
+  /** Getter for export curve. Used to obtain a curve's nurbs in OBJWriter class. */
+  const Curve *export_curve()
+  {
+    return _export_curve;
+  }
+  /** Get coordinates of a vertex at given point index. */
+  void calc_point_coords(float r_coords[3], uint point_index, Nurb *nurb);
+  /** Get nurbs' degree and number of "curv" points of a nurb. */
+  void get_curve_info(int *r_nurbs_degree, int *r_curv_num, Nurb *nurb);
 
-  Object *object;
-  Curve *curve;
-  void calc_vertex_coords(float coord[3], uint point_index);
-  const char *get_curve_info(int *nurbs_degree, int *curv_num);
+ private:
+  bContext *_C;
+  Object *_export_object_eval;
+  Curve *_export_curve;
+  void init_nurbs_curve(Object *export_object);
 };
 
 }  // namespace obj
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
index b72eaafe59d..401890a9d1d 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_exporter.cc
@@ -77,19 +77,25 @@ void OBJMesh::init_export_mesh(Object *export_object)
     }
     _tot_vertices = _export_mesh_eval->totvert;
     _tot_poly_normals = _export_mesh_eval->totpoly;
-    store_world_axes_transform();
   }
-
-  /* Curves need a new mesh when exported in the form of vertices and edges.
+  /* Curves and nurbs surfaces need a new mesh when exported in the form of vertices and edges.
    * For primitive circle, new mesh is redundant, but it behaves more like curves, so kept it here.
    */
-  else if (_export_object_eval->type == OB_CURVE && !_export_params->export_curves_as_nurbs) {
+  else {
     _export_mesh_eval = BKE_mesh_new_from_object(depsgraph, _export_object_eval, true);
     _me_eval_needs_free = true;
-    _tot_vertices = _export_mesh_eval->totvert;
-    _tot_edges = _export_mesh_eval->totedge;
-    store_world_axes_transform();
+    if (_export_object_eval->type == OB_CURVE || _export_mesh_eval->totpoly == 0) {
+      /* Don't export polygon normals when there are no polygons. */
+      _tot_poly_normals = 0;
+      _tot_vertices = _export_mesh_eval->totvert;
+      _tot_edges = _export_mesh_eval->totedge;
+    }
+    else if (_export_object_eval->type == OB_SURF) {
+      _tot_vertices = _export_mesh_eval->totvert;
+      _tot_poly_normals = _export_mesh_eval->totpoly;
+    }
   }
+  store_world_axes_transform();
 }
 
 /**
@@ -117,6 +123,15 @@ void OBJMesh::triangulate_mesh(Mesh *me_eval)
   _export_mesh_eval = BKE_mesh_from_bmesh_for_eval_nomain(bmesh, NULL, me_eval);
   BM_mesh_free(bmesh);
 }
+/**
+ * Initialise nurbs curve object.
+ */
+void OBJNurbs::init_nurbs_curve(Object *export_object)
+{
+  Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(_C);
+  _export_object_eval = DEG_get_evaluated_object(depsgraph, export_object);
+  _export_curve = (Curve *)_export_object_eval->data;
+}
 
 /**
  * Store the product of export axes settings and an object's world transform matrix in
@@ -257,24 +272,29 @@ void OBJMesh::calc_edge_vert_indices(uint r_vert_indices[2], uint edge_index)
   }
 }
 
-  void OBJNurbs::calc_vertex_coords(float coords[3], uint vert_index)
-  {
-    Nurb *nu = (Nurb *)curve->nurb.first;
-    BPoint *bpoint = nu->bp;
-    bpoint += vert_index;
-    copy_v3_v3(coords, bpoint->vec);
-  }
-  
-  const char *OBJNurbs::get_curve_info(int *nurbs_degree, int *curv_num)
-  {
-    Nurb *nurb = (Nurb *)curve->nurb.first;
-    *nurbs_degree = nurb->orderu - 1;
-    *curv_num = nurb->pntsv * nurb->pntsu;
-    if (nurb->flagu & CU_NURB_CYCLIC) {
-      *curv_num += *nurbs_degree;
-    }
-    return object->id.name + 2;
+void OBJNurbs::get_curve_name(const char **r_object_name)
+{
+  *r_object_name = _export_object_eval->id.name + 2;
+}
+
+  /** Get coordinates of a vertex at given point index. */
+void OBJNurbs::calc_point_coords(float r_coords[3], uint vert_index, Nurb *nurb)
+{
+  BPoint *bpoint = nurb->bp;
+  bpoint += vert_index;
+  copy_v3_v3(r_coords, bpoint->vec);
+}
+
+  /** Get nurbs' degree and number of "curv" points of a nurb. */
+void OBJNurbs::get_curve_info(int *r_nurbs_degree, int *r_curv_num, Nurb *nurb)
+{
+  *r_nurbs_degree = nurb->orderu - 1;
+  /* "curv_num" are number of control points in a nurbs. If it is cyclic, degree also adds up. */
+  *r_curv_num = nurb->pntsv * nurb->pntsu;
+  if (nurb->flagu & CU_NURB_CYCLIC) {
+    *r_curv_num += *r_nurbs_degree;
   }
+}
 
 /**
  * Traverses over and exports a single frame to a single OBJ file.
@@ -288,19 +308,28 @@ static void export_frame(bContext *C, const OBJExportParams *export_params, cons
   LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
     Object *object_in_layer = base->object;
     switch (object_in_layer->type) {
-      case OB_MESH:
+      case OB_SURF:
+      case OB_MESH: {
         exportable_meshes.append(OBJMesh(C, export_params, object_in_layer));
         break;
-      case OB_CURVE:
-        if (export_params->export_curves_as_nurbs) {
-          export_nurbs.append(OBJNurbs());
-          export_nurbs.last().object = object_in_layer;
-          export_nurbs.last().export_params = export_params;
-          export_nurbs.last().C = C;
+      }
+      case OB_CURVE: {
+        Curve *curve = (Curve *)object_in_layer->data;
+        Nurb *nurb = (Nurb *)curve->nurb.first;
+        if (nurb->type == CU_NURBS) {
+          if (export_params->export_curves_as_nurbs) {
+            exportable_nurbs.append(OBJNurbs(C, object_in_layer));
+          }
+          else {
+            exportable_meshes.append(OBJMesh(C, export_params, object_in_layer));
+          }
         }
-        else {
-        exportable_meshes.append(OBJMesh(C, export_params, object_in_layer));
+        if (nurb->type == CU_BEZIER) {
+          exportable_meshes.append(OBJMesh(C, export_params, object_in_layer));
         }
+        /* Other types of curves are not supported.  */
+        break;
+      }
       default:
         break;
     }
@@ -336,12 +365,11 @@ static void export_frame(bContext *C, const OBJExportParams *export_params, cons
 
     mesh_to_export.destruct();
   }
-  for (uint ob_iter = 0; ob_iter < export_nurbs.size(); ob_iter++) {
-    OBJNurbs &nurbs_to_export = export_nurbs[ob_iter];
-    nurbs_to_export.curve = (Curve *)nurbs_to_export.object->data;
-    frame_writer.write_nurbs_info(nurbs_to_export);
+  /* Export nurbs in parm form, not as vertices and edges. */
+  for (uint ob_iter = 0; ob_iter < exportable_nurbs.size(); ob_iter++) {
+    OBJNurbs &nurbs_to_export = exportable_nurbs[ob_iter];
+    frame_writer.write_nurbs_curve(nurbs_to_export);
   }
-  frame_writer.close_file();
 }
 
 /**
diff --git a/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc b/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
index 6388d978e3a..c9788876a81 100644
--- a/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
+++ b/source/blender/io/wavefront_obj/intern/wavefront_obj_file_handler.cc
@@ -212,46 +212,48 @@ void OBJWriter::write_curve_edges(OBJMesh &obj_mesh_data)
   }
 }
 
-void OBJWriter::write_nurbs_info(OBJNurbs &ob_nurbs)
+void OBJWriter::write_nurbs_curve(OBJNurbs &obj_nurbs_data)
 {
-  // todo object name max is 64.
-  Nurb *nurb = (Nurb *)ob_nurbs.curve->nurb.first;
-  uint tot_points = nurb->pntsv * nurb->pntsu;
-  float point_coord[3];
-  for (uint point_idx = 0; point_idx < tot_points; point_idx++) {
-    ob_nurbs.calc_vertex_coords(point_coord, point_idx);
-    fprintf(outfile, "v %f %f %f\n", point_coord[0], point_coord[1], point_coord[2]);
-  }
+  Nurb *nurb = (Nurb *)obj_nurbs_data.export_curve()->nurb.first;
+  for (; nurb; nurb = nurb->next) {
+    /* Total control points in a nurbs. */
+    uint tot_points = nurb->pntsv * nurb->pntsu;
+    float point_coord[3];
+    for (uint point_idx = 0; point_idx < tot_points; point_idx++) {
+      obj_nurbs_data.calc_point_coords(point_coord, point_idx, nurb);
+      fprintf(_outfile, "v %f %f %f\n", point_coord[0], point_coord[1], point_coord[2]);
+    }
 
-  const char *nurbs_name;
-  int nurbs_degree;
-  /** Number of vertices in the curve + degree of the curve if it is cyclic. */
-  int curv_num;
-  nurbs_name = ob_nurbs.get_curve_info(&nurbs_degree, &curv_num);
+    const char *nurbs_name;
+    obj_nurbs_data.get_curve_name(&nurbs_name);
+    int nurbs_degree;
+    /** Number of vertices in the curve + degree of the curve if it is cyclic. */
+    int curv_num;
+    obj_nurbs_data.get_curve_info(&nurbs_degree, &curv_num, nurb);
 
-  fprintf(outfile, "g %s\ncstype bspline\n deg %d\n", nurbs_name, nurbs_degree);
+    fprintf(_outfile, "g %s\ncstype bspline\ndeg %d\n", nurbs_name, nurbs_degree);
+    /**
+     * curv_num refers to the vertices above written in relative indices.
+     * 0.0 1.0 -1 -2 -3 -4 for a non-cyclic curve with 4 points.
+     * 0.0 1.0 -1 -2 -3 -4 -1 -2 -3 for a cyclic curve with 4 points.
+     */
+    fprintf(_outfile, "curv 0.0 1.0 ");
+    for (int i = 0; i < curv_num; i++) {
+      fprintf(_outfile, "%d ", -1 * ((i % tot_points) + 1));
+    }
+    fprintf(_outfile, "\n");
 
-  /**
-   * curv_num refers to the vertices above written in relative indices.
-   * 0.0 1.0 -1 -2 -3 -4 for a non-cyclic curve with 4 points.
-   * 0.0 1.0 -1 -2 -3 -4 -1 -2 -3 for a cyclic curve with 4 points.
-   */
-  fprintf(outfile, "curv 0.0 1.0 ");
-  for (int i = 0; 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list