2006-09-04 04:23:55 +00:00
#!BPY
"""
Name : ' Wavefront (.obj)... '
2009-06-13 03:05:20 +00:00
Blender : 249
2006-09-04 04:23:55 +00:00
Group : ' Import '
Tooltip : ' Load a Wavefront OBJ File, Shift: batch import all dir. '
"""
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-06-26 21:51:23 +00:00
__version__ = " 2.13 "
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-06-18 16:01:47 +00:00
# Script copyright (C) Campbell J Barton 2007-2009
# - V2.12- bspline import/export added (funded by PolyDimensions GmbH)
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-06-13 04:31:30 +00:00
from Blender import Mesh , Draw , Window , Texture , Material , sys
2007-03-27 14:49:37 +00:00
import bpy
2006-09-04 04:23:55 +00:00
import BPyMesh
import BPyImage
2006-09-26 04:39:46 +00:00
import BPyMessages
2006-09-04 04:23:55 +00:00
2006-11-02 17:42:30 +00:00
try : import os
except : os = False
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 ]
return ' %s %s ' % ( path , sys . sep )
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
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 : ] )
2006-09-20 05:03:53 +00:00
def obj_image_load ( imagepath , DIR , IMAGE_SEARCH ) :
'''
Mainly uses comprehensiveImageLoad
but tries to replace ' _ ' with ' ' for Max ' s exporter replaces spaces with underscores.
'''
2006-09-20 17:11:45 +00:00
2006-09-20 05:03:53 +00:00
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-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 ) :
2007-04-18 14:40:01 +00:00
texture = bpy . data . textures . new ( type )
2006-09-04 04:23:55 +00:00
texture . setType ( ' Image ' )
# Absolute path - c:\.. etc would work here
2006-09-20 05:03:53 +00:00
image = obj_image_load ( imagepath , DIR , IMAGE_SEARCH )
2006-11-27 23:59:53 +00:00
has_data = image . has_data
2006-10-05 11:15:22 +00:00
texture . image = image
2009-06-29 02:37:44 +00:00
if not has_data :
try :
# first time using this image. We need to load it first
image . glLoad ( )
except :
# probably the image is crashed
pass
else :
has_data = image . has_data
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
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
else :
blender_material . setTexture ( 0 , texture , Texture . TexCo . UV , Texture . MapTo . COL )
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 ' :
blender_material . setTexture ( 1 , texture , Texture . TexCo . UV , Texture . MapTo . CMIR ) # TODO- Add AMB to BPY API
elif type == ' Ks ' :
blender_material . setTexture ( 2 , texture , Texture . TexCo . UV , Texture . MapTo . SPEC )
elif type == ' Bump ' :
blender_material . setTexture ( 3 , texture , Texture . TexCo . UV , Texture . MapTo . NOR )
elif type == ' D ' :
blender_material . setTexture ( 4 , texture , Texture . TexCo . UV , Texture . MapTo . ALPHA )
2006-10-05 11:15:22 +00:00
blender_material . mode | = Material . Modes . ZTRANSP
blender_material . alpha = 0.0
# Todo, unset deffuse material alpha if it has an alpha channel
2006-09-04 04:23:55 +00:00
elif type == ' refl ' :
blender_material . setTexture ( 5 , texture , Texture . TexCo . UV , Texture . MapTo . REF )
# Add an MTL with the same name as the obj if no MTLs are spesified.
temp_mtl = stripExt ( stripPath ( filepath ) ) + ' .mtl '
2006-09-20 17:11:45 +00:00
if sys . exists ( DIR + temp_mtl ) and temp_mtl not in material_libs :
2006-09-04 04:23:55 +00:00
material_libs . append ( temp_mtl )
del temp_mtl
#Create new materials
2009-06-13 09:33:55 +00:00
for name in unique_materials : # .keys()
if name != None :
unique_materials [ name ] = bpy . data . materials . new ( name )
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
if not sys . exists ( mtlpath ) :
#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 ( ) )
if unique_materials . has_key ( context_material_name ) :
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 ' ) :
2006-09-04 04:23:55 +00:00
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 ' ) :
2006-09-04 04:23:55 +00:00
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 ' ) :
2006-09-04 04:23:55 +00:00
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 ' ) :
2006-09-04 04:23:55 +00:00
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
2006-09-04 04:23:55 +00:00
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 ' ) :
2006-09-04 04:23:55 +00:00
context_material . setAlpha ( float ( line_split [ 1 ] ) )
2009-06-26 21:51:23 +00:00
context_material . mode | = Material . Modes . ZTRANSP
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 ]
if matname and not unique_materials_split . has_key ( matname ) :
unique_materials_split [ matname ] = unique_materials [ matname ]
faces_split . append ( face )
# remove one of the itemas and reorder
2007-01-13 03:07:04 +00:00
return [ ( value [ 0 ] , value [ 1 ] , value [ 2 ] , key_to_name ( key ) ) for key , value in face_split_dict . iteritems ( ) ]
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 = { }
smooth_group_users = dict ( [ ( context_smooth_group , { } ) for context_smooth_group in unique_smooth_groups . iterkeys ( ) ] )
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
for f_idx in xrange ( len ( faces ) - 1 , - 1 , - 1 ) :
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) )
edges . extend ( [ ( face_vert_loc_indicies [ i ] , face_vert_loc_indicies [ i + 1 ] ) for i in xrange ( len_face_vert_loc_indicies - 1 ) ] )
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
for i in xrange ( len_face_vert_loc_indicies ) :
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 :
ngon_face_indices = BPyMesh . ngon ( verts_loc , face_vert_loc_indicies )
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
for key , users in edge_users . iteritems ( ) :
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 :
for edge_dict in smooth_group_users . itervalues ( ) :
for key , users in edge_dict . iteritems ( ) :
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 )
for name , index in material_mapping . iteritems ( ) :
materials [ index ] = unique_materials [ name ]
2007-04-18 14:40:01 +00:00
me = bpy . data . meshes . new ( dataname )
2006-09-04 04:23:55 +00:00
me . materials = materials [ 0 : 16 ] # make sure the list isnt too big.
#me.verts.extend([(0,0,0)]) # dummy vert
me . verts . extend ( verts_loc )
face_mapping = me . faces . extend ( [ f [ 0 ] for f in faces ] , indexList = True )
if verts_tex and me . faces :
me . faceUV = 1
# 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
2006-10-05 11:15:22 +00:00
ALPHA = Mesh . FaceTranspModes . ALPHA
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 :
face_index_map = face_mapping [ i ]
if face_index_map != None : # None means the face wasnt added
2007-01-26 06:02:21 +00:00
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
blender_face . mat = mat
if verts_tex :
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.
blender_face . image = image
2006-11-27 23:59:53 +00:00
if has_data and image . depth == 32 :
2006-10-05 11:15:22 +00:00
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
for ii , uv in enumerate ( blender_face . uv ) :
uv . x , uv . y = verts_tex [ face_vert_tex_indicies [ ii ] ]
del me_faces
2006-10-05 11:15:22 +00:00
del ALPHA
2006-09-04 04:23:55 +00:00
# Add edge faces.
me_edges = me . edges
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
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
if CREATE_EDGES :
2007-01-26 06:02:21 +00:00
me_edges . extend ( edges )
del me_edges
2006-09-04 04:23:55 +00:00
2006-12-28 22:56:24 +00:00
me . calcNormals ( )
2006-09-04 04:23:55 +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
for group_name , group_indicies in vertex_groups . iteritems ( ) :
me . addVertGroup ( group_name )
me . assignVertsToGroup ( group_name , group_indicies , 1.00 , Mesh . AssignModes . REPLACE )
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 :
print ' \t Warning, cstype not found '
return
if cstype != ' bspline ' :
print ' \t Warning, cstype is not supported (only bspline) '
return
if not curv_idx :
print ' \t Warning, curv argument empty or not set '
return
if len ( deg ) > 1 or parm_v :
print ' \t Warning, surfaces not supported '
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
for i in xrange ( deg [ 0 ] + 1 ) :
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 ,
CLAMP_SIZE = 0.0 ,
CREATE_FGONS = True ,
CREATE_SMOOTH_GROUPS = True ,
CREATE_EDGES = True ,
SPLIT_OBJECTS = True ,
SPLIT_GROUPS = True ,
SPLIT_MATERIALS = True ,
2009-06-13 03:05:20 +00:00
ROTATE_X90 = True ,
2009-05-13 00:20:14 +00:00
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
'''
2006-09-04 04:23:55 +00:00
print ' \n importing obj " %s " ' % filepath
2009-05-13 00:20:14 +00:00
if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS :
POLYGROUPS = False
2006-09-04 04:23:55 +00:00
time_main = sys . time ( )
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-04-29 10:24:12 +00:00
print ' \t parsing obj file " %s " ... ' % filepath ,
2006-09-04 04:23:55 +00:00
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 ( )
time_new = sys . time ( )
print ' %.4f sec ' % ( time_new - time_sub )
time_sub = time_new
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 )
2006-09-04 04:23:55 +00:00
time_new = sys . time ( )
print ' %.4f sec ' % ( time_new - time_sub )
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
2007-04-18 14:40:01 +00:00
scn = bpy . data . scenes . active
2007-04-14 17:44:50 +00:00
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
2007-01-26 06:02:21 +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
create_mesh ( scn , 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
for context_nurbs in nurbs :
create_nurbs ( scn , context_nurbs , verts_loc , new_objects )
2006-09-05 06:45:39 +00:00
axis_min = [ 1000000000 ] * 3
axis_max = [ - 1000000000 ] * 3
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
# 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
while CLAMP_SIZE < max_axis * scale :
scale = scale / 10.0
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
2006-09-04 04:23:55 +00:00
time_new = sys . time ( )
2006-09-05 06:45:39 +00:00
print ' %.4f sec ' % ( time_new - time_sub )
2006-09-04 04:23:55 +00:00
print ' finished importing: " %s " in %.4f sec. ' % ( filepath , ( time_new - time_main ) )
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 ]
print ' Trying to open web browser with documentation at this address... '
print ' \t ' + url
try :
import webbrowser
webbrowser . open ( url )
except :
print ' ...could not open a browser window. '
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
2006-09-04 04:23:55 +00:00
if __name__ == ' __main__ ' and not DEBUG :
2006-11-02 17:42:30 +00:00
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 ' )
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 )
'''
#load_obj('/test.obj')
#load_obj('/fe/obj/mba1.obj')