- #!BPY
- """
- Name: 'Wavefront (.obj)...'
- Blender: 242
- Group: 'Import'
- Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.'
- """
- __author__= "Campbell Barton", "Jiri Hnidek", "and then twak mucked it up"
- __url__= ["blender.org", "blenderartists.org"]
- __version__= "2.0 +0.1i"
- __bpydoc__= """
- This script imports a Wavefront OBJ files to Blender.
- Usage:
- Run this script from "File->Import" menu and then load the desired OBJ file.
- Note, This loads mesh objects and materials only, nurbs and curves are not supported.
- """
- # ***** BEGIN GPL LICENSE BLOCK *****
- #
- # Script copyright (C) Campbell J Barton 2007
- #
- # 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 *****
- # --------------------------------------------------------------------------
- from Blender import *
- import bpy
- import BPyMesh
- import BPyImage
- import BPyMessages
- try: import os
- except: os= False
- # Generic path functions
- 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):
- '''Strips the slashes from the back of a string'''
- 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
- def line_value(line_split):
- '''
- Returns 1 string represneting the value for this line
- None will be returned if theres only 1 word
- '''
- length= len(line_split)
- if length == 1:
- return None
- elif length == 2:
- return line_split[1]
- elif length > 2:
- return ' '.join( line_split[1:] )
- 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
- def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH):
- '''
- Create all the used materials in this obj,
- assign colors and images to the materials from all referenced material libs
- '''
- DIR= stripFile(filepath)
- #==================================================================================#
- # This function sets textures defined in .mtl file #
- #==================================================================================#
- def load_material_image(blender_material, context_material_name, imagepath, type):
- texture= bpy.data.textures.new(type)
- texture.setType('Image')
- # Absolute path - c:.. etc would work here
- image= obj_image_load(imagepath, DIR, IMAGE_SEARCH)
- has_data = image.has_data
- texture.image = image
- # Adds textures for materials (rendering)
- if type == 'Kd':
- if has_data and image.depth == 32:
- # 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)
- # 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.
- unique_material_images[context_material_name]= image, has_data # set the texface image
- 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)
- blender_material.mode |= Material.Modes.ZTRANSP
- blender_material.alpha = 0.0
- # Todo, unset deffuse material alpha if it has an alpha channel
- 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'
- if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
- material_libs.append( temp_mtl )
- del temp_mtl
- #Create new materials
- for name in unique_materials.iterkeys():
- 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.
- unique_materials[None]= None
- for libname in material_libs:
- mtlpath= DIR + libname
- if not sys.exists(mtlpath):
- #print ' Error Missing MTL: "%s"' % mtlpath
- pass
- else:
- #print ' loading mtl: "%s"' % mtlpath
- context_material= None
- mtl= open(mtlpath)
- for line in mtl.xreadlines():
- 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()
- line_lower= line.lower()
- if line_lower.startswith('ka'):
- context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
- elif line_lower.startswith('kd'):
- context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
- elif line_lower.startswith('ks'):
- context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
- elif line_lower.startswith('ns'):
- context_material.setHardness( int((float(line_split[1])*0.51)) )
- elif line_lower.startswith('ni'): # Refraction index
- context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
- elif line_lower.startswith('d') or line_lower.startswith('tr'):
- context_material.setAlpha(float(line_split[1]))
- elif line_lower.startswith('map_ka'):
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'Ka')
- elif line_lower.startswith('map_ks'):
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'Ks')
- elif line_lower.startswith('map_kd'):
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'Kd')
- elif line_lower.startswith('map_bump'):
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'Bump')
- elif line_lower.startswith('map_d') or line_lower.startswith('map_tr'): # Alpha map - Dissolve
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'D')
- elif line_lower.startswith('refl'): # Reflectionmap
- img_filepath= line_value(line.split())
- if img_filepath:
- load_material_image(context_material, context_material_name, img_filepath, 'refl')
- mtl.close()
- def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS):
- '''
- Takes vert_loc and faces, and seperates into multiple sets of
- (verts_loc, faces, unique_materials, dataname)
- This is done so objects do not overload the 16 material limit.
- '''
- filename = stripExt(stripPath(filepath))
- if not SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
- # use the filename for the object name since we arnt chopping up the mesh.
- return [(verts_loc, faces, unique_materials, filename)]
- 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
- # Return a key that makes the faces unique.
- if SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
- def face_key(face):
- return face[4] # object
- elif not SPLIT_OB_OR_GROUP and SPLIT_MATERIALS:
- def face_key(face):
- return face[2] # material
- else: # Both
- def face_key(face):
- return face[4], face[2] # object,material
- face_split_dict= {}
- oldkey= -1 # initialize to a value that will never match the key
- for face in faces:
- key= face_key(face)
- if oldkey != key:
- # Check the key has changed.
- try:
- verts_split, faces_split, unique_materials_split, vert_remap= face_split_dict[key]
- except KeyError:
- faces_split= []
- verts_split= []
- unique_materials_split= {}
- vert_remap= [-1]*len(verts_loc)
- face_split_dict[key]= (verts_split, faces_split, unique_materials_split, vert_remap)
- 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
- return [(value[0], value[1], value[2], key_to_name(key)) for key, value in face_split_dict.iteritems()]
- 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, dataname):
- '''
- Takes all the data gathered and generates a mesh, adding the new object to new_objects
- deals with fgons, sharp edges and assigning materials
- '''
- 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
- elif not face_vert_tex_indicies or len_face_vert_loc_indicies == 2: # faces that have no texture coords are lines
- if CREATE_EDGES:
- # 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)] )
- faces.pop(f_idx)
- else:
- # Smooth Group
- if unique_smooth_groups and context_smooth_group:
- # 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 > 3:
- 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:
Edit code: here. | Add this PasteBin to your website. | Report abuse.
Pasted as text by antonio on Monday, April 20th, 2009 6:31am
Parent PasteBin: 5692