[Bf-blender-cvs] [1cd052f469f] soc-2019-fast-io: [Fast import/export] OBJ exports materials and animations
Hugo Sales
noreply at git.blender.org
Sun Jun 23 15:58:03 CEST 2019
Commit: 1cd052f469f17c9b366f3a0301c459b8c50869b0
Author: Hugo Sales
Date: Sun Jun 23 14:57:44 2019 +0100
Branches: soc-2019-fast-io
https://developer.blender.org/rB1cd052f469f17c9b366f3a0301c459b8c50869b0
[Fast import/export] OBJ exports materials and animations
===================================================================
A release/scripts/modules/obj_export.py
M source/blender/editors/io/CMakeLists.txt
M source/blender/editors/io/intern/iterators.hpp
M source/blender/editors/io/intern/obj.cpp
M source/blender/editors/io/io_common.c
M source/blender/editors/io/io_common.h
===================================================================
diff --git a/release/scripts/modules/obj_export.py b/release/scripts/modules/obj_export.py
new file mode 100644
index 00000000000..9125aa85c76
--- /dev/null
+++ b/release/scripts/modules/obj_export.py
@@ -0,0 +1,130 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import os
+
+import bpy
+from mathutils import Matrix, Vector, Color
+from bpy_extras import io_utils, node_shader_utils
+
+def write_mtl(filepath, materials):
+ C = bpy.context
+ scene = C.scene
+ world = scene.world
+ world_amb = Color((0.8, 0.8, 0.8))
+
+ source_dir = os.path.dirname(bpy.data.filepath)
+ dest_dir = os.path.dirname(filepath)
+
+ with open(filepath, "w", encoding="utf8", newline="\n") as f:
+ fw = f.write
+
+ fw('# Blender MTL File: %r\n' % (os.path.basename(bpy.data.filepath) or "None"))
+ fw('# Material Count: %i\n' % len(materials))
+
+ for material in materials:
+ fw('newmtl %s\n' % material)
+ mat = bpy.data.materials[material]
+ mat_wrap = node_shader_utils.PrincipledBSDFWrapper(mat) if mat else None
+
+ if mat_wrap:
+ use_mirror = mat_wrap.metallic != 0.0
+ use_transparency = mat_wrap.alpha != 1.0
+
+ # XXX Totally empirical conversion, trying to adapt it
+ # (from 1.0 - 0.0 Principled BSDF range to 0.0 - 900.0 OBJ specular exponent range)...
+ spec = (1.0 - mat_wrap.roughness) * 30
+ spec *= spec
+ fw('Ns %.6f\n' % spec)
+
+ # Ambient
+ if use_mirror:
+ fw('Ka %.6f %.6f %.6f\n' % (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic))
+ else:
+ fw('Ka %.6f %.6f %.6f\n' % (1.0, 1.0, 1.0))
+ fw('Kd %.6f %.6f %.6f\n' % mat_wrap.base_color[:3]) # Diffuse
+ # XXX TODO Find a way to handle tint and diffuse color, in a consistent way with import...
+ fw('Ks %.6f %.6f %.6f\n' % (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular)) # Specular
+ # Emission, not in original MTL standard but seems pretty common, see T45766.
+ fw('Ke 0.0 0.0 0.0\n') # XXX Not supported by current Principled-based shader.
+ fw('Ni %.6f\n' % mat_wrap.ior) # Refraction index
+ fw('d %.6f\n' % mat_wrap.alpha) # Alpha (obj uses 'd' for dissolve)
+
+ # See http://en.wikipedia.org/wiki/Wavefront_.obj_file for whole list of values...
+ # Note that mapping is rather fuzzy sometimes, trying to do our best here.
+ if mat_wrap.specular == 0:
+ fw('illum 1\n') # no specular.
+ elif use_mirror:
+ if use_transparency:
+ fw('illum 6\n') # Reflection, Transparency, Ray trace
+ else:
+ fw('illum 3\n') # Reflection and Ray trace
+ elif use_transparency:
+ fw('illum 9\n') # 'Glass' transparency and no Ray trace reflection... fuzzy matching, but...
+ else:
+ fw('illum 2\n') # light normally
+
+ #### And now, the image textures...
+ image_map = {
+ "map_Kd": "base_color_texture",
+ "map_Ka": None, # ambient...
+ "map_Ks": "specular_texture",
+ "map_Ns": "roughness_texture",
+ "map_d": "alpha_texture",
+ "map_Tr": None, # transmission roughness?
+ "map_Bump": "normalmap_texture",
+ "disp": None, # displacement...
+ "refl": "metallic_texture",
+ "map_Ke": None # emission...
+ }
+
+ for key, mat_wrap_key in sorted(image_map.items()):
+ if mat_wrap_key is None:
+ continue
+ tex_wrap = getattr(mat_wrap, mat_wrap_key, None)
+ if tex_wrap is None:
+ continue
+ image = tex_wrap.image
+ if image is None:
+ continue
+
+ filepath = io_utils.path_reference(image.filepath, source_dir, dest_dir,
+ 'AUTO', "", None, image.library)
+ options = []
+ if key == "map_Bump":
+ if mat_wrap.normalmap_strength != 1.0:
+ options.append('-bm %.6f' % mat_wrap.normalmap_strength)
+ if tex_wrap.translation != Vector((0.0, 0.0, 0.0)):
+ options.append('-o %.6f %.6f %.6f' % tex_wrap.translation[:])
+ if tex_wrap.scale != Vector((1.0, 1.0, 1.0)):
+ options.append('-s %.6f %.6f %.6f' % tex_wrap.scale[:])
+ if options:
+ fw('%s %s %s\n' % (key, " ".join(options), repr(filepath)[1:-1]))
+ else:
+ fw('%s %s\n' % (key, repr(filepath)[1:-1]))
+
+ else:
+ # Write a dummy material here?
+ fw('Ns 500\n')
+ fw('Ka 0.8 0.8 0.8\n') # Ambient
+ fw('Kd 0.8 0.8 0.8\n') # Diffuse
+ fw('Ks 0.8 0.8 0.8\n') # Specular
+ fw('d 1\n') # No alpha
+ fw('illum 2\n') # light normally
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 35b3f892ac6..a7f6d77dfc4 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -88,6 +88,11 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_PYTHON)
+ list(APPEND INC ../../python)
+ add_definitions(-DWITH_PYTHON)
+endif()
+
if(CMAKE_COMPILER_IS_GNUCC)
add_definitions(-Wfatal-errors) # Temporary, for development
endif()
diff --git a/source/blender/editors/io/intern/iterators.hpp b/source/blender/editors/io/intern/iterators.hpp
index cbd825d37f4..422c658d2f9 100644
--- a/source/blender/editors/io/intern/iterators.hpp
+++ b/source/blender/editors/io/intern/iterators.hpp
@@ -10,6 +10,7 @@ extern "C" {
#include "BKE_library.h"
#include "BKE_customdata.h"
#include "BKE_scene.h"
+#include "BKE_material.h"
#include "DNA_layer_types.h"
#include "DNA_meshdata_types.h"
@@ -43,6 +44,7 @@ struct pointer_iterator_base {
using iterator_category = Tag;
pointer_iterator_base(pointer p, size_t size) : first(p), curr(p), size(size) {}
pointer_iterator_base(const pointer_iterator_base &pib) : first(pib.first), curr(pib.curr), size(pib.size) {}
+ // Conversion to base pointer
operator pointer() const { return curr; }
pointer_iterator_base &operator=(const pointer_iterator_base &p) {
// Placement new: construct a new object in the position of `this`
@@ -55,8 +57,8 @@ struct pointer_iterator_base {
pointer_iterator_base & operator++() { ++curr; return *this; }
pointer_iterator_base & operator--() { --curr; return *this; }
pointer_iterator_base & operator+(difference_type n) { curr += n; return *this; }
- ptrdiff_t operator-(const pointer_iterator_base &other) const { return other.curr - curr; }
- bool operator==(const pointer_iterator_base &other) const { return curr == other.curr; }
+ difference_type operator-(const pointer_iterator_base &other) const { return other.curr - curr; }
+ bool operator==(const pointer_iterator_base &other) const { return curr == other.curr; }
pointer first;
pointer curr;
size_t size;
@@ -82,6 +84,14 @@ struct list_iterator : pointer_iterator_base<SourceT, Tag> {
inline const ResT operator*() const { return *this->curr; }
};
+// Represents an offset into an array (base for iterators like material_iter)
+template<typename T>
+struct offset_iterator : pointer_iterator_base<T, std::random_access_iterator_tag> {
+ offset_iterator(size_t size)
+ : pointer_iterator_base<T, std::random_access_iterator_tag>(0, size) {}
+ size_t offset() const { return ((size_t) this->curr) / sizeof(T); }
+};
+
// Iterator over the polygons of a mesh
struct poly_iter : pointer_iterator<MPoly> {
poly_iter(const Mesh *const m) : pointer_iterator(m->mpoly, m->totpoly) {}
@@ -191,6 +201,25 @@ struct loop_of_poly_iter : pointer_iterator<MLoop> {
// loop_of_poly_iter(pointer_iterator &&p) : pointer_iterator(std::move(p)) {}
};
+struct material_iter : offset_iterator<Material *> {
+ material_iter(const Object * const ob)
+ : offset_iterator(ob->totcol), ob(ob), mdata(*give_matarar((Object *) ob)) {}
+ material_iter begin() const { return material_iter(ob); }
+ material_iter end() const { material_iter mi(ob); mi.curr = mi.first + mi.size; return mi; }
+ const Material * operator*() {
+ const size_t off = offset();
+ if (ob->matbits && ob->matbits[off]) {
+ // In Object
+ return ob->mat[off];
+ } else {
+ // In Data
+ return mdata[off];
+ }
+ }
+ const Object * const ob;
+ const Material * const * const mdata;
+};
+
// Iterator over the UVs of a mesh (as `const std::array<float, 2>`)
struct uv_iter : pointer_iterator_base<MLoopUV> {
uv_iter(const Mesh *const m) : pointer_iterator_base(m->mloopuv, m->totloop) {}
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list