[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20427] branches/soc-2009-kazanbas/release /scripts/export_obj-2.5.py: Start OBJ exporter conversion.
Arystanbek Dyussenov
arystan.d at gmail.com
Tue May 26 18:22:00 CEST 2009
Revision: 20427
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20427
Author: kazanbas
Date: 2009-05-26 18:22:00 +0200 (Tue, 26 May 2009)
Log Message:
-----------
Start OBJ exporter conversion.
Just copied export_obj.py to export_obj-2.5.py leaving old one for
reference. Once conversion is done, the new one will replace it.
Added Paths:
-----------
branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py
Added: branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py
===================================================================
--- branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py (rev 0)
+++ branches/soc-2009-kazanbas/release/scripts/export_obj-2.5.py 2009-05-26 16:22:00 UTC (rev 20427)
@@ -0,0 +1,791 @@
+#!BPY
+
+"""
+Name: 'Wavefront (.obj)...'
+Blender: 248
+Group: 'Export'
+Tooltip: 'Save a Wavefront OBJ File'
+"""
+
+__author__ = "Campbell Barton, Jiri Hnidek"
+__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
+__version__ = "1.2"
+
+__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 Blender
+# from Blender import Mesh, Scene, Window, sys, Image, Draw
+# import BPyMesh
+# import BPyObject
+# import BPySys
+# import BPyMessages
+
+# 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(' ', '_')
+
+# A Dict of Materials
+# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
+MTL_DICT = {}
+
+def write_mtl(filename):
+
+ world = Blender.World.GetCurrent()
+ if world:
+ worldAmb = world.getAmb()
+ else:
+ worldAmb = (0,0,0) # Default value
+
+ file = open(filename, "w")
+ 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.iteritems():
+
+ # 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.getHardness()-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's
+ file.write('Ka %.6f %.6f %.6f\n' % tuple([c*mat.amb for c in worldAmb]) ) # Ambient, uses mirror colour,
+ file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.ref for c in mat.rgbCol]) ) # Diffuse
+ file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.spec for c in mat.specCol]) ) # 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.getMode() & Blender.Material.Modes['SHADELESS']:
+ file.write('illum 0\n') # ignore lighting
+ elif mat.getSpec() == 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.getTextures():
+ if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
+ try:
+ filename = mtex.tex.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] != sys.sep:
+ dest_dir += sys.sep
+
+ # Get unique image names
+ uniqueImages = {}
+ for matname, mat, image in MTL_DICT.itervalues(): # 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.getTextures():
+ if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
+ image_tex = mtex.tex.image
+ if image_tex:
+ try:
+ uniqueImages[image_tex] = image_tex
+ except:
+ pass
+
+ # Now copy images
+ copyCount = 0
+
+ for bImage in uniqueImages.itervalues():
+ image_path = sys.expandpath(bImage.filename)
+ if sys.exists(image_path):
+ # Make a name for the target path.
+ dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
+ if not 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
+
+def write(filename, objects,\
+EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\
+EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\
+EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\
+EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False):
+ '''
+ Basic write function. The context and options must be alredy set
+ This can be accessed externaly
+ eg.
+ write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
+ '''
+
+ def veckey3d(v):
+ return round(v.x, 6), round(v.y, 6), round(v.z, 6)
+
+ def veckey2d(v):
+ return round(v.x, 6), round(v.y, 6)
+
+ print 'OBJ Export path: "%s"' % filename
+ temp_mesh_name = '~tmp-mesh'
+
+ time1 = sys.time()
+ scn = Scene.GetCurrent()
+
+ file = open(filename, "w")
+
+ # Write Header
+ file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
+ file.write('# www.blender3d.org\n')
+
+ # Tell the obj file what material file to use.
+ if EXPORT_MTL:
+ mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
+ file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
+
+ # Get the container mesh. - used for applying modifiers and non mesh objects.
+ containerMesh = meshName = tempMesh = None
+ for meshName in Blender.NMesh.GetNames():
+ if meshName.startswith(temp_mesh_name):
+ tempMesh = Mesh.Get(meshName)
+ if not tempMesh.users:
+ containerMesh = tempMesh
+ if not containerMesh:
+ containerMesh = Mesh.New(temp_mesh_name)
+
+ if EXPORT_ROTX90:
+ mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x')
+
+ del meshName
+ del tempMesh
+
+ # Initialize totals, these are updated each object
+ totverts = totuvco = totno = 1
+
+ face_vert_index = 1
+
+ globalNormals = {}
+
+ # Get all meshs
+ for ob_main in objects:
+ for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
+ # Will work for non meshes now! :)
+ # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
+ me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn)
+ if not me:
+ continue
+
+ if EXPORT_UV:
+ faceuv= me.faceUV
+ else:
+ faceuv = False
+
+ # We have a valid mesh
+ if EXPORT_TRI and me.faces:
+ # Add a dummy object to it.
+ has_quads = False
+ for f in me.faces:
+ if len(f) == 4:
+ has_quads = True
+ break
+
+ if has_quads:
+ oldmode = Mesh.Mode()
+ Mesh.Mode(Mesh.SelectModes['FACE'])
+
+ me.sel = True
+ tempob = scn.objects.new(me)
+ me.quadToTriangle(0) # more=0 shortest length
+ oldmode = Mesh.Mode(oldmode)
+ scn.objects.unlink(tempob)
+
+ Mesh.Mode(oldmode)
+
+ # Make our own list so it can be sorted to reduce context switching
+ faces = [ f for f in me.faces ]
+
+ if EXPORT_EDGES:
+ edges = me.edges
+ else:
+ edges = []
+
+ if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write
+ continue # dont bother with this mesh.
+
+ if EXPORT_ROTX90:
+ me.transform(ob_mat*mat_xrot90)
+ else:
+ me.transform(ob_mat)
+
+ # High Quality Normals
+ if EXPORT_NORMALS and faces:
+ if EXPORT_NORMALS_HQ:
+ BPyMesh.meshCalcNormals(me)
+ else:
+ # transforming normals is incorrect
+ # when the matrix is scaled,
+ # better to recalculate them
+ me.calcNormals()
+
+ # # Crash Blender
+ #materials = me.getMaterials(1) # 1 == will return None in the list.
+ materials = me.materials
+
+ materialNames = []
+ materialItems = materials[:]
+ if materials:
+ for mat in materials:
+ if mat: # !=None
+ materialNames.append(mat.name)
+ else:
+ materialNames.append(None)
+ # Cant use LC because some materials are None.
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list