[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21219] branches/soc-2009-kazanbas: OBJ exporter working (Python 3.0), but needs testing and fixing.

Arystanbek Dyussenov arystan.d at gmail.com
Sun Jun 28 15:29:03 CEST 2009


Revision: 21219
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21219
Author:   kazanbas
Date:     2009-06-28 15:29:03 +0200 (Sun, 28 Jun 2009)

Log Message:
-----------
OBJ exporter working (Python 3.0), but needs testing and fixing.
Current issues:
- NURBS - needs API additions
- "all scenes" export - cannot switch scene in bpy
- normal calculation, disabled
- duplis - need testing, only dupliverts tested
- matrix problem
- UI, 18 options currently don't fit into filesel panel, will do manual lay out once it's available
- probably others...

BPY:
- made operator "execute" method required to avoid crash
- added bpy.sys module which replicates old "sys" module

API:
- replaced create_*_mesh with a single create_mesh accepting type parameter
- added Mesh.create_copy to create a copy of a mesh with 0 users

Ran `dos2unix` on source/blender/python/SConscript

Modified Paths:
--------------
    branches/soc-2009-kazanbas/release/io/export_ply.py
    branches/soc-2009-kazanbas/release/scripts/3ds_export.py
    branches/soc-2009-kazanbas/release/ui/space_script.py
    branches/soc-2009-kazanbas/source/blender/makesrna/intern/rna_mesh_api.c
    branches/soc-2009-kazanbas/source/blender/makesrna/intern/rna_object_api.c
    branches/soc-2009-kazanbas/source/blender/python/SConscript
    branches/soc-2009-kazanbas/source/blender/python/intern/bpy_interface.c
    branches/soc-2009-kazanbas/source/blender/python/intern/bpy_operator_wrap.c
    branches/soc-2009-kazanbas/source/blender/python/intern/bpy_rna.c

Added Paths:
-----------
    branches/soc-2009-kazanbas/release/io/export_obj.py
    branches/soc-2009-kazanbas/source/blender/python/intern/bpy_sys.c
    branches/soc-2009-kazanbas/source/blender/python/intern/bpy_sys.h

Removed Paths:
-------------
    branches/soc-2009-kazanbas/release/io/export_obj.py
    branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py

Deleted: branches/soc-2009-kazanbas/release/io/export_obj.py
===================================================================
--- branches/soc-2009-kazanbas/release/io/export_obj.py	2009-06-28 13:27:06 UTC (rev 21218)
+++ branches/soc-2009-kazanbas/release/io/export_obj.py	2009-06-28 13:29:03 UTC (rev 21219)
@@ -1,83 +0,0 @@
-import bpy
-
-def write_obj(filepath, scene, ob):
-	out = open(filepath, 'w')
-
-	# create a temporary mesh
-	mesh = ob.create_render_mesh(scene)
-
-	# for vert in mesh.verts:
-	# ^ iterating that way doesn't work atm for some reason
-
-	for i in range(len(mesh.verts)):
-		vert = mesh.verts[i]
-		out.write('v {0} {1} {2}\n'.format(vert.co[0], vert.co[1], vert.co[2]))
-	
-	for i in range(len(mesh.faces)):
-		face = mesh.faces[i]
-		out.write('f')
-
-		# but this works
-		for index in face.verts:
-			out.write(' {0}'.format(index + 1))
-		out.write('\n')
-
-	# delete mesh gain
-	bpy.data.remove_mesh(mesh)
-
-	out.close()
-	
-class SCRIPT_OT_export_obj(bpy.types.Operator):
-	'''A very basic OBJ exporter, writes only active object's mesh.'''
-
-	__label__ = 'Export OBJ'
-	
-	# List of operator properties, the attributes will be assigned
-	# to the class instance from the operator settings before calling.
-	__props__ = [
-		bpy.props.StringProperty(attr="filename", name="filename")
-		]
-
-	def debug(self, message):
-		print("{0}: {1}".format(self.__class__.__name__, message))
-
-	def execute_(self, context):
-		self.debug("exec")
-		self.debug("filename = " + self.filename)
-
-		act = context.active_object
-
-		if act.type == 'MESH':
-			write_obj(self.filename, context.scene, act)
-		else:
-			self.debug("Active object is not a MESH.")
-
-		# XXX errors are silenced for some reason
-#		raise Exception("oops!")
-
-		return ('FINISHED',)
-
-	def execute(self, context):
-		self.debug("exec")
-		
-		act = context.active_object
-
-		act.create_dupli_list()
-		print("{0} has {1} dupli objects".format(act.name, len(act.dupli_list)))
-
-		act.free_dupli_list()
-
-		return ('FINISHED',)
-	
-	def invoke(self, context, event):
-		self.debug("invoke")
-		wm = context.manager
-		wm.add_fileselect(self.__operator__)
-		return ('RUNNING_MODAL',)
-	
-	def poll(self, context): # poll isnt working yet
-		self.debug("poll")
-		return True
-
-bpy.ops.add(SCRIPT_OT_export_obj)
-

Copied: branches/soc-2009-kazanbas/release/io/export_obj.py (from rev 21172, branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py)
===================================================================
--- branches/soc-2009-kazanbas/release/io/export_obj.py	                        (rev 0)
+++ branches/soc-2009-kazanbas/release/io/export_obj.py	2009-06-28 13:29:03 UTC (rev 21219)
@@ -0,0 +1,961 @@
+#!BPY
+
+"""
+Name: 'Wavefront (.obj)...'
+Blender: 248
+Group: 'Export'
+Tooltip: 'Save a Wavefront OBJ File'
+"""
+
+__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
+__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
+__version__ = "1.21"
+
+__bpydoc__ = """\
+This script is an exporter to OBJ file format.
+
+Usage:
+
+Select the objects you wish to export and run this script from "File->Export" menu.
+Selecting the default options from the popup box will be good in most cases.
+All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
+will be exported as mesh data.
+"""
+
+
+# --------------------------------------------------------------------------
+# OBJ Export v1.1 by Campbell Barton (AKA Ideasman)
+# --------------------------------------------------------------------------
+# ***** 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., 59 Temple Place - Suite 330, Boston, MA	 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+
+import bpy
+import os # os.sep
+import Mathutils
+
+# Returns a tuple - path,extension.
+# 'hello.obj' >	 ('hello', '.obj')
+def splitExt(path):
+	dotidx = path.rfind('.')
+	if dotidx == -1:
+		return path, ''
+	else:
+		return path[:dotidx], path[dotidx:] 
+
+def fixName(name):
+	if name == None:
+		return 'None'
+	else:
+		return name.replace(' ', '_')
+
+
+# this used to be in BPySys module
+# frankly, I don't understand how it works
+def BPySys_cleanName(name):
+
+	v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
+
+	invalid = ''.join([chr(i) for i in v])
+
+	for ch in invalid:
+		name = name.replace(ch, '_')
+	return name
+
+# A Dict of Materials
+# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
+MTL_DICT = {} 
+
+def write_mtl(scene, filename):
+
+	world = scene.world
+	worldAmb = world.ambient_color
+
+	file = open(filename, "w")
+	# XXX
+#	file.write('# Blender3D MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1])
+	file.write('# Material Count: %i\n' % len(MTL_DICT))
+	# Write material/image combinations we have used.
+	for key, (mtl_mat_name, mat, img) in MTL_DICT.items():
+		
+		# Get the Blender data for the material and the image.
+		# Having an image named None will make a bug, dont do it :)
+		
+		file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
+		
+		if mat:
+			file.write('Ns %.6f\n' % ((mat.specular_hardness-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's
+			file.write('Ka %.6f %.6f %.6f\n' %	tuple([c*mat.ambient for c in worldAmb])  ) # Ambient, uses mirror colour,
+			file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.diffuse_reflection for c in mat.diffuse_color]) ) # Diffuse
+			file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.specular_reflection for c in mat.specular_color]) ) # Specular
+			file.write('Ni %.6f\n' % mat.ior) # Refraction index
+			file.write('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve)
+
+			# 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
+			if mat.shadeless:
+				file.write('illum 0\n') # ignore lighting
+			elif mat.specular_reflection == 0:
+				file.write('illum 1\n') # no specular.
+			else:
+				file.write('illum 2\n') # light normaly	
+		
+		else:
+			#write a dummy material here?
+			file.write('Ns 0\n')
+			file.write('Ka %.6f %.6f %.6f\n' %	tuple([c for c in worldAmb])  ) # Ambient, uses mirror colour,
+			file.write('Kd 0.8 0.8 0.8\n')
+			file.write('Ks 0.8 0.8 0.8\n')
+			file.write('d 1\n') # No alpha
+			file.write('illum 2\n') # light normaly
+		
+		# Write images!
+		if img:	 # We have an image on the face!
+			file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image			
+		
+		elif mat: # No face image. if we havea material search for MTex image.
+			for mtex in mat.textures:
+				if mtex and mtex.texure.type == 'IMAGE':
+					try:
+						filename = mtex.texture.image.filename.split('\\')[-1].split('/')[-1]
+						file.write('map_Kd %s\n' % filename) # Diffuse mapping image
+						break
+					except:
+						# Texture has no image though its an image type, best ignore.
+						pass
+		
+		file.write('\n\n')
+	
+	file.close()
+
+def copy_file(source, dest):
+	file = open(source, 'rb')
+	data = file.read()
+	file.close()
+	
+	file = open(dest, 'wb')
+	file.write(data)
+	file.close()
+
+
+def copy_images(dest_dir):
+	if dest_dir[-1] != os.sep:
+		dest_dir += os.sep
+#	if dest_dir[-1] != sys.sep:
+#		dest_dir += sys.sep
+	
+	# Get unique image names
+	uniqueImages = {}
+	for matname, mat, image in MTL_DICT.values(): # Only use image name
+		# Get Texface images
+		if image:
+			uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default.
+		
+		# Get MTex images
+		if mat:
+			for mtex in mat.textures:
+				if mtex and mtex.texture.type == 'IMAGE':
+					image_tex = mtex.texture.image
+					if image_tex:
+						try:
+							uniqueImages[image_tex] = image_tex
+						except:
+							pass
+	
+	# Now copy images
+	copyCount = 0
+	
+	for bImage in uniqueImages.values():
+		image_path = bpy.sys.expandpath(bImage.filename)
+		if bpy.sys.exists(image_path):
+			# Make a name for the target path.
+			dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
+			if not bpy.sys.exists(dest_image_path): # Image isnt alredy there
+				print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
+				copy_file(image_path, dest_image_path)
+				copyCount+=1
+
+	print('\tCopied %d images' % copyCount)
+
+# XXX not converted
+def test_nurbs_compat(ob):
+	if ob.type != 'CURVE':
+		return False
+	
+	for nu in ob.data.curves:
+		if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
+			return True
+
+#	for nu in ob.data:
+#		if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
+#			return True
+	
+	return False
+
+# XXX not converted
+def write_nurb(file, ob, ob_mat):
+	tot_verts = 0
+	cu = ob.data
+	
+	# use negative indices
+	Vector = Blender.Mathutils.Vector
+	for nu in cu:
+		
+		if nu.type==0:		DEG_ORDER_U = 1
+		else:				DEG_ORDER_U = nu.orderU-1  # Tested to be correct
+		
+		if nu.type==1:
+			print("\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported")
+			continue
+		
+		if nu.knotsV:

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list