[Bf-blender-cvs] [2eb8ba7005e] soc-2019-fast-io: [Fast import/export] Initial iterator implementation and STL export

Hugo Sales noreply at git.blender.org
Mon Jun 3 10:52:22 CEST 2019


Commit: 2eb8ba7005e1a6db5bd64e743f66a6e3a88f716e
Author: Hugo Sales
Date:   Mon Jun 3 09:51:58 2019 +0100
Branches: soc-2019-fast-io
https://developer.blender.org/rB2eb8ba7005e1a6db5bd64e743f66a6e3a88f716e

[Fast import/export] Initial iterator implementation and STL export

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

M	release/scripts/startup/bl_ui/space_topbar.py
M	source/blender/editors/io/intern/common.cpp
M	source/blender/editors/io/intern/common.hpp
M	source/blender/editors/io/intern/obj.cpp
M	source/blender/editors/io/intern/stl.cpp
M	source/blender/editors/io/intern/stl.h
M	source/blender/editors/io/io_common.c
M	source/blender/editors/io/io_obj.c
M	source/blender/editors/io/io_stl.c

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

diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 01a7dd0346c..33114a777fa 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -408,7 +408,8 @@ class TOPBAR_MT_file_import(Menu):
         if bpy.app.build_options.alembic:
             self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
 
-        self.layout.operator("wm.obj_import", text="Wavefront (.obj)")
+        self.layout.operator("wm.obj_import_c", text="Wavefront (.obj)")
+        self.layout.operator("wm.stl_import_c", text="STL (.stl)")
 
 
 class TOPBAR_MT_file_export(Menu):
@@ -421,7 +422,8 @@ class TOPBAR_MT_file_export(Menu):
         if bpy.app.build_options.alembic:
             self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
 
-        self.layout.operator("wm.obj_export", text="Wavefront (.obj)")
+        self.layout.operator("wm.obj_export_c", text="Wavefront (.obj)")
+        self.layout.operator("wm.stl_export_c", text="STL (.stl)")
 
 class TOPBAR_MT_file_external_data(Menu):
     bl_label = "External Data"
diff --git a/source/blender/editors/io/intern/common.cpp b/source/blender/editors/io/intern/common.cpp
index a1be9c54687..570694f3e4a 100644
--- a/source/blender/editors/io/intern/common.cpp
+++ b/source/blender/editors/io/intern/common.cpp
@@ -123,9 +123,8 @@ namespace common {
 
 		/* Temporarily disable modifiers if we shouldn't apply them */
 		if (!settings->apply_modifiers)
-			for_each_modifier(ob, [](ModifierData *md){
-				                      md->mode |= eModifierMode_DisableTemporary;
-			                      });
+			for(ModifierData &md : common::modifier_iter{ob})
+				md.mode |= eModifierMode_DisableTemporary;
 
 		float scale_mat[4][4];
 		scale_m4_fl(scale_mat, settings->global_scale);
@@ -154,9 +153,8 @@ namespace common {
 			                                    (Object *) ob, &CD_MASK_MESH);
 
 		if (!settings->apply_modifiers)
-			for_each_modifier(ob, [](ModifierData *md){
-				                      md->mode &= ~eModifierMode_DisableTemporary;
-			                      });
+			for(ModifierData &md : common::modifier_iter{ob})
+				md.mode &= ~eModifierMode_DisableTemporary;
 
 		if (settings->triangulate) {
 			struct BMeshCreateParams bmcp = {false};
@@ -177,6 +175,11 @@ namespace common {
 		return false;
 	}
 
+	void free_mesh(Mesh *mesh, bool needs_free) {
+		if (needs_free)
+			BKE_id_free(NULL, mesh); // TODO someoene null? (alembic)
+	}
+
 	std::string get_object_name(const Object * const eob, const Mesh * const mesh) {
 		std::string name{eob->id.name + 2};
 		std::string mesh_name{mesh->id.name + 2};
@@ -184,6 +187,10 @@ namespace common {
 		return name;
 	}
 
+	std::string get_version_string() {
+		return ""; // TODO someone implement
+	}
+
 	void export_start(bContext *UNUSED(C), ExportSettings * const settings) {
 		/* From alembic_capi.cc
 		 * XXX annoying hack: needed to prevent data corruption when changing
@@ -214,4 +221,12 @@ namespace common {
 		std::cout << "Took " << (std::chrono::steady_clock::now() - f).count() << "ns\n";
 		return ret;
 	}
+
+	const std::array<float, 3> 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]};
+	}
 }
diff --git a/source/blender/editors/io/intern/common.hpp b/source/blender/editors/io/intern/common.hpp
index 5c492b40687..3d036c75f6f 100644
--- a/source/blender/editors/io/intern/common.hpp
+++ b/source/blender/editors/io/intern/common.hpp
@@ -27,6 +27,7 @@ extern "C" {
 #include "BLI_listbase.h"
 #include "BLI_math_matrix.h"
 #include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
 
 #include "bmesh.h"
 #include "bmesh_tools.h"
@@ -50,6 +51,10 @@ extern "C" {
 #include <set>
 #include <array>
 #include <typeinfo>
+#include <iterator>
+
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
 
 namespace common {
 	using ulong = unsigned long;
@@ -65,117 +70,241 @@ namespace common {
 	void change_orientation(float (&mat)[4][4], int forward, int up);
 
 	bool get_final_mesh(const ExportSettings * const settings, const Scene * const escene,
-	                    const Object *eob, Mesh **mesh);
+	                    const Object *ob, Mesh **mesh /* out */);
+
+	void free_mesh(Mesh *mesh, bool needs_free);
 
-	std::string get_object_name(const Object * const eob, const Mesh * const mesh);
+	std::string get_object_name(const Object * const ob, const Mesh * const mesh);
+	std::string get_version_string();
 
 	void export_start(bContext *C, ExportSettings * const settings);
 	bool export_end(bContext *C, ExportSettings * const settings);
 
-	// Execute `start` and `end` and time it. Those functions should be specific to each exportter,
-	// but have the same signature as the two above
+	// Execute `start` and `end` and time it. Those functions should be
+	// specific to each exportter, but have the same signature as the two above
 	bool time_export(bContext *C, ExportSettings * const settings,
 	                 typeof(export_start) start, typeof(export_end) end);
 
+	const std::array<float, 3> calculate_normal(const Mesh * const mesh,
+	                                            const MPoly &mp);
+
 	// --- TEMPLATES ---
 
-	template<typename func>
-	void for_each_modifier(const Object * const ob, func f) {
-		for (ModifierData *md = (ModifierData *) ob->modifiers.first;
-		     md; md = md->next)
-			f(md);
-	}
+	// Adapt a pointer-size pair as a random access iterator
+	template<typename SourceT, typename Tag = std::random_access_iterator_tag>
+	struct pointer_iterator :
+		public boost::iterator_facade<pointer_iterator<SourceT, Tag>, SourceT &, Tag> {
+		pointer_iterator() = default;
+		pointer_iterator(const pointer_iterator<SourceT, Tag> &) = default;
+		pointer_iterator(pointer_iterator<SourceT, Tag> &&) = default;
+		explicit pointer_iterator(SourceT *p) : it(p), first(p), size(0) {}
+		explicit pointer_iterator(SourceT *p, size_t size) : it(p), first(p), size(size) {}
+		pointer_iterator operator=(const pointer_iterator<SourceT, Tag> &p) {
+			return pointer_iterator<SourceT, Tag>(p);
+		}
+		pointer_iterator operator=(pointer_iterator<SourceT, Tag> &&p) {
+			return pointer_iterator<SourceT, Tag>(p);
+		}
+		pointer_iterator       begin()  const { return pointer_iterator{first, size}; }
+		const pointer_iterator cbegin() const { return pointer_iterator{first, size}; }
+		pointer_iterator       end()    const { return pointer_iterator{first + size, size}; }
+		const pointer_iterator cend()   const { return pointer_iterator{first + size, size}; }
+		friend class boost::iterator_core_access;
+		void increment() { ++it; }
+		void decrement() { --it; }
+		void advance(ptrdiff_t n) { it += n; }
+		ptrdiff_t distance_to(const pointer_iterator &other) { return other.it - it; }
+		bool equal(const pointer_iterator &other) const { return it == other.it; }
+		SourceT & dereference() const { return *this->it; }
+		SourceT *it;
+		SourceT * const first;
+		size_t size;
+	};
 
-	template<typename func>
-	void for_each_base(ViewLayer * const view_layer, func f) {
-		for (Base *base = static_cast<Base *>(view_layer->object_bases.first);
-		     base; base = base->next)
-			if (!G.is_break && !f(base)) // If we should break, or f return false (error)
-				break;
-		G.is_break = false;
-	}
+	// TODO soemeone Document CTRP
+	template<typename SourceT, typename ResT, typename CRTP,
+	         typename Base = pointer_iterator<SourceT>,
+	         typename Tag = typename std::iterator_traits<Base>::iterator_category>
+	struct dereference_iterator
+		: public boost::iterator_adaptor<dereference_iterator<SourceT, ResT, CRTP, Base>,
+		                                 Base, ResT, Tag, ResT> {
+		using dereference_iterator_ = dereference_iterator<SourceT, ResT, CRTP, Base>;
+		dereference_iterator() : dereference_iterator::iterator_adaptor_(), crtp(nullptr) {}
+		dereference_iterator(const dereference_iterator &di, CRTP *crtp)
+			: dereference_iterator::iterator_adaptor_(di.base()), crtp(crtp) {}
+		dereference_iterator(dereference_iterator &&di, CRTP *crtp)
+			: dereference_iterator::iterator_adaptor_(di.base()), crtp(crtp) {}
+		dereference_iterator(Base const & other, CRTP *crtp)
+			: dereference_iterator::iterator_adaptor_(other), crtp(crtp) {}
+		template<typename Size = size_t>
+		explicit dereference_iterator(SourceT *p, Size size, CRTP *crtp)
+			: dereference_iterator(Base{p, (size_t) size}, crtp) {}
+		explicit dereference_iterator(SourceT *p, CRTP *crtp) // For list_iterator
+			: dereference_iterator(Base{p}, crtp) {}
+		dereference_iterator       begin()  const { return {this->base().begin(), crtp}; }
+		const dereference_iterator cbegin() const { return {this->base().cbegin(), crtp}; }
+		dereference_iterator       end()    const { return {this->base().end(), crtp}; }
+		const dereference_iterator cend()   const { return {this->base().cend(), crtp}; }
+		friend class boost::iterator_core_access;
+		ResT dereference() const { return crtp->dereference(this->base()); }
+		CRTP *crtp;
+	};
 
-	template<typename func>
-	void for_each_vertex(const Mesh * const mesh, func f) {
-		// TODO someone Should this use iterators? Unsure if those are only for BMesh
-		for (int i = 0, e = mesh->totvert; i < e; ++i)
-			f(i, mesh->mvert[i]);
-	}
+	template<typename SourceT, typename ResT = SourceT &,
+	         typename Tag = std::bidirectional_iterator_tag>
+	struct list_iterator : public boost::iterator_adaptor<list_iterator<SourceT, ResT, Tag>,
+	                                                      pointer_iterator<SourceT, Tag>, ResT, Tag, ResT> {
+		list_iterator() : list_iterator::iterator_adaptor_() {}
+		list_iterator(const pointer_iterator<SourceT, Tag> & other)
+			: list_iterator::iterator_adaptor_(other), first(other.first) {}
+		explicit list_iterator(SourceT *first)
+			: list_iterator::iterator_adaptor_(pointer_iterator<SourceT, Tag>{first}),
+			  first(first) {}
+		list_iterator

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list