[Bf-blender-cvs] [309bc3c6532] soc-2019-fast-io: [Fast import/export] Added OBJ Import with support for only one object and using only vertices and faces

Hugo Sales noreply at git.blender.org
Sun Jul 21 02:37:27 CEST 2019


Commit: 309bc3c6532bac9836c3d0554ae75b79ed1e6502
Author: Hugo Sales
Date:   Sun Jul 21 01:36:08 2019 +0100
Branches: soc-2019-fast-io
https://developer.blender.org/rB309bc3c6532bac9836c3d0554ae75b79ed1e6502

[Fast import/export] Added OBJ Import with support for only one object and using only vertices and faces

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

M	source/blender/editors/io/intern/common.cpp
M	source/blender/editors/io/intern/common.hpp
M	source/blender/editors/io/intern/obj_import.cpp

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

diff --git a/source/blender/editors/io/intern/common.cpp b/source/blender/editors/io/intern/common.cpp
index 484c5365d29..9ddc9b80c07 100644
--- a/source/blender/editors/io/intern/common.cpp
+++ b/source/blender/editors/io/intern/common.cpp
@@ -281,16 +281,16 @@ bool import_end(bContext *UNUSED(C), ImportSettings *const settings)
   return true;
 }
 
-const std::array<float, 3> calculate_normal(const Mesh *const mesh, const MPoly &mp)
+const float3 calculate_normal(const Mesh *const mesh, const MPoly &mp)
 {
   float no[3];
   BKE_mesh_calc_poly_normal(&mp, mesh->mloop + mp.loopstart, mesh->mvert, no);
-  return std::array<float, 3>{no[0], no[1], no[2]};
+  return float3{no[0], no[1], no[2]};
 }
 
-std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh)
+std::vector<float3> get_normals(const Mesh *const mesh)
 {
-  std::vector<std::array<float, 3>> normals{};
+  std::vector<float3> normals{};
   normals.reserve(mesh->totvert);
   const float(*loop_no)[3] = static_cast<float(*)[3]>(
       CustomData_get_layer(&mesh->ldata, CD_NORMAL));
@@ -306,7 +306,7 @@ std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh)
       ml = mesh->mloop + mp->loopstart + (mp->totloop - 1);
       for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
         const float(&no)[3] = loop_no[ml->v];
-        normals.push_back(std::array<float, 3>{no[0], no[1], no[2]});
+        normals.push_back(float3{no[0], no[1], no[2]});
       }
     }
   }
@@ -318,7 +318,7 @@ std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh)
       /* Flat shaded, use common normal for all verts. */
       if ((mp->flag & ME_SMOOTH) == 0) {
         BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no);
-        normals.push_back(std::array<float, 3>{no[0], no[1], no[2]});
+        normals.push_back(float3{no[0], no[1], no[2]});
         ml -= mp->totloop;
         loop_index += mp->totloop;
       }
@@ -326,7 +326,7 @@ std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh)
         /* Smooth shaded, use individual vert normals. */
         for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
           normal_short_to_float_v3(no, verts[ml->v].no);
-          normals.push_back(std::array<float, 3>{no[0], no[1], no[2]});
+          normals.push_back(float3{no[0], no[1], no[2]});
         }
       }
     }
@@ -334,24 +334,24 @@ std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh)
   normals.shrink_to_fit();
   return normals;
 }
-std::vector<std::array<float, 2>> get_uv(const Mesh *const mesh)
+std::vector<float2> get_uv(const Mesh *const mesh)
 {
-  std::vector<std::array<float, 2>> uvs{};
+  std::vector<float2> uvs{};
   uvs.reserve(mesh->totloop);
   for (int i = 0, e = mesh->totloop; i < e; ++i) {
     const float(&uv)[2] = mesh->mloopuv[i].uv;
-    uvs.push_back(std::array<float, 2>{uv[0], uv[1]});
+    uvs.push_back(float2{uv[0], uv[1]});
   }
   return uvs;
 }
 
-std::vector<std::array<float, 3>> get_vertices(const Mesh *const mesh)
+std::vector<float3> get_vertices(const Mesh *const mesh)
 {
-  std::vector<std::array<float, 3>> vxs{};
+  std::vector<float3> vxs{};
   vxs.reserve(mesh->totvert);
   for (int i = 0, e = mesh->totvert; i < e; ++i) {
     const MVert &v = mesh->mvert[i];
-    vxs.push_back(std::array<float, 3>{v.co[0], v.co[1], v.co[2]});
+    vxs.push_back(float3{v.co[0], v.co[1], v.co[2]});
   }
   return vxs;
 }
diff --git a/source/blender/editors/io/intern/common.hpp b/source/blender/editors/io/intern/common.hpp
index cbd6e416ce1..25a5f92200d 100644
--- a/source/blender/editors/io/intern/common.hpp
+++ b/source/blender/editors/io/intern/common.hpp
@@ -56,6 +56,9 @@ extern "C" {
 
 namespace common {
 
+using float3 = std::array<float, 3>;
+using float2 = std::array<float, 2>;
+
 // --- PROTOTYPES ---
 
 bool object_is_smoke_sim(const Object *const ob);
@@ -92,11 +95,11 @@ bool time_export(bContext *C,
                  void (*start)(bContext *C, ExportSettings *const settings),
                  bool (*end)(bContext *C, ExportSettings *const settings));
 
-const std::array<float, 3> calculate_normal(const Mesh *const mesh, const MPoly &mp);
+const float3 calculate_normal(const Mesh *const mesh, const MPoly &mp);
 
-std::vector<std::array<float, 3>> get_normals(const Mesh *const mesh);
-std::vector<std::array<float, 2>> get_uv(const Mesh *const mesh);
-std::vector<std::array<float, 3>> get_vertices(const Mesh *const mesh);
+std::vector<float3> get_normals(const Mesh *const mesh);
+std::vector<float2> get_uv(const Mesh *const mesh);
+std::vector<float3> get_vertices(const Mesh *const mesh);
 
 // --- TEMPLATES ---
 
@@ -144,8 +147,8 @@ template<typename key_t> using set_mapping_t = std::vector<typename set_t<key_t>
 // A pair of the two above, to tie them together
 template<typename key_t> using dedup_pair_t = std::pair<set_t<key_t>, set_mapping_t<key_t>>;
 // The set key for UV and normal. size_t is the original index
-using uv_key_t = std::pair<std::array<float, 2>, size_t>;
-using no_key_t = std::pair<std::array<float, 3>, size_t>;
+using uv_key_t = std::pair<float2, size_t>;
+using no_key_t = std::pair<float3, size_t>;
 
 // Construct a new deduplicated set for either normals or UVs, with the given similarity threshold
 // C++14/17 would be useful here...
diff --git a/source/blender/editors/io/intern/obj_import.cpp b/source/blender/editors/io/intern/obj_import.cpp
index 0bed847704b..f8836f6bd09 100644
--- a/source/blender/editors/io/intern/obj_import.cpp
+++ b/source/blender/editors/io/intern/obj_import.cpp
@@ -11,6 +11,7 @@ extern "C" {
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
 #include "BKE_mesh_runtime.h"
+#include "BKE_object.h"
 #include "BKE_scene.h"
 
 #include "DNA_curve_types.h"
@@ -54,15 +55,187 @@ extern "C" {
 #include <sstream>
 #include <unordered_map>
 #include <vector>
+#include <tuple>
+
+#define BOOST_SPIRIT_DEBUG
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/iostreams/device/mapped_file.hpp>
+#include <boost/phoenix/phoenix.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/define_struct.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
 
 #include "common.hpp"
 #include "iterators.hpp"
 
+// struct float3 {
+//   float x, y, z;
+// };
+// BOOST_FUSION_ADAPT_STRUCT(float3, (float, x)(float, y)(float, z))
+
+BOOST_FUSION_DEFINE_STRUCT((), obj_face, (int, vx)(int, uv)(int, no))
+BOOST_FUSION_DEFINE_STRUCT((), float3, (float, x)(float, y)(float, z))
+BOOST_FUSION_DEFINE_STRUCT((), float2, (float, u)(float, v))
+
 namespace {
+
+namespace qi = boost::spirit::qi;
+namespace ph = boost::phoenix;
+template<typename Result> using rule = qi::rule<const char *, Result>;
+
+template<typename Inner> using vec = std::vector<Inner>;
+using str = std::string;
+
+struct OBJImport {
+  ImportSettings *settings;
+  vec<float3> vertices;
+  vec<float2> uvs;
+  vec<float3> normals;
+  vec<vec<obj_face>> faces;
+  // Object *current_object;
+  Mesh *current_mesh;
+  vec<Mesh *> meshes;
+
+  OBJImport(ImportSettings *settings) : settings(settings)
+  {
+  }
+
+  void v_line(float3 &v)
+  {
+    this->vertices.push_back(v);
+  }
+  void vn_line(float3 &no)
+  {
+    this->normals.push_back(no);
+  }
+  void vt_line(float2 &uv)
+  {
+    this->uvs.push_back(uv);
+  }
+  void f_line(vec<obj_face> &face)
+  {
+    this->faces.push_back(face);
+    this->current_mesh->totloop += face.size();
+    ++this->current_mesh->totpoly;
+  }
+  void g_line(vec<str> &s)
+  {
+  }
+  void o_line(str &o)
+  {
+    Object *ob = BKE_object_add(
+        settings->main, settings->scene, settings->view_layer, OB_MESH, o.c_str());
+    this->current_mesh = (Mesh *)ob->data;
+    this->meshes.push_back(current_mesh);
+  }
+  void s_line(int &s)
+  {
+  }
+  void mtllib_line(vec<str> &mtllibs)
+  {
+  }
+  void usemtl_line(str &s)
+  {
+  }
+};
+
 void OBJ_import_start(bContext *C, ImportSettings *const settings)
 {
   common::import_start(C, settings);
-  std::cerr << "IMPORTING\n";
+
+  OBJImport import{settings};
+
+  boost::iostreams::mapped_file mmap(settings->filepath, boost::iostreams::mapped_file::readonly);
+  const char *const start = mmap.const_data();
+  const char *const last = start + mmap.size() - 1;
+  const char *first = start;
+
+  /* clang-format off */
+
+  // Components
+  auto           token         = qi::lexeme[+(qi::graph)];
+  auto           rest          = qi::omit[*(qi::char_ - qi::eol)] >> qi::eol;
+  auto           comment       = qi::lit("#") >> rest;
+  rule<float3()> rule3f        = qi::float_ >> qi::float_ >> qi::float_;
+  rule<float2()> rule2f        = qi::float_ >> qi::float_;
+  rule<obj_face> rule_obj_face = qi::int_ >> -('/' >> -qi::int_) >> -('/' >> qi::int_);
+  rule<int()>    on_off        = qi::lit("off")[qi::_val = 0] |
+                                 qi::lit("on")[qi::_val = 1] |
+                                 qi::int_[qi::_val = qi::_1];
+  // Lines
+  rule<float3()>   v_line      = 'v' >> rule3f >> rest;
+  rule<float3()>   vn_line     = "vn" >> rule3f >> rest;
+  rule<float2()>   vt_line     = "vt" >> rule2f >> rest;
+  rule<vec<obj_face>()> f_line = 'f' >> qi::repeat(3, qi::inf)[rule_obj_face] >> rest;
+  rule<vec<str>()> g_line      = 'g' >> *token >> rest;
+  rule<str()>      o_line      = 'o' >> token >> qi::eol;
+  rule<int()>      s_line      = 's' >> on_off >> rest;
+  rule<vec<str>()> mtllib_line = "mtllib" >> +token >> rest;
+  rule<str()>      usemtl_line = "usemtl" >> token >> rest;
+
+  // When rule x matches, run function of same name on the import
+  // object (instance of OBJImport) with the match
+#define BIND(x) x[ph::bind(&OBJImport::x, &import, qi::_1)]
+
+
+  bool result = qi::phrase_parse(first /* modifies */, last,
+                                 *(BIND(v_line) |
+                                   BIND(vn_line) |
+                                   BIND(vt_line) |
+                                   BIND(f_line) |
+                                   BIND(g_line) |
+                                   BIND(o_line) |
+                                   BIND(s_line) |
+                                   BIND(mtllib_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list