[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