2009-11-01 15:21:20 +00:00
# ##### 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 LICENSE BLOCK #####
2006-09-04 04:23:55 +00:00
2009-05-13 00:20:14 +00:00
__author__ = " Campbell Barton " , " Jiri Hnidek " , " Paolo Ciccone "
2008-10-19 15:53:22 +00:00
__url__ = [ ' http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj ' , ' blender.org ' , ' blenderartists.org ' ]
2009-09-29 15:27:00 +00:00
__version__ = " 2.11 "
2006-09-04 04:23:55 +00:00
__bpydoc__ = """ \
2006-09-25 05:12:37 +00:00
This script imports a Wavefront OBJ files to Blender .
2006-09-04 04:23:55 +00:00
Usage :
Run this script from " File->Import " menu and then load the desired OBJ file .
2006-09-25 05:12:37 +00:00
Note , This loads mesh objects and materials only , nurbs and curves are not supported .
2006-09-04 04:23:55 +00:00
"""
2007-02-14 01:03:32 +00:00
# ***** BEGIN GPL LICENSE BLOCK *****
#
2009-09-29 15:27:00 +00:00
# Script copyright (C) Campbell J Barton 2007
2007-02-14 01:03:32 +00:00
#
# 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 *****
# --------------------------------------------------------------------------
2009-09-29 15:27:00 +00:00
import os
import time
2007-03-27 14:49:37 +00:00
import bpy
2009-09-29 15:27:00 +00:00
import Mathutils
import Geometry
2006-09-04 04:23:55 +00:00
2009-09-29 15:27:00 +00:00
# from Blender import Mesh, Draw, Window, Texture, Material, sys
# # import BPyMesh
# import BPyImage
# import BPyMessages
# try: import os
# except: os= False
2006-11-02 17:42:30 +00:00
2006-09-25 05:12:37 +00:00
# Generic path functions
2006-09-04 04:23:55 +00:00
def stripFile ( path ) :
''' Return directory, where the file is '''
lastSlash = max ( path . rfind ( ' \\ ' ) , path . rfind ( ' / ' ) )
if lastSlash != - 1 :
path = path [ : lastSlash ]
2009-09-29 15:27:00 +00:00
return ' %s %s ' % ( path , os . sep )
# return '%s%s' % (path, sys.sep)
2006-09-04 04:23:55 +00:00
def stripPath ( path ) :
2006-09-25 05:12:37 +00:00
''' Strips the slashes from the back of a string '''
2006-09-04 04:23:55 +00:00
return path . split ( ' / ' ) [ - 1 ] . split ( ' \\ ' ) [ - 1 ]
def stripExt ( name ) : # name is a string
''' Strips the prefix off the name before writing '''
index = name . rfind ( ' . ' )
if index != - 1 :
return name [ : index ]
else :
return name
# end path funcs
2009-09-29 15:27:00 +00:00
def unpack_list ( list_of_tuples ) :
l = [ ]
for t in list_of_tuples :
l . extend ( t )
return l
# same as above except that it adds 0 for triangle faces
def unpack_face_list ( list_of_tuples ) :
l = [ ]
for t in list_of_tuples :
face = [ i for i in t ]
2006-09-25 05:12:37 +00:00
2009-09-29 15:27:00 +00:00
if len ( face ) != 3 and len ( face ) != 4 :
raise RuntimeError ( " {0} vertices in face. " . format ( len ( face ) ) )
# rotate indices if the 4th is 0
if len ( face ) == 4 and face [ 3 ] == 0 :
face = [ face [ 3 ] , face [ 0 ] , face [ 1 ] , face [ 2 ] ]
if len ( face ) == 3 :
face . append ( 0 )
l . extend ( face )
return l
def BPyMesh_ngon ( from_data , indices , PREF_FIX_LOOPS = True ) :
'''
Takes a polyline of indices ( fgon )
and returns a list of face indicie lists .
Designed to be used for importers that need indices for an fgon to create from existing verts .
from_data : either a mesh , or a list / tuple of vectors .
indices : a list of indicies to use this list is the ordered closed polyline to fill , and can be a subset of the data given .
PREF_FIX_LOOPS : If this is enabled polylines that use loops to make multiple polylines are delt with correctly .
'''
if not set : # Need sets for this, otherwise do a normal fill.
PREF_FIX_LOOPS = False
Vector = Mathutils . Vector
if not indices :
return [ ]
# return []
def rvec ( co ) : return round ( co . x , 6 ) , round ( co . y , 6 ) , round ( co . z , 6 )
def mlen ( co ) : return abs ( co [ 0 ] ) + abs ( co [ 1 ] ) + abs ( co [ 2 ] ) # manhatten length of a vector, faster then length
def vert_treplet ( v , i ) :
return v , rvec ( v ) , i , mlen ( v )
def ed_key_mlen ( v1 , v2 ) :
if v1 [ 3 ] > v2 [ 3 ] :
return v2 [ 1 ] , v1 [ 1 ]
else :
return v1 [ 1 ] , v2 [ 1 ]
if not PREF_FIX_LOOPS :
'''
Normal single concave loop filling
'''
if type ( from_data ) in ( tuple , list ) :
verts = [ Vector ( from_data [ i ] ) for ii , i in enumerate ( indices ) ]
else :
verts = [ from_data . verts [ i ] . co for ii , i in enumerate ( indices ) ]
for i in range ( len ( verts ) - 1 , 0 , - 1 ) : # same as reversed(xrange(1, len(verts))):
if verts [ i ] [ 1 ] == verts [ i - 1 ] [ 0 ] :
verts . pop ( i - 1 )
fill = Geometry . PolyFill ( [ verts ] )
else :
'''
Seperate this loop into multiple loops be finding edges that are used twice
This is used by lightwave LWO files a lot
'''
if type ( from_data ) in ( tuple , list ) :
verts = [ vert_treplet ( Vector ( from_data [ i ] ) , ii ) for ii , i in enumerate ( indices ) ]
else :
verts = [ vert_treplet ( from_data . verts [ i ] . co , ii ) for ii , i in enumerate ( indices ) ]
edges = [ ( i , i - 1 ) for i in range ( len ( verts ) ) ]
if edges :
edges [ 0 ] = ( 0 , len ( verts ) - 1 )
if not verts :
return [ ]
edges_used = set ( )
edges_doubles = set ( )
# We need to check if any edges are used twice location based.
for ed in edges :
edkey = ed_key_mlen ( verts [ ed [ 0 ] ] , verts [ ed [ 1 ] ] )
if edkey in edges_used :
edges_doubles . add ( edkey )
else :
edges_used . add ( edkey )
# Store a list of unconnected loop segments split by double edges.
# will join later
loop_segments = [ ]
v_prev = verts [ 0 ]
context_loop = [ v_prev ]
loop_segments = [ context_loop ]
for v in verts :
if v != v_prev :
# Are we crossing an edge we removed?
if ed_key_mlen ( v , v_prev ) in edges_doubles :
context_loop = [ v ]
loop_segments . append ( context_loop )
else :
if context_loop and context_loop [ - 1 ] [ 1 ] == v [ 1 ] :
#raise "as"
pass
else :
context_loop . append ( v )
v_prev = v
# Now join loop segments
def join_seg ( s1 , s2 ) :
if s2 [ - 1 ] [ 1 ] == s1 [ 0 ] [ 1 ] : #
s1 , s2 = s2 , s1
elif s1 [ - 1 ] [ 1 ] == s2 [ 0 ] [ 1 ] :
pass
else :
return False
# If were stuill here s1 and s2 are 2 segments in the same polyline
s1 . pop ( ) # remove the last vert from s1
s1 . extend ( s2 ) # add segment 2 to segment 1
if s1 [ 0 ] [ 1 ] == s1 [ - 1 ] [ 1 ] : # remove endpoints double
s1 . pop ( )
s2 [ : ] = [ ] # Empty this segment s2 so we dont use it again.
return True
joining_segments = True
while joining_segments :
joining_segments = False
segcount = len ( loop_segments )
for j in range ( segcount - 1 , - 1 , - 1 ) : #reversed(range(segcount)):
seg_j = loop_segments [ j ]
if seg_j :
for k in range ( j - 1 , - 1 , - 1 ) : # reversed(range(j)):
if not seg_j :
break
seg_k = loop_segments [ k ]
if seg_k and join_seg ( seg_j , seg_k ) :
joining_segments = True
loop_list = loop_segments
for verts in loop_list :
while verts and verts [ 0 ] [ 1 ] == verts [ - 1 ] [ 1 ] :
verts . pop ( )
loop_list = [ verts for verts in loop_list if len ( verts ) > 2 ]
# DONE DEALING WITH LOOP FIXING
# vert mapping
vert_map = [ None ] * len ( indices )
ii = 0
for verts in loop_list :
if len ( verts ) > 2 :
for i , vert in enumerate ( verts ) :
vert_map [ i + ii ] = vert [ 2 ]
ii + = len ( verts )
fill = Geometry . PolyFill ( [ [ v [ 0 ] for v in loop ] for loop in loop_list ] )
#draw_loops(loop_list)
#raise 'done loop'
# map to original indicies
fill = [ [ vert_map [ i ] for i in reversed ( f ) ] for f in fill ]
if not fill :
print ( ' Warning Cannot scanfill, fallback on a triangle fan. ' )
fill = [ [ 0 , i - 1 , i ] for i in range ( 2 , len ( indices ) ) ]
else :
# Use real scanfill.
# See if its flipped the wrong way.
flip = None
for fi in fill :
if flip != None :
break
for i , vi in enumerate ( fi ) :
if vi == 0 and fi [ i - 1 ] == 1 :
flip = False
break
elif vi == 1 and fi [ i - 1 ] == 0 :
flip = True
break
if not flip :
for i , fi in enumerate ( fill ) :
fill [ i ] = tuple ( [ ii for ii in reversed ( fi ) ] )
return fill
2006-09-25 05:12:37 +00:00
2006-09-04 04:23:55 +00:00
def line_value ( line_split ) :
2006-09-25 05:12:37 +00:00
'''
Returns 1 string represneting the value for this line
None will be returned if theres only 1 word
'''
2006-09-04 04:23:55 +00:00
length = len ( line_split )
if length == 1 :
return None
elif length == 2 :
return line_split [ 1 ]
elif length > 2 :
return ' ' . join ( line_split [ 1 : ] )
2009-09-29 15:27:00 +00:00
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image ( imagepath , dirname ) :
if os . path . exists ( imagepath ) :
return bpy . data . add_image ( imagepath )
variants = [ os . path . join ( dirname , imagepath ) , os . path . join ( dirname , os . path . basename ( imagepath ) ) ]
for path in variants :
if os . path . exists ( path ) :
return bpy . data . add_image ( path )
else :
print ( path , " doesn ' t exist " )
# TODO comprehensiveImageLoad also searched in bpy.config.textureDir
return None
2006-09-20 05:03:53 +00:00
def obj_image_load ( imagepath , DIR , IMAGE_SEARCH ) :
2009-09-29 15:27:00 +00:00
2006-09-20 05:03:53 +00:00
if ' _ ' in imagepath :
2009-09-29 15:27:00 +00:00
image = load_image ( imagepath . replace ( ' _ ' , ' ' ) , DIR )
2006-09-20 05:03:53 +00:00
if image : return image
2009-09-29 15:27:00 +00:00
return load_image ( imagepath , DIR )
# def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
# '''
# Mainly uses comprehensiveImageLoad
# but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
# '''
# if '_' in imagepath:
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# # Did the exporter rename the image?
# image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
# if image: return image
# # Return an image, placeholder if it dosnt exist
# image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
# return image
2006-09-20 05:03:53 +00:00
2006-09-04 04:23:55 +00:00
2006-09-20 05:03:53 +00:00
def create_materials ( filepath , material_libs , unique_materials , unique_material_images , IMAGE_SEARCH ) :
2006-09-25 05:12:37 +00:00
'''
Create all the used materials in this obj ,
assign colors and images to the materials from all referenced material libs
'''
2006-09-04 04:23:55 +00:00
DIR = stripFile ( filepath )
#==================================================================================#
# This function sets textures defined in .mtl file #
#==================================================================================#
def load_material_image ( blender_material , context_material_name , imagepath , type ) :
2009-09-29 15:27:00 +00:00
texture = bpy . data . add_texture ( type )
texture . type = ' IMAGE '
# texture= bpy.data.textures.new(type)
# texture.setType('Image')
2006-09-04 04:23:55 +00:00
# Absolute path - c:\.. etc would work here
2006-09-20 05:03:53 +00:00
image = obj_image_load ( imagepath , DIR , IMAGE_SEARCH )
2009-09-29 15:27:00 +00:00
has_data = image . has_data if image else False
2009-06-29 02:37:44 +00:00
2009-09-29 15:27:00 +00:00
if image :
texture . image = image
2006-10-05 11:15:22 +00:00
2006-09-04 04:23:55 +00:00
# Adds textures for materials (rendering)
if type == ' Kd ' :
2006-11-27 23:59:53 +00:00
if has_data and image . depth == 32 :
2006-10-05 11:15:22 +00:00
# Image has alpha
2009-09-29 15:27:00 +00:00
# XXX bitmask won't work?
blender_material . add_texture ( texture , " UV " , ( " COLOR " , " ALPHA " ) )
texture . mipmap = True
texture . interpolation = True
texture . use_alpha = True
blender_material . z_transparency = True
2006-10-05 11:15:22 +00:00
blender_material . alpha = 0.0
2009-09-29 15:27:00 +00:00
# blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL | Texture.MapTo.ALPHA)
# texture.setImageFlags('MipMap', 'InterPol', 'UseAlpha')
# blender_material.mode |= Material.Modes.ZTRANSP
# blender_material.alpha = 0.0
2006-10-05 11:15:22 +00:00
else :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " COLOR " )
# blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL)
2006-10-05 11:15:22 +00:00
2006-09-04 04:23:55 +00:00
# adds textures to faces (Textured/Alt-Z mode)
# Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
2006-11-27 23:59:53 +00:00
unique_material_images [ context_material_name ] = image , has_data # set the texface image
2006-09-04 04:23:55 +00:00
elif type == ' Ka ' :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " AMBIENT " )
# blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API
2006-09-04 04:23:55 +00:00
elif type == ' Ks ' :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " SPECULARITY " )
# blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
2006-09-04 04:23:55 +00:00
elif type == ' Bump ' :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " NORMAL " )
# blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR)
2006-09-04 04:23:55 +00:00
elif type == ' D ' :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " ALPHA " )
blender_material . z_transparency = True
2006-10-05 11:15:22 +00:00
blender_material . alpha = 0.0
2009-09-29 15:27:00 +00:00
# blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)
# blender_material.mode |= Material.Modes.ZTRANSP
# blender_material.alpha = 0.0
2006-10-05 11:15:22 +00:00
# Todo, unset deffuse material alpha if it has an alpha channel
2006-09-04 04:23:55 +00:00
elif type == ' refl ' :
2009-09-29 15:27:00 +00:00
blender_material . add_texture ( texture , " UV " , " REFLECTION " )
# blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF)
2006-09-04 04:23:55 +00:00
# Add an MTL with the same name as the obj if no MTLs are spesified.
temp_mtl = stripExt ( stripPath ( filepath ) ) + ' .mtl '
2009-09-29 15:27:00 +00:00
if os . path . exists ( DIR + temp_mtl ) and temp_mtl not in material_libs :
# if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
material_libs . append ( temp_mtl )
2006-09-04 04:23:55 +00:00
del temp_mtl
#Create new materials
2009-06-13 09:33:55 +00:00
for name in unique_materials : # .keys()
if name != None :
2009-09-29 15:27:00 +00:00
unique_materials [ name ] = bpy . data . add_material ( name )
# unique_materials[name]= bpy.data.materials.new(name)
2009-06-13 09:33:55 +00:00
unique_material_images [ name ] = None , False # assign None to all material images to start with, add to later.
2006-09-04 04:23:55 +00:00
unique_materials [ None ] = None
2009-06-13 09:33:55 +00:00
unique_material_images [ None ] = None , False
2006-09-04 04:23:55 +00:00
for libname in material_libs :
mtlpath = DIR + libname
2009-09-29 15:27:00 +00:00
if not os . path . exists ( mtlpath ) :
# if not sys.exists(mtlpath):
2006-09-04 04:23:55 +00:00
#print '\tError Missing MTL: "%s"' % mtlpath
pass
else :
#print '\t\tloading mtl: "%s"' % mtlpath
context_material = None
2008-09-25 13:17:56 +00:00
mtl = open ( mtlpath , ' rU ' )
2007-05-29 04:15:45 +00:00
for line in mtl : #.xreadlines():
2006-09-04 04:23:55 +00:00
if line . startswith ( ' newmtl ' ) :
context_material_name = line_value ( line . split ( ) )
2009-09-29 15:27:00 +00:00
if context_material_name in unique_materials :
2006-09-04 04:23:55 +00:00
context_material = unique_materials [ context_material_name ]
else :
context_material = None
elif context_material :
# we need to make a material to assign properties to it.
line_split = line . split ( )
2008-09-25 13:17:56 +00:00
line_lower = line . lower ( ) . lstrip ( )
2006-10-05 11:15:22 +00:00
if line_lower . startswith ( ' ka ' ) :
2009-09-29 15:27:00 +00:00
context_material . mirror_color = ( float ( line_split [ 1 ] ) , float ( line_split [ 2 ] ) , float ( line_split [ 3 ] ) )
# context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' kd ' ) :
2009-09-29 15:27:00 +00:00
context_material . diffuse_color = ( float ( line_split [ 1 ] ) , float ( line_split [ 2 ] ) , float ( line_split [ 3 ] ) )
# context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' ks ' ) :
2009-09-29 15:27:00 +00:00
context_material . specular_color = ( float ( line_split [ 1 ] ) , float ( line_split [ 2 ] ) , float ( line_split [ 3 ] ) )
# context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' ns ' ) :
2009-09-29 15:27:00 +00:00
context_material . specular_hardness = int ( ( float ( line_split [ 1 ] ) * 0.51 ) )
# context_material.setHardness( int((float(line_split[1])*0.51)) )
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' ni ' ) : # Refraction index
2009-09-29 15:27:00 +00:00
context_material . ior = max ( 1 , min ( float ( line_split [ 1 ] ) , 3 ) )
# context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' d ' ) or line_lower . startswith ( ' tr ' ) :
2009-09-29 15:27:00 +00:00
context_material . alpha = float ( line_split [ 1 ] )
# context_material.setAlpha(float(line_split[1]))
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' map_ka ' ) :
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' Ka ' )
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' map_ks ' ) :
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' Ks ' )
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' map_kd ' ) :
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' Kd ' )
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' map_bump ' ) :
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' Bump ' )
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' map_d ' ) or line_lower . startswith ( ' map_tr ' ) : # Alpha map - Dissolve
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' D ' )
2006-09-04 04:23:55 +00:00
2006-10-05 11:15:22 +00:00
elif line_lower . startswith ( ' refl ' ) : # Reflectionmap
2006-09-04 04:23:55 +00:00
img_filepath = line_value ( line . split ( ) )
2007-03-29 14:35:01 +00:00
if img_filepath :
load_material_image ( context_material , context_material_name , img_filepath , ' refl ' )
2006-09-04 04:23:55 +00:00
mtl . close ( )
2006-10-05 11:15:22 +00:00
2007-01-13 03:07:04 +00:00
2007-04-14 17:44:50 +00:00
def split_mesh ( verts_loc , faces , unique_materials , filepath , SPLIT_OB_OR_GROUP , SPLIT_MATERIALS ) :
2006-09-25 05:12:37 +00:00
'''
Takes vert_loc and faces , and seperates into multiple sets of
2007-01-13 03:07:04 +00:00
( verts_loc , faces , unique_materials , dataname )
2006-09-25 05:12:37 +00:00
This is done so objects do not overload the 16 material limit .
'''
2007-01-13 03:07:04 +00:00
filename = stripExt ( stripPath ( filepath ) )
2007-04-14 17:44:50 +00:00
if not SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS :
2007-01-13 03:07:04 +00:00
# use the filename for the object name since we arnt chopping up the mesh.
return [ ( verts_loc , faces , unique_materials , filename ) ]
2006-09-04 04:23:55 +00:00
2007-01-13 03:07:04 +00:00
def key_to_name ( key ) :
# if the key is a tuple, join it to make a string
if type ( key ) == tuple :
return ' %s _ %s ' % key
elif not key :
return filename # assume its a string. make sure this is true if the splitting code is changed
else :
return key
2006-09-04 04:23:55 +00:00
# Return a key that makes the faces unique.
2007-04-14 17:44:50 +00:00
if SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS :
2006-09-04 04:23:55 +00:00
def face_key ( face ) :
return face [ 4 ] # object
2007-04-15 05:01:34 +00:00
elif not SPLIT_OB_OR_GROUP and SPLIT_MATERIALS :
2006-09-04 04:23:55 +00:00
def face_key ( face ) :
return face [ 2 ] # material
else : # Both
def face_key ( face ) :
2007-01-13 03:07:04 +00:00
return face [ 4 ] , face [ 2 ] # object,material
2006-09-04 04:23:55 +00:00
face_split_dict = { }
2007-01-26 06:02:21 +00:00
oldkey = - 1 # initialize to a value that will never match the key
2006-09-04 04:23:55 +00:00
for face in faces :
key = face_key ( face )
if oldkey != key :
# Check the key has changed.
try :
2007-01-13 03:07:04 +00:00
verts_split , faces_split , unique_materials_split , vert_remap = face_split_dict [ key ]
2006-09-04 04:23:55 +00:00
except KeyError :
faces_split = [ ]
verts_split = [ ]
unique_materials_split = { }
vert_remap = [ - 1 ] * len ( verts_loc )
2007-01-13 03:07:04 +00:00
face_split_dict [ key ] = ( verts_split , faces_split , unique_materials_split , vert_remap )
2007-04-15 05:01:34 +00:00
2006-09-04 04:23:55 +00:00
oldkey = key
face_vert_loc_indicies = face [ 0 ]
# Remap verts to new vert list and add where needed
for enum , i in enumerate ( face_vert_loc_indicies ) :
if vert_remap [ i ] == - 1 :
new_index = len ( verts_split )
vert_remap [ i ] = new_index # set the new remapped index so we only add once and can reference next time.
face_vert_loc_indicies [ enum ] = new_index # remap to the local index
verts_split . append ( verts_loc [ i ] ) # add the vert to the local verts
else :
face_vert_loc_indicies [ enum ] = vert_remap [ i ] # remap to the local index
matname = face [ 2 ]
2009-09-29 15:27:00 +00:00
if matname and matname not in unique_materials_split :
2006-09-04 04:23:55 +00:00
unique_materials_split [ matname ] = unique_materials [ matname ]
faces_split . append ( face )
# remove one of the itemas and reorder
2009-09-29 15:27:00 +00:00
return [ ( value [ 0 ] , value [ 1 ] , value [ 2 ] , key_to_name ( key ) ) for key , value in list ( face_split_dict . items ( ) ) ]
2006-09-04 04:23:55 +00:00
2009-05-13 00:20:14 +00:00
def create_mesh ( scn , new_objects , has_ngons , CREATE_FGONS , CREATE_EDGES , verts_loc , verts_tex , faces , unique_materials , unique_material_images , unique_smooth_groups , vertex_groups , dataname ) :
2006-09-25 05:12:37 +00:00
'''
Takes all the data gathered and generates a mesh , adding the new object to new_objects
deals with fgons , sharp edges and assigning materials
'''
2006-09-04 04:23:55 +00:00
if not has_ngons :
CREATE_FGONS = False
if unique_smooth_groups :
sharp_edges = { }
2009-09-29 15:27:00 +00:00
smooth_group_users = dict ( [ ( context_smooth_group , { } ) for context_smooth_group in list ( unique_smooth_groups . keys ( ) ) ] )
2006-09-04 04:23:55 +00:00
context_smooth_group_old = - 1
# Split fgons into tri's
fgon_edges = { } # Used for storing fgon keys
if CREATE_EDGES :
edges = [ ]
context_object = None
# reverse loop through face indicies
2009-09-29 15:27:00 +00:00
for f_idx in range ( len ( faces ) - 1 , - 1 , - 1 ) :
2006-09-04 04:23:55 +00:00
face_vert_loc_indicies , \
face_vert_tex_indicies , \
context_material , \
context_smooth_group , \
context_object = faces [ f_idx ]
len_face_vert_loc_indicies = len ( face_vert_loc_indicies )
if len_face_vert_loc_indicies == 1 :
faces . pop ( f_idx ) # cant add single vert faces
2007-01-26 06:02:21 +00:00
elif not face_vert_tex_indicies or len_face_vert_loc_indicies == 2 : # faces that have no texture coords are lines
2006-09-04 04:23:55 +00:00
if CREATE_EDGES :
2006-11-25 17:34:57 +00:00
# generators are better in python 2.4+ but can't be used in 2.3
# edges.extend( (face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1) )
2009-09-29 15:27:00 +00:00
edges . extend ( [ ( face_vert_loc_indicies [ i ] , face_vert_loc_indicies [ i + 1 ] ) for i in range ( len_face_vert_loc_indicies - 1 ) ] )
2006-11-25 17:34:57 +00:00
2007-01-26 06:02:21 +00:00
faces . pop ( f_idx )
2006-09-04 04:23:55 +00:00
else :
# Smooth Group
2007-01-26 06:02:21 +00:00
if unique_smooth_groups and context_smooth_group :
2006-09-04 04:23:55 +00:00
# Is a part of of a smooth group and is a face
if context_smooth_group_old is not context_smooth_group :
edge_dict = smooth_group_users [ context_smooth_group ]
context_smooth_group_old = context_smooth_group
2009-09-29 15:27:00 +00:00
for i in range ( len_face_vert_loc_indicies ) :
2006-09-04 04:23:55 +00:00
i1 = face_vert_loc_indicies [ i ]
i2 = face_vert_loc_indicies [ i - 1 ]
if i1 > i2 : i1 , i2 = i2 , i1
try :
edge_dict [ i1 , i2 ] + = 1
except KeyError :
edge_dict [ i1 , i2 ] = 1
# FGons into triangles
if has_ngons and len_face_vert_loc_indicies > 4 :
2009-09-29 15:27:00 +00:00
ngon_face_indices = BPyMesh_ngon ( verts_loc , face_vert_loc_indicies )
2006-09-04 04:23:55 +00:00
faces . extend ( \
[ ( \
[ face_vert_loc_indicies [ ngon [ 0 ] ] , face_vert_loc_indicies [ ngon [ 1 ] ] , face_vert_loc_indicies [ ngon [ 2 ] ] ] , \
[ face_vert_tex_indicies [ ngon [ 0 ] ] , face_vert_tex_indicies [ ngon [ 1 ] ] , face_vert_tex_indicies [ ngon [ 2 ] ] ] , \
context_material , \
context_smooth_group , \
context_object ) \
for ngon in ngon_face_indices ] \
)
# edges to make fgons
if CREATE_FGONS :
edge_users = { }
for ngon in ngon_face_indices :
for i in ( 0 , 1 , 2 ) :
i1 = face_vert_loc_indicies [ ngon [ i ] ]
i2 = face_vert_loc_indicies [ ngon [ i - 1 ] ]
if i1 > i2 : i1 , i2 = i2 , i1
try :
edge_users [ i1 , i2 ] + = 1
except KeyError :
edge_users [ i1 , i2 ] = 1
2009-09-29 15:27:00 +00:00
for key , users in edge_users . items ( ) :
2006-09-04 04:23:55 +00:00
if users > 1 :
fgon_edges [ key ] = None
# remove all after 3, means we dont have to pop this one.
faces . pop ( f_idx )
# Build sharp edges
if unique_smooth_groups :
2009-09-29 15:27:00 +00:00
for edge_dict in list ( smooth_group_users . values ( ) ) :
for key , users in list ( edge_dict . items ( ) ) :
2006-09-04 04:23:55 +00:00
if users == 1 : # This edge is on the boundry of a group
sharp_edges [ key ] = None
2009-01-30 02:01:16 +00:00
# map the material names to an index
material_mapping = dict ( [ ( name , i ) for i , name in enumerate ( unique_materials ) ] ) # enumerate over unique_materials keys()
2006-09-04 04:23:55 +00:00
materials = [ None ] * len ( unique_materials )
2009-09-29 15:27:00 +00:00
for name , index in list ( material_mapping . items ( ) ) :
2006-09-04 04:23:55 +00:00
materials [ index ] = unique_materials [ name ]
2009-09-29 15:27:00 +00:00
me = bpy . data . add_mesh ( dataname )
# me= bpy.data.meshes.new(dataname)
# make sure the list isnt too big
for material in materials [ 0 : 16 ] :
me . add_material ( material )
# me.materials= materials[0:16] # make sure the list isnt too big.
2006-09-04 04:23:55 +00:00
#me.verts.extend([(0,0,0)]) # dummy vert
2009-09-29 15:27:00 +00:00
me . add_geometry ( len ( verts_loc ) , 0 , len ( faces ) )
# verts_loc is a list of (x, y, z) tuples
me . verts . foreach_set ( " co " , unpack_list ( verts_loc ) )
# me.verts.extend(verts_loc)
# faces is a list of (vert_indices, texco_indices, ...) tuples
# XXX faces should contain either 3 or 4 verts
# XXX no check for valid face indices
me . faces . foreach_set ( " verts_raw " , unpack_face_list ( [ f [ 0 ] for f in faces ] ) )
# face_mapping= me.faces.extend([f[0] for f in faces], indexList=True)
2006-09-04 04:23:55 +00:00
if verts_tex and me . faces :
2009-09-29 15:27:00 +00:00
me . add_uv_texture ( )
# me.faceUV= 1
2006-09-04 04:23:55 +00:00
# TEXMODE= Mesh.FaceModes['TEX']
context_material_old = - 1 # avoid a dict lookup
mat = 0 # rare case it may be un-initialized.
me_faces = me . faces
2009-09-29 15:27:00 +00:00
# ALPHA= Mesh.FaceTranspModes.ALPHA
2006-10-05 11:15:22 +00:00
2006-09-04 04:23:55 +00:00
for i , face in enumerate ( faces ) :
2007-01-26 06:02:21 +00:00
if len ( face [ 0 ] ) < 2 :
2007-04-14 17:44:50 +00:00
pass #raise "bad face"
elif len ( face [ 0 ] ) == 2 :
2006-09-04 04:23:55 +00:00
if CREATE_EDGES :
edges . append ( face [ 0 ] )
else :
2009-09-29 15:27:00 +00:00
# face_index_map= face_mapping[i]
# since we use foreach_set to add faces, all of them are added
if 1 :
# if face_index_map!=None: # None means the face wasnt added
blender_face = me . faces [ i ]
# blender_face= me_faces[face_index_map]
2006-09-04 04:23:55 +00:00
face_vert_loc_indicies , \
face_vert_tex_indicies , \
context_material , \
context_smooth_group , \
context_object = face
2007-01-26 06:02:21 +00:00
2006-09-04 04:23:55 +00:00
if context_smooth_group :
blender_face . smooth = True
if context_material :
if context_material_old is not context_material :
mat = material_mapping [ context_material ]
if mat > 15 :
mat = 15
context_material_old = context_material
2009-09-29 15:27:00 +00:00
blender_face . material_index = mat
# blender_face.mat= mat
2006-09-04 04:23:55 +00:00
2009-09-29 15:27:00 +00:00
if verts_tex :
blender_tface = me . uv_textures [ 0 ] . data [ i ]
2006-09-04 04:23:55 +00:00
if context_material :
2006-11-27 23:59:53 +00:00
image , has_data = unique_material_images [ context_material ]
2006-09-04 04:23:55 +00:00
if image : # Can be none if the material dosnt have an image.
2009-09-29 15:27:00 +00:00
blender_tface . image = image
# blender_face.image= image
if has_data :
# if has_data and image.depth == 32:
blender_tface . transp = ' ALPHA '
# blender_face.transp |= ALPHA
2006-09-04 04:23:55 +00:00
# BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled.
if len ( face_vert_loc_indicies ) == 4 :
if face_vert_loc_indicies [ 2 ] == 0 or face_vert_loc_indicies [ 3 ] == 0 :
face_vert_tex_indicies = face_vert_tex_indicies [ 2 ] , face_vert_tex_indicies [ 3 ] , face_vert_tex_indicies [ 0 ] , face_vert_tex_indicies [ 1 ]
else : # length of 3
if face_vert_loc_indicies [ 2 ] == 0 :
face_vert_tex_indicies = face_vert_tex_indicies [ 1 ] , face_vert_tex_indicies [ 2 ] , face_vert_tex_indicies [ 0 ]
# END EEEKADOODLE FIX
# assign material, uv's and image
2009-09-29 15:27:00 +00:00
blender_tface . uv1 = verts_tex [ face_vert_tex_indicies [ 0 ] ]
blender_tface . uv2 = verts_tex [ face_vert_tex_indicies [ 1 ] ]
blender_tface . uv3 = verts_tex [ face_vert_tex_indicies [ 2 ] ]
2009-11-28 20:26:22 +00:00
if len ( face_vert_loc_indicies ) == 4 :
2009-09-29 15:27:00 +00:00
blender_tface . uv4 = verts_tex [ face_vert_tex_indicies [ 3 ] ]
# for ii, uv in enumerate(blender_face.uv):
# uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]]
2006-09-04 04:23:55 +00:00
del me_faces
2009-09-29 15:27:00 +00:00
# del ALPHA
2006-09-04 04:23:55 +00:00
if CREATE_EDGES :
2009-09-29 15:27:00 +00:00
me . add_geometry ( 0 , len ( edges ) , 0 )
# edges should be a list of (a, b) tuples
me . edges . foreach_set ( " verts " , unpack_list ( edges ) )
# me_edges.extend( edges )
2007-01-26 06:02:21 +00:00
2009-09-29 15:27:00 +00:00
# del me_edges
2006-09-04 04:23:55 +00:00
2009-09-29 15:27:00 +00:00
# Add edge faces.
# me_edges= me.edges
def edges_match ( e1 , e2 ) :
return ( e1 [ 0 ] == e2 [ 0 ] and e1 [ 1 ] == e2 [ 1 ] ) or ( e1 [ 0 ] == e2 [ 1 ] and e1 [ 1 ] == e2 [ 0 ] )
# XXX slow
# if CREATE_FGONS and fgon_edges:
# for fgon_edge in fgon_edges.keys():
# for ed in me.edges:
# if edges_match(fgon_edge, ed.verts):
# ed.fgon = True
# if CREATE_FGONS and fgon_edges:
# FGON= Mesh.EdgeFlags.FGON
# for ed in me.findEdges( fgon_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= FGON
# del FGON
# XXX slow
# if unique_smooth_groups and sharp_edges:
# for sharp_edge in sharp_edges.keys():
# for ed in me.edges:
# if edges_match(sharp_edge, ed.verts):
# ed.sharp = True
# if unique_smooth_groups and sharp_edges:
# SHARP= Mesh.EdgeFlags.SHARP
# for ed in me.findEdges( sharp_edges.keys() ):
# if ed!=None:
# me_edges[ed].flag |= SHARP
# del SHARP
me . update ( )
# me.calcNormals()
2006-12-28 22:56:24 +00:00
2009-09-29 15:27:00 +00:00
ob = bpy . data . add_object ( " MESH " , " Mesh " )
ob . data = me
2009-11-20 10:00:54 +00:00
scn . objects . link ( ob )
2009-09-29 15:27:00 +00:00
# ob= scn.objects.new(me)
2006-09-05 06:45:39 +00:00
new_objects . append ( ob )
2006-09-04 04:23:55 +00:00
2009-05-13 00:20:14 +00:00
# Create the vertex groups. No need to have the flag passed here since we test for the
# content of the vertex_groups. If the user selects to NOT have vertex groups saved then
# the following test will never run
2009-09-29 15:27:00 +00:00
for group_name , group_indicies in vertex_groups . items ( ) :
group = ob . add_vertex_group ( group_name )
# me.addVertGroup(group_name)
for vertex_index in group_indicies :
ob . add_vertex_to_group ( vertex_index , group , 1.0 , ' REPLACE ' )
# me.assignVertsToGroup(group_name, group_indicies, 1.00, Mesh.AssignModes.REPLACE)
2009-05-13 00:20:14 +00:00
2009-06-12 04:16:12 +00:00
def create_nurbs ( scn , context_nurbs , vert_loc , new_objects ) :
'''
Add nurbs object to blender , only support one type at the moment
'''
deg = context_nurbs . get ( ' deg ' , ( 3 , ) )
curv_range = context_nurbs . get ( ' curv_range ' , None )
curv_idx = context_nurbs . get ( ' curv_idx ' , [ ] )
parm_u = context_nurbs . get ( ' parm_u ' , [ ] )
parm_v = context_nurbs . get ( ' parm_v ' , [ ] )
name = context_nurbs . get ( ' name ' , ' ObjNurb ' )
cstype = context_nurbs . get ( ' cstype ' , None )
if cstype == None :
2009-09-29 15:27:00 +00:00
print ( ' \t Warning, cstype not found ' )
2009-06-12 04:16:12 +00:00
return
if cstype != ' bspline ' :
2009-09-29 15:27:00 +00:00
print ( ' \t Warning, cstype is not supported (only bspline) ' )
2009-06-12 04:16:12 +00:00
return
if not curv_idx :
2009-09-29 15:27:00 +00:00
print ( ' \t Warning, curv argument empty or not set ' )
2009-06-12 04:16:12 +00:00
return
if len ( deg ) > 1 or parm_v :
2009-09-29 15:27:00 +00:00
print ( ' \t Warning, surfaces not supported ' )
2009-06-12 04:16:12 +00:00
return
cu = bpy . data . curves . new ( name , ' Curve ' )
2009-06-13 03:54:27 +00:00
cu . flag | = 1 # 3D curve
2009-06-12 04:16:12 +00:00
nu = None
for pt in curv_idx :
pt = vert_loc [ pt ]
pt = ( pt [ 0 ] , pt [ 1 ] , pt [ 2 ] , 1.0 )
if nu == None :
nu = cu . appendNurb ( pt )
else :
nu . append ( pt )
nu . orderU = deg [ 0 ] + 1
# get for endpoint flag from the weighting
if curv_range and len ( parm_u ) > deg [ 0 ] + 1 :
do_endpoints = True
2009-09-29 15:27:00 +00:00
for i in range ( deg [ 0 ] + 1 ) :
2009-06-12 04:16:12 +00:00
if abs ( parm_u [ i ] - curv_range [ 0 ] ) > 0.0001 :
do_endpoints = False
break
if abs ( parm_u [ - ( i + 1 ) ] - curv_range [ 1 ] ) > 0.0001 :
do_endpoints = False
break
else :
do_endpoints = False
if do_endpoints :
nu . flagU | = 2
# close
'''
do_closed = False
if len ( parm_u ) > deg [ 0 ] + 1 :
for i in xrange ( deg [ 0 ] + 1 ) :
#print curv_idx[i], curv_idx[-(i+1)]
if curv_idx [ i ] == curv_idx [ - ( i + 1 ) ] :
do_closed = True
break
if do_closed :
nu . flagU | = 1
'''
ob = scn . objects . new ( cu )
new_objects . append ( ob )
2009-06-13 03:05:20 +00:00
2009-06-12 04:16:12 +00:00
def strip_slash ( line_split ) :
if line_split [ - 1 ] [ - 1 ] == ' \\ ' :
if len ( line_split [ - 1 ] ) == 1 :
line_split . pop ( ) # remove the \ item
else :
line_split [ - 1 ] = line_split [ - 1 ] [ : - 1 ] # remove the \ from the end last number
return True
return False
2006-09-04 04:23:55 +00:00
def get_float_func ( filepath ) :
'''
find the float function for this obj file
- weather to replace commas or not
'''
2007-08-01 18:04:44 +00:00
file = open ( filepath , ' rU ' )
2007-05-29 04:15:45 +00:00
for line in file : #.xreadlines():
2009-04-10 14:33:52 +00:00
line = line . lstrip ( )
2006-09-04 04:23:55 +00:00
if line . startswith ( ' v ' ) : # vn vt v
if ' , ' in line :
return lambda f : float ( f . replace ( ' , ' , ' . ' ) )
elif ' . ' in line :
return float
2007-12-19 07:44:37 +00:00
# incase all vert values were ints
return float
2006-09-04 04:23:55 +00:00
2009-05-13 00:20:14 +00:00
def load_obj ( filepath ,
2009-09-29 15:27:00 +00:00
context ,
CLAMP_SIZE = 0.0 ,
CREATE_FGONS = True ,
CREATE_SMOOTH_GROUPS = True ,
CREATE_EDGES = True ,
SPLIT_OBJECTS = True ,
SPLIT_GROUPS = True ,
SPLIT_MATERIALS = True ,
ROTATE_X90 = True ,
IMAGE_SEARCH = True ,
POLYGROUPS = False ) :
2006-09-25 05:12:37 +00:00
'''
Called by the user interface or another script .
load_obj ( path ) - should give acceptable results .
This function passes the file and sends the data off
to be split into objects and then converted into mesh objects
'''
2009-09-29 15:27:00 +00:00
print ( ' \n importing obj " %s " ' % filepath )
2006-09-04 04:23:55 +00:00
2009-05-13 00:20:14 +00:00
if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS :
POLYGROUPS = False
2009-09-29 15:27:00 +00:00
time_main = time . time ( )
# time_main= sys.time()
2006-09-04 04:23:55 +00:00
verts_loc = [ ]
verts_tex = [ ]
faces = [ ] # tuples of the faces
material_libs = [ ] # filanems to material libs this uses
2009-05-13 00:20:14 +00:00
vertex_groups = { } # when POLYGROUPS is true
2006-09-04 04:23:55 +00:00
# Get the string to float conversion func for this file- is 'float' for almost all files.
float_func = get_float_func ( filepath )
# Context variables
context_material = None
context_smooth_group = None
context_object = None
2009-05-13 00:20:14 +00:00
context_vgroup = None
2009-06-12 04:16:12 +00:00
# Nurbs
context_nurbs = { }
nurbs = [ ]
context_parm = ' ' # used by nurbs too but could be used elsewhere
2009-05-13 00:20:14 +00:00
2006-09-04 04:23:55 +00:00
has_ngons = False
# has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0
# Until we can use sets
unique_materials = { }
unique_material_images = { }
unique_smooth_groups = { }
# unique_obects= {} - no use for this variable since the objects are stored in the face.
# when there are faces that end with \
# it means they are multiline-
# since we use xreadline we cant skip to the next line
# so we need to know weather
2009-06-12 04:16:12 +00:00
context_multi_line = ' '
2006-09-04 04:23:55 +00:00
2009-09-29 15:27:00 +00:00
print ( ' \t parsing obj file " %s " ... ' % filepath )
time_sub = time . time ( )
# time_sub= sys.time()
2009-05-13 00:20:14 +00:00
2008-09-25 13:17:56 +00:00
file = open ( filepath , ' rU ' )
2007-05-29 04:15:45 +00:00
for line in file : #.xreadlines():
2009-04-10 14:33:52 +00:00
line = line . lstrip ( ) # rare cases there is white space at the start of the line
2006-09-04 04:23:55 +00:00
if line . startswith ( ' v ' ) :
line_split = line . split ( )
# rotate X90: (x,-z,y)
verts_loc . append ( ( float_func ( line_split [ 1 ] ) , - float_func ( line_split [ 3 ] ) , float_func ( line_split [ 2 ] ) ) )
elif line . startswith ( ' vn ' ) :
pass
elif line . startswith ( ' vt ' ) :
line_split = line . split ( )
verts_tex . append ( ( float_func ( line_split [ 1 ] ) , float_func ( line_split [ 2 ] ) ) )
# Handel faces lines (as faces) and the second+ lines of fa multiline face here
# use 'f' not 'f ' because some objs (very rare have 'fo ' for faces)
2009-06-12 04:16:12 +00:00
elif line . startswith ( ' f ' ) or context_multi_line == ' f ' :
2006-09-04 04:23:55 +00:00
2009-06-12 04:16:12 +00:00
if context_multi_line :
2006-09-04 04:23:55 +00:00
# use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
line_split = line . split ( )
else :
line_split = line [ 2 : ] . split ( )
face_vert_loc_indicies = [ ]
face_vert_tex_indicies = [ ]
# Instance a face
faces . append ( ( \
face_vert_loc_indicies , \
face_vert_tex_indicies , \
context_material , \
context_smooth_group , \
context_object \
) )
2009-06-12 04:16:12 +00:00
if strip_slash ( line_split ) :
context_multi_line = ' f '
else :
context_multi_line = ' '
2006-09-04 04:23:55 +00:00
for v in line_split :
obj_vert = v . split ( ' / ' )
vert_loc_index = int ( obj_vert [ 0 ] ) - 1
2009-05-13 00:20:14 +00:00
# Add the vertex to the current group
# *warning*, this wont work for files that have groups defined around verts
if POLYGROUPS and context_vgroup :
vertex_groups [ context_vgroup ] . append ( vert_loc_index )
2006-09-04 04:23:55 +00:00
# Make relative negative vert indicies absolute
if vert_loc_index < 0 :
vert_loc_index = len ( verts_loc ) + vert_loc_index + 1
face_vert_loc_indicies . append ( vert_loc_index )
2009-06-12 04:16:12 +00:00
if len ( obj_vert ) > 1 and obj_vert [ 1 ] :
# formatting for faces with normals and textures us
# loc_index/tex_index/nor_index
vert_tex_index = int ( obj_vert [ 1 ] ) - 1
# Make relative negative vert indicies absolute
if vert_tex_index < 0 :
vert_tex_index = len ( verts_tex ) + vert_tex_index + 1
face_vert_tex_indicies . append ( vert_tex_index )
else :
# dummy
face_vert_tex_indicies . append ( 0 )
2006-09-04 04:23:55 +00:00
if len ( face_vert_loc_indicies ) > 4 :
has_ngons = True
2009-06-12 04:16:12 +00:00
elif CREATE_EDGES and ( line . startswith ( ' l ' ) or context_multi_line == ' l ' ) :
# very similar to the face load function above with some parts removed
2006-09-04 04:23:55 +00:00
2009-06-12 04:16:12 +00:00
if context_multi_line :
# use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
line_split = line . split ( )
else :
line_split = line [ 2 : ] . split ( )
face_vert_loc_indicies = [ ]
face_vert_tex_indicies = [ ]
# Instance a face
faces . append ( ( \
face_vert_loc_indicies , \
face_vert_tex_indicies , \
context_material , \
context_smooth_group , \
context_object \
) )
if strip_slash ( line_split ) :
context_multi_line = ' l '
else :
context_multi_line = ' '
isline = line . startswith ( ' l ' )
for v in line_split :
vert_loc_index = int ( v ) - 1
# Make relative negative vert indicies absolute
if vert_loc_index < 0 :
vert_loc_index = len ( verts_loc ) + vert_loc_index + 1
face_vert_loc_indicies . append ( vert_loc_index )
2006-09-04 04:23:55 +00:00
elif line . startswith ( ' s ' ) :
if CREATE_SMOOTH_GROUPS :
context_smooth_group = line_value ( line . split ( ) )
if context_smooth_group == ' off ' :
context_smooth_group = None
elif context_smooth_group : # is not None
unique_smooth_groups [ context_smooth_group ] = None
elif line . startswith ( ' o ' ) :
if SPLIT_OBJECTS :
context_object = line_value ( line . split ( ) )
# unique_obects[context_object]= None
elif line . startswith ( ' g ' ) :
if SPLIT_GROUPS :
context_object = line_value ( line . split ( ) )
# print 'context_object', context_object
# unique_obects[context_object]= None
2009-05-13 00:20:14 +00:00
elif POLYGROUPS :
context_vgroup = line_value ( line . split ( ) )
if context_vgroup and context_vgroup != ' (null) ' :
vertex_groups . setdefault ( context_vgroup , [ ] )
else :
context_vgroup = None # dont assign a vgroup
2006-09-04 04:23:55 +00:00
elif line . startswith ( ' usemtl ' ) :
context_material = line_value ( line . split ( ) )
unique_materials [ context_material ] = None
elif line . startswith ( ' mtllib ' ) : # usemap or usemat
material_libs . extend ( line . split ( ) [ 1 : ] ) # can have multiple mtllib filenames per line
2009-06-12 04:16:12 +00:00
# Nurbs support
elif line . startswith ( ' cstype ' ) :
context_nurbs [ ' cstype ' ] = line_value ( line . split ( ) ) # 'rat bspline' / 'bspline'
elif line . startswith ( ' curv ' ) or context_multi_line == ' curv ' :
line_split = line . split ( )
curv_idx = context_nurbs [ ' curv_idx ' ] = context_nurbs . get ( ' curv_idx ' , [ ] ) # incase were multiline
if not context_multi_line :
context_nurbs [ ' curv_range ' ] = float_func ( line_split [ 1 ] ) , float_func ( line_split [ 2 ] )
line_split [ 0 : 3 ] = [ ] # remove first 3 items
if strip_slash ( line_split ) :
context_multi_line = ' curv '
else :
context_multi_line = ' '
for i in line_split :
vert_loc_index = int ( i ) - 1
if vert_loc_index < 0 :
vert_loc_index = len ( verts_loc ) + vert_loc_index + 1
curv_idx . append ( vert_loc_index )
elif line . startswith ( ' parm ' ) or context_multi_line == ' parm ' :
line_split = line . split ( )
if context_multi_line :
context_multi_line = ' '
else :
context_parm = line_split [ 1 ]
line_split [ 0 : 2 ] = [ ] # remove first 2
if strip_slash ( line_split ) :
context_multi_line = ' parm '
else :
context_multi_line = ' '
if context_parm . lower ( ) == ' u ' :
context_nurbs . setdefault ( ' parm_u ' , [ ] ) . extend ( [ float_func ( f ) for f in line_split ] )
elif context_parm . lower ( ) == ' v ' : # surfaces not suported yet
context_nurbs . setdefault ( ' parm_v ' , [ ] ) . extend ( [ float_func ( f ) for f in line_split ] )
# else: # may want to support other parm's ?
elif line . startswith ( ' deg ' ) :
context_nurbs [ ' deg ' ] = [ int ( i ) for i in line . split ( ) [ 1 : ] ]
elif line . startswith ( ' end ' ) :
# Add the nurbs curve
2009-06-13 03:54:27 +00:00
if context_object :
context_nurbs [ ' name ' ] = context_object
2009-06-12 04:16:12 +00:00
nurbs . append ( context_nurbs )
context_nurbs = { }
context_parm = ' '
2006-09-04 04:23:55 +00:00
''' # How to use usemap? depricated?
elif line . startswith ( ' usema ' ) : # usemap or usemat
context_image = line_value ( line . split ( ) )
'''
file . close ( )
2009-09-29 15:27:00 +00:00
time_new = time . time ( )
# time_new= sys.time()
print ( ' %.4f sec ' % ( time_new - time_sub ) )
2006-09-04 04:23:55 +00:00
time_sub = time_new
2009-09-29 15:27:00 +00:00
print ( ' \t loading materials and images... ' )
2006-09-20 05:03:53 +00:00
create_materials ( filepath , material_libs , unique_materials , unique_material_images , IMAGE_SEARCH )
2009-09-29 15:27:00 +00:00
time_new = time . time ( )
# time_new= sys.time()
print ( ' %.4f sec ' % ( time_new - time_sub ) )
2006-09-04 04:23:55 +00:00
time_sub = time_new
2009-06-13 03:05:20 +00:00
if not ROTATE_X90 :
2009-06-13 04:31:30 +00:00
verts_loc [ : ] = [ ( v [ 0 ] , v [ 2 ] , - v [ 1 ] ) for v in verts_loc ]
2006-09-04 04:23:55 +00:00
# deselect all
2009-09-29 15:27:00 +00:00
# if context.selected_objects:
2009-11-29 22:16:29 +00:00
# bpy.ops.OBJECT_OT_select_all()
2009-09-29 15:27:00 +00:00
scene = context . scene
# scn = bpy.data.scenes.active
# scn.objects.selected = []
2006-09-05 06:45:39 +00:00
new_objects = [ ] # put new objects here
2006-09-04 04:23:55 +00:00
2009-09-29 15:27:00 +00:00
print ( ' \t building geometry... \n \t verts: %i faces: %i materials: %i smoothgroups: %i ... ' % ( len ( verts_loc ) , len ( faces ) , len ( unique_materials ) , len ( unique_smooth_groups ) ) )
2006-09-04 04:23:55 +00:00
# Split the mesh by objects/materials, may
2007-04-14 17:44:50 +00:00
if SPLIT_OBJECTS or SPLIT_GROUPS : SPLIT_OB_OR_GROUP = True
else : SPLIT_OB_OR_GROUP = False
for verts_loc_split , faces_split , unique_materials_split , dataname in split_mesh ( verts_loc , faces , unique_materials , filepath , SPLIT_OB_OR_GROUP , SPLIT_MATERIALS ) :
2009-05-13 00:20:14 +00:00
# Create meshes from the data, warning 'vertex_groups' wont support splitting
2009-09-29 15:27:00 +00:00
create_mesh ( scene , new_objects , has_ngons , CREATE_FGONS , CREATE_EDGES , verts_loc_split , verts_tex , faces_split , unique_materials_split , unique_material_images , unique_smooth_groups , vertex_groups , dataname )
2006-09-05 06:45:39 +00:00
2009-06-12 04:16:12 +00:00
# nurbs support
2009-09-29 15:27:00 +00:00
# for context_nurbs in nurbs:
# create_nurbs(scn, context_nurbs, verts_loc, new_objects)
2009-06-12 04:16:12 +00:00
2006-09-05 06:45:39 +00:00
axis_min = [ 1000000000 ] * 3
axis_max = [ - 1000000000 ] * 3
2009-09-29 15:27:00 +00:00
# if CLAMP_SIZE:
# # Get all object bounds
# for ob in new_objects:
# for v in ob.getBoundBox():
# for axis, value in enumerate(v):
# if axis_min[axis] > value: axis_min[axis]= value
# if axis_max[axis] < value: axis_max[axis]= value
2006-09-05 06:45:39 +00:00
2009-09-29 15:27:00 +00:00
# # Scale objects
# max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2])
# scale= 1.0
2006-09-05 06:45:39 +00:00
2009-09-29 15:27:00 +00:00
# while CLAMP_SIZE < max_axis * scale:
# scale= scale/10.0
2006-09-05 06:45:39 +00:00
2009-09-29 15:27:00 +00:00
# for ob in new_objects:
# ob.setSize(scale, scale, scale)
2006-09-04 04:23:55 +00:00
2009-06-13 03:05:20 +00:00
# Better rotate the vert locations
#if not ROTATE_X90:
# for ob in new_objects:
# ob.RotX = -1.570796326794896558
2009-09-29 15:27:00 +00:00
time_new = time . time ( )
# time_new= sys.time()
2009-06-13 03:05:20 +00:00
2009-09-29 15:27:00 +00:00
print ( ' %.4f sec ' % ( time_new - time_sub ) )
print ( ' finished importing: " %s " in %.4f sec. ' % ( filepath , ( time_new - time_main ) ) )
2006-09-04 04:23:55 +00:00
DEBUG = True
2006-11-02 17:42:30 +00:00
def load_obj_ui ( filepath , BATCH_LOAD = False ) :
2006-09-26 04:39:46 +00:00
if BPyMessages . Error_NoFile ( filepath ) :
return
2009-06-13 03:05:20 +00:00
global CREATE_SMOOTH_GROUPS , CREATE_FGONS , CREATE_EDGES , SPLIT_OBJECTS , SPLIT_GROUPS , SPLIT_MATERIALS , CLAMP_SIZE , IMAGE_SEARCH , POLYGROUPS , KEEP_VERT_ORDER , ROTATE_X90
2007-01-26 07:01:30 +00:00
2006-09-04 04:23:55 +00:00
CREATE_SMOOTH_GROUPS = Draw . Create ( 0 )
CREATE_FGONS = Draw . Create ( 1 )
CREATE_EDGES = Draw . Create ( 1 )
2008-10-19 15:53:22 +00:00
SPLIT_OBJECTS = Draw . Create ( 0 )
SPLIT_GROUPS = Draw . Create ( 0 )
SPLIT_MATERIALS = Draw . Create ( 0 )
2006-09-05 06:45:39 +00:00
CLAMP_SIZE = Draw . Create ( 10.0 )
2006-09-20 05:03:53 +00:00
IMAGE_SEARCH = Draw . Create ( 1 )
2009-05-13 00:20:14 +00:00
POLYGROUPS = Draw . Create ( 0 )
2008-10-19 15:53:22 +00:00
KEEP_VERT_ORDER = Draw . Create ( 1 )
2009-06-13 03:05:20 +00:00
ROTATE_X90 = Draw . Create ( 1 )
2006-09-05 06:45:39 +00:00
2006-09-04 04:23:55 +00:00
# Get USER Options
2008-10-19 15:53:22 +00:00
# Note, Works but not pretty, instead use a more complicated GUI
'''
2006-09-04 04:23:55 +00:00
pup_block = [ \
2007-01-26 07:01:30 +00:00
' Import... ' , \
2006-09-04 04:23:55 +00:00
( ' Smooth Groups ' , CREATE_SMOOTH_GROUPS , ' Surround smooth groups by sharp edges ' ) , \
( ' Create FGons ' , CREATE_FGONS , ' Import faces with more then 4 verts as fgons. ' ) , \
( ' Lines ' , CREATE_EDGES , ' Import lines and faces with 2 verts as edges ' ) , \
2007-04-14 17:44:50 +00:00
' Separate objects from obj... ' , \
2007-01-26 07:01:30 +00:00
( ' Object ' , SPLIT_OBJECTS , ' Import OBJ Objects into Blender Objects ' ) , \
( ' Group ' , SPLIT_GROUPS , ' Import OBJ Groups into Blender Objects ' ) , \
( ' Material ' , SPLIT_MATERIALS , ' Import each material into a seperate mesh (Avoids > 16 per mesh error) ' ) , \
' Options... ' , \
2008-09-17 04:07:58 +00:00
( ' Keep Vert Order ' , KEEP_VERT_ORDER , ' Keep vert and face order, disables some other options. ' ) , \
2006-09-05 06:45:39 +00:00
( ' Clamp Scale: ' , CLAMP_SIZE , 0.0 , 1000.0 , ' Clamp the size to this maximum (Zero to Disable) ' ) , \
2006-09-20 05:03:53 +00:00
( ' Image Search ' , IMAGE_SEARCH , ' Search subdirs for any assosiated images (Warning, may be slow) ' ) , \
2006-09-04 04:23:55 +00:00
]
if not Draw . PupBlock ( ' Import OBJ... ' , pup_block ) :
return
2008-09-17 04:07:58 +00:00
if KEEP_VERT_ORDER . val :
2007-01-26 07:01:30 +00:00
SPLIT_OBJECTS . val = False
SPLIT_GROUPS . val = False
SPLIT_MATERIALS . val = False
2008-10-19 15:53:22 +00:00
'''
# BEGIN ALTERNATIVE UI *******************
if True :
EVENT_NONE = 0
EVENT_EXIT = 1
EVENT_REDRAW = 2
EVENT_IMPORT = 3
GLOBALS = { }
GLOBALS [ ' EVENT ' ] = EVENT_REDRAW
#GLOBALS['MOUSE'] = Window.GetMouseCoords()
GLOBALS [ ' MOUSE ' ] = [ i / 2 for i in Window . GetScreenSize ( ) ]
def obj_ui_set_event ( e , v ) :
GLOBALS [ ' EVENT ' ] = e
def do_split ( e , v ) :
2009-05-13 00:20:14 +00:00
global SPLIT_OBJECTS , SPLIT_GROUPS , SPLIT_MATERIALS , KEEP_VERT_ORDER , POLYGROUPS
2008-10-19 15:53:22 +00:00
if SPLIT_OBJECTS . val or SPLIT_GROUPS . val or SPLIT_MATERIALS . val :
KEEP_VERT_ORDER . val = 0
2009-05-13 00:20:14 +00:00
POLYGROUPS . val = 0
2008-10-19 15:53:22 +00:00
else :
KEEP_VERT_ORDER . val = 1
def do_vertorder ( e , v ) :
global SPLIT_OBJECTS , SPLIT_GROUPS , SPLIT_MATERIALS , KEEP_VERT_ORDER
if KEEP_VERT_ORDER . val :
SPLIT_OBJECTS . val = SPLIT_GROUPS . val = SPLIT_MATERIALS . val = 0
else :
if not ( SPLIT_OBJECTS . val or SPLIT_GROUPS . val or SPLIT_MATERIALS . val ) :
KEEP_VERT_ORDER . val = 1
2009-05-13 00:20:14 +00:00
def do_polygroups ( e , v ) :
global SPLIT_OBJECTS , SPLIT_GROUPS , SPLIT_MATERIALS , KEEP_VERT_ORDER , POLYGROUPS
if POLYGROUPS . val :
SPLIT_OBJECTS . val = SPLIT_GROUPS . val = SPLIT_MATERIALS . val = 0
2008-10-19 15:53:22 +00:00
def do_help ( e , v ) :
url = __url__ [ 0 ]
2009-09-29 15:27:00 +00:00
print ( ' Trying to open web browser with documentation at this address... ' )
print ( ' \t ' + url )
2008-10-19 15:53:22 +00:00
try :
import webbrowser
webbrowser . open ( url )
except :
2009-09-29 15:27:00 +00:00
print ( ' ...could not open a browser window. ' )
2008-10-19 15:53:22 +00:00
def obj_ui ( ) :
ui_x , ui_y = GLOBALS [ ' MOUSE ' ]
# Center based on overall pup size
ui_x - = 165
ui_y - = 90
2009-06-13 03:05:20 +00:00
global CREATE_SMOOTH_GROUPS , CREATE_FGONS , CREATE_EDGES , SPLIT_OBJECTS , SPLIT_GROUPS , SPLIT_MATERIALS , CLAMP_SIZE , IMAGE_SEARCH , POLYGROUPS , KEEP_VERT_ORDER , ROTATE_X90
2008-10-19 15:53:22 +00:00
Draw . Label ( ' Import... ' , ui_x + 9 , ui_y + 159 , 220 , 21 )
Draw . BeginAlign ( )
CREATE_SMOOTH_GROUPS = Draw . Toggle ( ' Smooth Groups ' , EVENT_NONE , ui_x + 9 , ui_y + 139 , 110 , 20 , CREATE_SMOOTH_GROUPS . val , ' Surround smooth groups by sharp edges ' )
CREATE_FGONS = Draw . Toggle ( ' NGons as FGons ' , EVENT_NONE , ui_x + 119 , ui_y + 139 , 110 , 20 , CREATE_FGONS . val , ' Import faces with more then 4 verts as fgons ' )
CREATE_EDGES = Draw . Toggle ( ' Lines as Edges ' , EVENT_NONE , ui_x + 229 , ui_y + 139 , 110 , 20 , CREATE_EDGES . val , ' Import lines and faces with 2 verts as edges ' )
Draw . EndAlign ( )
Draw . Label ( ' Separate objects by OBJ... ' , ui_x + 9 , ui_y + 110 , 220 , 20 )
Draw . BeginAlign ( )
2009-06-13 03:05:20 +00:00
SPLIT_OBJECTS = Draw . Toggle ( ' Object ' , EVENT_REDRAW , ui_x + 9 , ui_y + 89 , 55 , 21 , SPLIT_OBJECTS . val , ' Import OBJ Objects into Blender Objects ' , do_split )
SPLIT_GROUPS = Draw . Toggle ( ' Group ' , EVENT_REDRAW , ui_x + 64 , ui_y + 89 , 55 , 21 , SPLIT_GROUPS . val , ' Import OBJ Groups into Blender Objects ' , do_split )
SPLIT_MATERIALS = Draw . Toggle ( ' Material ' , EVENT_REDRAW , ui_x + 119 , ui_y + 89 , 60 , 21 , SPLIT_MATERIALS . val , ' Import each material into a seperate mesh (Avoids > 16 per mesh error) ' , do_split )
2008-10-19 15:53:22 +00:00
Draw . EndAlign ( )
# Only used for user feedback
2009-06-13 03:05:20 +00:00
KEEP_VERT_ORDER = Draw . Toggle ( ' Keep Vert Order ' , EVENT_REDRAW , ui_x + 184 , ui_y + 89 , 113 , 21 , KEEP_VERT_ORDER . val , ' Keep vert and face order, disables split options, enable for morph targets ' , do_vertorder )
ROTATE_X90 = Draw . Toggle ( ' -X90 ' , EVENT_REDRAW , ui_x + 302 , ui_y + 89 , 38 , 21 , ROTATE_X90 . val , ' Rotate X 90. ' )
2008-10-19 15:53:22 +00:00
Draw . Label ( ' Options... ' , ui_x + 9 , ui_y + 60 , 211 , 20 )
2009-05-13 00:20:14 +00:00
CLAMP_SIZE = Draw . Number ( ' Clamp Scale: ' , EVENT_NONE , ui_x + 9 , ui_y + 39 , 130 , 21 , CLAMP_SIZE . val , 0.0 , 1000.0 , ' Clamp the size to this maximum (Zero to Disable) ' )
POLYGROUPS = Draw . Toggle ( ' Poly Groups ' , EVENT_REDRAW , ui_x + 144 , ui_y + 39 , 90 , 21 , POLYGROUPS . val , ' Import OBJ groups as vertex groups. ' , do_polygroups )
IMAGE_SEARCH = Draw . Toggle ( ' Image Search ' , EVENT_NONE , ui_x + 239 , ui_y + 39 , 100 , 21 , IMAGE_SEARCH . val , ' Search subdirs for any assosiated images (Warning, may be slow) ' )
2008-10-19 15:53:22 +00:00
Draw . BeginAlign ( )
Draw . PushButton ( ' Online Help ' , EVENT_REDRAW , ui_x + 9 , ui_y + 9 , 110 , 21 , ' Load the wiki page for this script ' , do_help )
Draw . PushButton ( ' Cancel ' , EVENT_EXIT , ui_x + 119 , ui_y + 9 , 110 , 21 , ' ' , obj_ui_set_event )
Draw . PushButton ( ' Import ' , EVENT_IMPORT , ui_x + 229 , ui_y + 9 , 110 , 21 , ' Import with these settings ' , obj_ui_set_event )
Draw . EndAlign ( )
# hack so the toggle buttons redraw. this is not nice at all
while GLOBALS [ ' EVENT ' ] not in ( EVENT_EXIT , EVENT_IMPORT ) :
2008-10-22 08:21:43 +00:00
Draw . UIBlock ( obj_ui , 0 )
2008-10-19 15:53:22 +00:00
if GLOBALS [ ' EVENT ' ] != EVENT_IMPORT :
return
# END ALTERNATIVE UI *********************
2007-01-26 07:01:30 +00:00
2006-09-04 04:23:55 +00:00
Window . WaitCursor ( 1 )
2006-11-02 17:42:30 +00:00
if BATCH_LOAD : # load the dir
try :
files = [ f for f in os . listdir ( filepath ) if f . lower ( ) . endswith ( ' .obj ' ) ]
except :
2007-01-26 07:01:30 +00:00
Window . WaitCursor ( 0 )
2006-11-02 17:42:30 +00:00
Draw . PupMenu ( ' Error % t|Could not open path ' + filepath )
return
if not files :
2007-01-26 07:01:30 +00:00
Window . WaitCursor ( 0 )
2006-11-02 17:42:30 +00:00
Draw . PupMenu ( ' Error % t|No files at path ' + filepath )
return
for f in files :
2007-04-18 14:40:01 +00:00
scn = bpy . data . scenes . new ( stripExt ( f ) )
2006-11-02 17:42:30 +00:00
scn . makeCurrent ( )
load_obj ( sys . join ( filepath , f ) , \
CLAMP_SIZE . val , \
CREATE_FGONS . val , \
CREATE_SMOOTH_GROUPS . val , \
CREATE_EDGES . val , \
SPLIT_OBJECTS . val , \
SPLIT_GROUPS . val , \
SPLIT_MATERIALS . val , \
2009-06-13 03:05:20 +00:00
ROTATE_X90 . val , \
2006-11-02 17:42:30 +00:00
IMAGE_SEARCH . val , \
2009-05-13 00:20:14 +00:00
POLYGROUPS . val
2006-11-02 17:42:30 +00:00
)
else : # Normal load
load_obj ( filepath , \
CLAMP_SIZE . val , \
CREATE_FGONS . val , \
CREATE_SMOOTH_GROUPS . val , \
CREATE_EDGES . val , \
SPLIT_OBJECTS . val , \
SPLIT_GROUPS . val , \
SPLIT_MATERIALS . val , \
2009-06-13 03:05:20 +00:00
ROTATE_X90 . val , \
2006-11-02 17:42:30 +00:00
IMAGE_SEARCH . val , \
2009-05-13 00:20:14 +00:00
POLYGROUPS . val
2006-11-02 17:42:30 +00:00
)
2006-09-04 04:23:55 +00:00
Window . WaitCursor ( 0 )
2006-11-02 17:42:30 +00:00
def load_obj_ui_batch ( file ) :
load_obj_ui ( file , True )
2006-09-04 04:23:55 +00:00
DEBUG = False
2006-11-02 17:42:30 +00:00
2009-09-29 15:27:00 +00:00
# if __name__=='__main__' and not DEBUG:
# if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT:
# Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '')
# else:
# Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
2006-11-02 17:42:30 +00:00
2009-06-13 03:05:20 +00:00
# For testing compatibility
2009-06-12 04:16:12 +00:00
'''
2006-09-04 04:23:55 +00:00
else :
# DEBUG ONLY
TIME = sys . time ( )
2009-06-12 04:16:12 +00:00
DIR = ' /fe/obj '
2006-09-04 04:23:55 +00:00
import os
print ' Searching for files '
2009-06-12 04:16:12 +00:00
def fileList ( path ) :
for dirpath , dirnames , filenames in os . walk ( path ) :
for filename in filenames :
yield os . path . join ( dirpath , filename )
files = [ f for f in fileList ( DIR ) if f . lower ( ) . endswith ( ' .obj ' ) ]
files . sort ( )
for i , obj_file in enumerate ( files ) :
if 0 < i < 20 :
print ' Importing ' , obj_file , ' \n NUMBER ' , i , ' of ' , len ( files )
newScn = bpy . data . scenes . new ( os . path . basename ( obj_file ) )
2006-09-04 04:23:55 +00:00
newScn . makeCurrent ( )
2009-06-13 03:05:20 +00:00
load_obj ( obj_file , False , IMAGE_SEARCH = 0 )
2006-09-04 04:23:55 +00:00
print ' TOTAL TIME: %.6f ' % ( sys . time ( ) - TIME )
'''
2009-09-29 15:27:00 +00:00
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
from bpy . props import *
2009-09-29 15:27:00 +00:00
class IMPORT_OT_obj ( bpy . types . Operator ) :
- add torus back from 2.4x as an operator
bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops - MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
2009-10-10 21:23:20 +00:00
''' Load a Wavefront OBJ File. '''
2009-11-04 17:16:58 +00:00
bl_idname = " import_scene.obj "
2009-10-31 13:31:23 +00:00
bl_label = " Import OBJ "
2009-09-29 15:27:00 +00:00
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
path = StringProperty ( name = " File Path " , description = " File path used for importing the OBJ file " , maxlen = 1024 , default = " " )
CREATE_SMOOTH_GROUPS = BoolProperty ( name = " Smooth Groups " , description = " Surround smooth groups by sharp edges " , default = True )
CREATE_FGONS = BoolProperty ( name = " NGons as FGons " , description = " Import faces with more then 4 verts as fgons " , default = True )
CREATE_EDGES = BoolProperty ( name = " Lines as Edges " , description = " Import lines and faces with 2 verts as edge " , default = True )
SPLIT_OBJECTS = BoolProperty ( name = " Object " , description = " Import OBJ Objects into Blender Objects " , default = True )
SPLIT_GROUPS = BoolProperty ( name = " Group " , description = " Import OBJ Groups into Blender Objects " , default = True )
SPLIT_MATERIALS = BoolProperty ( name = " Material " , description = " Import each material into a seperate mesh (Avoids > 16 per mesh error) " , default = True )
# old comment: only used for user feedback
# disabled this option because in old code a handler for it disabled SPLIT* params, it's not passed to load_obj
# KEEP_VERT_ORDER = BoolProperty(name="Keep Vert Order", description="Keep vert and face order, disables split options, enable for morph targets", default= True)
ROTATE_X90 = BoolProperty ( name = " -X90 " , description = " Rotate X 90. " , default = True )
CLAMP_SIZE = FloatProperty ( name = " Clamp Scale " , description = " Clamp the size to this maximum (Zero to Disable) " , min = 0.01 , max = 1000.0 , soft_min = 0.0 , soft_max = 1000.0 , default = 0.0 )
POLYGROUPS = BoolProperty ( name = " Poly Groups " , description = " Import OBJ groups as vertex groups. " , default = True )
IMAGE_SEARCH = BoolProperty ( name = " Image Search " , description = " Search subdirs for any assosiated images (Warning, may be slow) " , default = True )
2009-09-29 15:27:00 +00:00
def execute ( self , context ) :
# print("Selected: " + context.active_object.name)
2009-11-19 17:12:08 +00:00
load_obj ( self . properties . path ,
2009-09-29 15:27:00 +00:00
context ,
2009-11-19 17:12:08 +00:00
self . properties . CLAMP_SIZE ,
self . properties . CREATE_FGONS ,
self . properties . CREATE_SMOOTH_GROUPS ,
self . properties . CREATE_EDGES ,
self . properties . SPLIT_OBJECTS ,
self . properties . SPLIT_GROUPS ,
self . properties . SPLIT_MATERIALS ,
self . properties . ROTATE_X90 ,
self . properties . IMAGE_SEARCH ,
self . properties . POLYGROUPS )
2009-09-29 15:27:00 +00:00
return ( ' FINISHED ' , )
def invoke ( self , context , event ) :
wm = context . manager
2009-11-02 08:32:00 +00:00
wm . add_fileselect ( self )
2009-09-29 15:27:00 +00:00
return ( ' RUNNING_MODAL ' , )
bpy . ops . add ( IMPORT_OT_obj )
- add torus back from 2.4x as an operator
bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops - MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
2009-10-10 21:23:20 +00:00
import dynamic_menu
2009-11-23 00:27:30 +00:00
menu_func = lambda self , context : self . layout . operator ( IMPORT_OT_obj . bl_idname , text = " Wavefront (.obj)... " )
- add torus back from 2.4x as an operator
bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops - MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
2009-10-10 21:23:20 +00:00
menu_item = dynamic_menu . add ( bpy . types . INFO_MT_file_import , menu_func )
2009-09-29 15:27:00 +00:00
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file)
# check later: line 489
# can convert now: edge flags, edges: lines 508-528
# ngon (uses python module BPyMesh): 384-414
# nurbs: 947-
# NEXT clamp size: get bound box with RNA
# get back to l 140 (here)
# search image in bpy.config.textureDir - load_image
# replaced BPyImage.comprehensiveImageLoad with a simplified version that only checks additional directory specified, but doesn't search dirs recursively (obj_image_load)
# bitmask won't work? - 132
2009-11-29 22:16:29 +00:00
# uses operator bpy.ops.OBJECT_OT_select_all() to deselect all (not necessary?)
2009-09-29 15:27:00 +00:00
# uses bpy.sys.time()