Profile

Welcome, guest!

Would you like to Login, or Register?

What are the benefits of registering?

Pastes: 22015

Quickie

If you tried registering a few days ago and didn't get the email activation reply, try now. Sorry!

Poll

Do you like Microsoft's Windows 7?

Yes
No
Undecided

Top Code
text5099
bash1552
cpp1382
php1097
c813
java705
html4strict514
python478
javascript380
csharp318
Top Members

Edit code: here. | Add this PasteBin to your website. | Report abuse.

Pasted as c by amelia on Monday, February 8th, 2010 9:22pm

  1. #!BPY
  2.  
  3. """
  4. Name: 'Wavefront (.obj)...'
  5. Blender: 242
  6. Group: 'Import'
  7. Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.'
  8. """
  9.  
  10. __author__= "Campbell Barton", "Jiri Hnidek", "and then twak mucked it up"
  11. __url__= ["blender.org", "blenderartists.org"]
  12. __version__= "2.0 +0.1i"
  13.  
  14. __bpydoc__= """
  15. This script imports a Wavefront OBJ files to Blender.
  16.  
  17. Usage:
  18. Run this script from "File->Import" menu and then load the desired OBJ file.
  19. Note, This loads mesh objects and materials only, nurbs and curves are not supported.
  20. """
  21.  
  22. # ***** BEGIN GPL LICENSE BLOCK *****
  23. #
  24. # Script copyright (C) Campbell J Barton 2007
  25. #
  26. # This program is free software; you can redistribute it and/or
  27. # modify it under the terms of the GNU General Public License
  28. # as published by the Free Software Foundation; either version 2
  29. # of the License, or (at your option) any later version.
  30. #
  31. # This program is distributed in the hope that it will be useful,
  32. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  34. # GNU General Public License for more details.
  35. #
  36. # You should have received a copy of the GNU General Public License
  37. # along with this program; if not, write to the Free Software Foundation,
  38. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  39. #
  40. # ***** END GPL LICENCE BLOCK *****
  41. # --------------------------------------------------------------------------
  42.  
  43. from Blender import *
  44. import bpy
  45. import BPyMesh
  46. import BPyImage
  47. import BPyMessages
  48.  
  49. try:  import os
  50. except:  os= False
  51.  
  52.  
  53. # Generic path functions
  54. def stripFile(path):
  55.  '''Return directory, where the file is'''
  56.  lastSlash= max(path.rfind(''), path.rfind('/'))
  57.  if lastSlash != -1:
  58.   path= path[:lastSlash]
  59.  return '%s%s' % (path, sys.sep)
  60.  
  61. def stripPath(path):
  62.  '''Strips the slashes from the back of a string'''
  63.  return path.split('/')[-1].split('')[-1]
  64.  
  65. def stripExt(name): # name is a string
  66.  '''Strips the prefix off the name before writing'''
  67.  index= name.rfind('.')
  68.  if index != -1:
  69.   return name[ : index ]
  70.  else:
  71.   return name
  72. # end path funcs
  73.  
  74.  
  75.  
  76. def line_value(line_split):
  77.  '''
  78. Returns 1 string represneting the value for this line
  79. None will be returned if theres only 1 word
  80. '''
  81.  length= len(line_split)
  82.  if length == 1:
  83.   return None
  84.  
  85.  elif length == 2:
  86.   return line_split[1]
  87.  
  88.  elif length > 2:
  89.   return ' '.join( line_split[1:] )
  90.  
  91. def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
  92.  '''
  93. Mainly uses comprehensiveImageLoad
  94. but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
  95.  '''
  96.  
  97. if '_' in imagepath:
  98.  image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
  99.  if image: return image
  100.  # Did the exporter rename the image?
  101.  image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
  102.  if image: return image
  103.  
  104. # Return an image, placeholder if it dosnt exist
  105. image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
  106. return image
  107.  
  108.  
  109. def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH):
  110. '''
  111.  Create all the used materials in this obj,
  112.  assign colors and images to the materials from all referenced material libs
  113.  '''
  114. DIR= stripFile(filepath)
  115.  
  116. #==================================================================================#
  117. # This function sets textures defined in .mtl file                                 #
  118. #==================================================================================#
  119. def load_material_image(blender_material, context_material_name, imagepath, type):
  120.  
  121.  texture= bpy.data.textures.new(type)
  122.  texture.setType('Image')
  123.  
  124.  # Absolute path - c:.. etc would work here
  125.  image= obj_image_load(imagepath, DIR, IMAGE_SEARCH)
  126.  has_data = image.has_data
  127.  texture.image = image
  128.  
  129.  # Adds textures for materials (rendering)
  130.  if type == 'Kd':
  131.   if has_data and image.depth == 32:
  132.    # Image has alpha
  133.    blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL | Texture.MapTo.ALPHA)
  134.    texture.setImageFlags('MipMap', 'InterPol', 'UseAlpha')
  135.    blender_material.mode |= Material.Modes.ZTRANSP
  136.    blender_material.alpha = 0.0
  137.   else:
  138.    blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL)
  139.    
  140.   # adds textures to faces (Textured/Alt-Z mode)
  141.   # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
  142.   unique_material_images[context_material_name]= image, has_data # set the texface image
  143.  
  144.  elif type == 'Ka':
  145.   blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API
  146.  
  147.  elif type == 'Ks':
  148.   blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
  149.  
  150.  elif type == 'Bump':
  151.   blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR)  
  152.  elif type == 'D':
  153.   blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)    
  154.   blender_material.mode |= Material.Modes.ZTRANSP
  155.   blender_material.alpha = 0.0
  156.   # Todo, unset deffuse material alpha if it has an alpha channel
  157.  
  158.  elif type == 'refl':
  159.   blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF)  
  160.  
  161.  
  162. # Add an MTL with the same name as the obj if no MTLs are spesified.
  163. temp_mtl= stripExt(stripPath(filepath))+ '.mtl'
  164.  
  165. if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
  166.   material_libs.append( temp_mtl )
  167. del temp_mtl
  168.  
  169. #Create new materials
  170. for name in unique_materials.iterkeys():
  171.  unique_materials[name]= bpy.data.materials.new(name)
  172.  
  173.  unique_material_images[name]= None, False # assign None to all material images to start with, add to later.
  174.  
  175. unique_materials[None]= None
  176.  
  177. for libname in material_libs:
  178.  mtlpath= DIR + libname
  179.  if not sys.exists(mtlpath):
  180.   #print ' Error Missing MTL: "%s"' % mtlpath
  181.   pass
  182.  else:
  183.   #print '  loading mtl: "%s"' % mtlpath
  184.   context_material= None
  185.   mtl= open(mtlpath)
  186.   for line in mtl.xreadlines():
  187.    if line.startswith('newmtl'):
  188.     context_material_name= line_value(line.split())
  189.     if unique_materials.has_key(context_material_name):
  190.      context_material = unique_materials[ context_material_name ]
  191.     else:
  192.      context_material = None
  193.    
  194.    elif context_material:
  195.     # we need to make a material to assign properties to it.
  196.     line_split= line.split()
  197.     line_lower= line.lower()
  198.     if line_lower.startswith('ka'):
  199.      context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
  200.     elif line_lower.startswith('kd'):
  201.      context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
  202.     elif line_lower.startswith('ks'):
  203.      context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
  204.     elif line_lower.startswith('ns'):
  205.      context_material.setHardness( int((float(line_split[1])*0.51)) )
  206.     elif line_lower.startswith('ni'): # Refraction index
  207.      context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
  208.     elif line_lower.startswith('d') or line_lower.startswith('tr'):
  209.      context_material.setAlpha(float(line_split[1]))
  210.     elif line_lower.startswith('map_ka'):
  211.      img_filepath= line_value(line.split())
  212.      if img_filepath:
  213.       load_material_image(context_material, context_material_name, img_filepath, 'Ka')
  214.     elif line_lower.startswith('map_ks'):
  215.      img_filepath= line_value(line.split())
  216.      if img_filepath:
  217.       load_material_image(context_material, context_material_name, img_filepath, 'Ks')
  218.     elif line_lower.startswith('map_kd'):
  219.      img_filepath= line_value(line.split())
  220.      if img_filepath:
  221.       load_material_image(context_material, context_material_name, img_filepath, 'Kd')
  222.     elif line_lower.startswith('map_bump'):
  223.      img_filepath= line_value(line.split())
  224.      if img_filepath:
  225.       load_material_image(context_material, context_material_name, img_filepath, 'Bump')
  226.     elif line_lower.startswith('map_d') or line_lower.startswith('map_tr'): # Alpha map - Dissolve
  227.      img_filepath= line_value(line.split())
  228.      if img_filepath:
  229.       load_material_image(context_material, context_material_name, img_filepath, 'D')
  230.    
  231.     elif line_lower.startswith('refl'): # Reflectionmap
  232.      img_filepath= line_value(line.split())
  233.      if img_filepath:
  234.       load_material_image(context_material, context_material_name, img_filepath, 'refl')
  235.   mtl.close()
  236.  
  237.  
  238.  
  239.  
  240. def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS):
  241. '''
  242.  Takes vert_loc and faces, and seperates into multiple sets of
  243.  (verts_loc, faces, unique_materials, dataname)
  244.  This is done so objects do not overload the 16 material limit.
  245.  '''
  246.  
  247. filename = stripExt(stripPath(filepath))
  248.  
  249. if not SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
  250.  # use the filename for the object name since we arnt chopping up the mesh.
  251.  return [(verts_loc, faces, unique_materials, filename)]
  252.  
  253.  
  254. def key_to_name(key):
  255.  # if the key is a tuple, join it to make a string
  256.  if type(key) == tuple:
  257.   return '%s_%s' % key
  258.  elif not key:
  259.   return filename # assume its a string. make sure this is true if the splitting code is changed
  260.  else:
  261.   return key
  262.  
  263. # Return a key that makes the faces unique.
  264. if SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
  265.  def face_key(face):
  266.   return face[4] # object
  267.  
  268. elif not SPLIT_OB_OR_GROUP and SPLIT_MATERIALS:
  269.  def face_key(face):
  270.   return face[2] # material
  271.  
  272. else: # Both
  273.  def face_key(face):
  274.   return face[4], face[2] # object,material  
  275.  
  276.  
  277. face_split_dict= {}
  278.  
  279. oldkey= -1 # initialize to a value that will never match the key
  280.  
  281. for face in faces:
  282.  
  283.  key= face_key(face)
  284.  
  285.  if oldkey != key:
  286.   # Check the key has changed.
  287.   try:
  288.    verts_split, faces_split, unique_materials_split, vert_remap= face_split_dict[key]
  289.   except KeyError:
  290.    faces_split= []
  291.    verts_split= []
  292.    unique_materials_split= {}
  293.    vert_remap= [-1]*len(verts_loc)
  294.    
  295.    face_split_dict[key]= (verts_split, faces_split, unique_materials_split, vert_remap)
  296.  
  297.   oldkey= key
  298.  
  299.  face_vert_loc_indicies= face[0]
  300.  
  301.  # Remap verts to new vert list and add where needed
  302.  for enum, i in enumerate(face_vert_loc_indicies):
  303.   if vert_remap[i] == -1:
  304.    new_index= len(verts_split)
  305.    vert_remap[i]= new_index # set the new remapped index so we only add once and can reference next time.
  306.    face_vert_loc_indicies[enum] = new_index # remap to the local index
  307.    verts_split.append( verts_loc[i] ) # add the vert to the local verts
  308.    
  309.   else:
  310.    face_vert_loc_indicies[enum] = vert_remap[i] # remap to the local index
  311.  
  312.   matname= face[2]
  313.   if matname and not unique_materials_split.has_key(matname):
  314.    unique_materials_split[matname] = unique_materials[matname]
  315.  
  316.  faces_split.append(face)
  317.  
  318.  
  319. # remove one of the itemas and reorder
  320. return [(value[0], value[1], value[2], key_to_name(key)) for key, value in face_split_dict.iteritems()]
  321.  
  322.  
  323. 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):
  324. '''
  325.  Takes all the data gathered and generates a mesh, adding the new object to new_objects
  326.  deals with fgons, sharp edges and assigning materials
  327.  '''
  328. if not has_ngons:
  329.  CREATE_FGONS= False
  330.  
  331. if unique_smooth_groups:
  332.  sharp_edges= {}
  333.  smooth_group_users= dict([ (context_smooth_group, {}) for context_smooth_group in unique_smooth_groups.iterkeys() ])
  334.  context_smooth_group_old= -1
  335.  
  336. # Split fgons into tri's
  337.  fgon_edges= {} # Used for storing fgon keys
  338.  if CREATE_EDGES:
  339.   edges= []
  340.  
  341.  context_object= None
  342.  
  343.  # reverse loop through face indicies
  344.  for f_idx in xrange(len(faces)-1, -1, -1):
  345.  
  346.   face_vert_loc_indicies,
  347.   face_vert_tex_indicies,
  348.   context_material,
  349.   context_smooth_group,
  350.   context_object= faces[f_idx]
  351.  
  352.   len_face_vert_loc_indicies = len(face_vert_loc_indicies)
  353.  
  354.   if len_face_vert_loc_indicies==1:
  355.    faces.pop(f_idx)# cant add single vert faces
  356.  
  357.   elif not face_vert_tex_indicies or len_face_vert_loc_indicies == 2: # faces that have no texture coords are lines
  358.    if CREATE_EDGES:
  359.     # generators are better in python 2.4+ but can't be used in 2.3
  360.     # edges.extend( (face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1) )
  361.     edges.extend( [(face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1)] )
  362.  
  363.    faces.pop(f_idx)
  364.   else:
  365.    
  366.    # Smooth Group
  367.    if unique_smooth_groups and context_smooth_group:
  368.     # Is a part of of a smooth group and is a face
  369.     if context_smooth_group_old is not context_smooth_group:
  370.      edge_dict= smooth_group_users[context_smooth_group]
  371.      context_smooth_group_old= context_smooth_group
  372.    
  373.     for i in xrange(len_face_vert_loc_indicies):
  374.      i1= face_vert_loc_indicies[i]
  375.      i2= face_vert_loc_indicies[i-1]
  376.      if i1>i2: i1,i2= i2,i1
  377.      
  378.      try:
  379.       edge_dict[i1,i2]+= 1
  380.      except KeyError:
  381.       edge_dict[i1,i2]=  1
  382.    
  383.    # FGons into triangles
  384.    if has_ngons and len_face_vert_loc_indicies > 3:
  385.    
  386.     ngon_face_indices= BPyMesh.ngon(verts_loc, face_vert_loc_indicies)
  387.     faces.extend(
  388.     [(
  389.     [face_vert_loc_indicies[ngon[0]], face_vert_loc_indicies[ngon[1]], face_vert_loc_indicies[ngon[2]] ],
  390.     [face_vert_tex_indicies[ngon[0]], face_vert_tex_indicies[ngon[1]], face_vert_tex_indicies[ngon[2]] ],
  391.     context_material,
  392.     context_smooth_group,
  393.     context_object)
  394.     for ngon in ngon_face_indices]
  395.     )
  396.    
  397.     # edges to make fgons
  398.     if CREATE_FGONS:
  399.      edge_users= {}
  400.      for ngon in ngon_face_indices:
  401.       for i in (0,1,2):
  402.        i1= face_vert_loc_indicies[ngon[i  ]]
  403.        i2= face_vert_loc_indicies[ngon[i-1]]
  404.        if i1>i2: i1,i2= i2,i1
  405.        
  406.        try:
  407.         edge_users[i1,i2]+=1
  408.        except KeyError:
  409.         edge_users[i1,i2]= 1
  410.      
  411.      for key, users in edge_users.iteritems():
  412.       if users>1:
  413.        fgon_edges[key]= None
  414.    
  415.     # remove all after 3, means we dont have to pop this one.
  416.     faces.pop(f_idx)
  417.  
  418.  
  419.  # Build sharp edges
  420.  if unique_smooth_groups:
  421.   for edge_dict in smooth_group_users.itervalues():
  422.    for key, users in edge_dict.iteritems():
  423.     if users==1: # This edge is on the boundry of a group
  424.      sharp_edges[key]= None
  425.  
  426.  
  427.  # mat the material names to an index
  428.  material_mapping= dict([(name, i) for i, name in enumerate(unique_materials.keys())])
  429.  
  430.  materials= [None] * len(unique_materials)
  431.  
  432.  for name, index in material_mapping.iteritems():
  433.   materials[index]= unique_materials[name]
  434.  
  435.  me= bpy.data.meshes.new(dataname)
  436.  
  437.  me.materials= materials[0:16] # make sure the list isnt too big.
  438.  #me.verts.extend([(0,0,0)]) # dummy vert
  439.  me.verts.extend(verts_loc)
  440.  
  441.  face_mapping= me.faces.extend([f[0] for f in faces], indexList=True)
  442.  
  443.  if verts_tex and me.faces:
  444.   me.faceUV= 1
  445.   # TEXMODE= Mesh.FaceModes['TEX']
  446.  
  447.  context_material_old= -1 # avoid a dict lookup
  448.  mat= 0 # rare case it may be un-initialized.
  449.  me_faces= me.faces
  450.  ALPHA= Mesh.FaceTranspModes.ALPHA
  451.  
  452.  for i, face in enumerate(faces):
  453.   if len(face[0]) < 2:
  454.    pass #raise "bad face"
  455.   elif len(face[0])==2:
  456.    if CREATE_EDGES:
  457.     edges.append(face[0])
  458.   else:
  459.    face_index_map= face_mapping[i]
  460.    if face_index_map!=None: # None means the face wasnt added
  461.     blender_face= me_faces[face_index_map]
  462.    
  463.     face_vert_loc_indicies,
  464.     face_vert_tex_indicies,
  465.     context_material,
  466.     context_smooth_group,
  467.     context_object= face
  468.    
  469.    
  470.    
  471.     if context_smooth_group:
  472.      blender_face.smooth= True
  473.    
  474.     if context_material:
  475.      if context_material_old is not context_material:
  476.       mat= material_mapping[context_material]
  477.       if mat>15:
  478.        mat= 15
  479.       context_material_old= context_material
  480.      
  481.      blender_face.mat= mat
  482.    
  483.    
  484.     if verts_tex:
  485.      if context_material:
  486.       image, has_data= unique_material_images[context_material]
  487.       if image: # Can be none if the material dosnt have an image.
  488.        blender_face.image= image
  489.        if has_data and image.depth == 32:
  490.         blender_face.transp |= ALPHA
  491.      
  492.      # BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled.
  493.      if len(face_vert_loc_indicies)==4:
  494.       if face_vert_loc_indicies[2]==0 or face_vert_loc_indicies[3]==0:
  495.        face_vert_tex_indicies= face_vert_tex_indicies[2], face_vert_tex_indicies[3], face_vert_tex_indicies[0], face_vert_tex_indicies[1]
  496.      else: # length of 3
  497.       if face_vert_loc_indicies[2]==0:
  498.        face_vert_tex_indicies= face_vert_tex_indicies[1], face_vert_tex_indicies[2], face_vert_tex_indicies[0]
  499.      # END EEEKADOODLE FIX
  500.      
  501.      # assign material, uv's and image
  502.      for ii, uv in enumerate(blender_face.uv):
  503.       uv.x, uv.y=  verts_tex[face_vert_tex_indicies[ii]]
  504.  del me_faces
  505.  del ALPHA
  506.  
  507.  # Add edge faces.
  508.  me_edges= me.edges
  509.  if CREATE_FGONS and fgon_edges:
  510.   FGON= Mesh.EdgeFlags.FGON
  511.   for ed in me.findEdges( fgon_edges.keys() ):
  512.    if ed!=None:
  513.     me_edges[ed].flag |= FGON
  514.   del FGON
  515.  
  516.  if unique_smooth_groups and sharp_edges:
  517.   SHARP= Mesh.EdgeFlags.SHARP
  518.   for ed in me.findEdges( sharp_edges.keys() ):
  519.    if ed!=None:
  520.     me_edges[ed].flag |= SHARP
  521.   del SHARP
  522.  
  523.  if CREATE_EDGES:
  524.   me_edges.extend( edges )
  525.  
  526.  del me_edges
  527.  
  528.  me.calcNormals()
  529.  
  530.  ob= scn.objects.new(me)
  531.  new_objects.append(ob)
  532.  
  533. def get_float_func(filepath):
  534.  '''
  535. find the float function for this obj file
  536. - weather to replace commas or not
  537. '''
  538.  file= open(filepath, 'rU')
  539.  for line in file: #.xreadlines():
  540.   if line.startswith('v'): # vn vt v
  541.    if ',' in line:
  542.     return lambda f: float(f.replace(',', '.'))
  543.    elif '.' in line:
  544.     return float
  545.  
  546. 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, IMAGE_SEARCH=True, FRAME=0):
  547.  '''
  548. Called by the user interface or another script.
  549. load_obj(path) - should give acceptable results.
  550. This function passes the file and sends the data off
  551.  to be split into objects and then converted into mesh objects
  552. '''
  553.  print '
  554. importing obj "%s"' % filepath
  555.  
  556.  time_main= sys.time()
  557.  
  558.  verts_loc= []
  559.  verts_tex= []
  560.  faces= [] # tuples of the faces
  561.  material_libs= [] # filanems to material libs this uses
  562.  
  563.  
  564.  # Get the string to float conversion func for this file- is 'float' for almost all files.
  565.  float_func= get_float_func(filepath)
  566.  
  567.  # Context variables
  568.  context_material= None
  569.  context_smooth_group= None
  570.  context_object= None
  571.  
  572.  has_ngons= False
  573.  # has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0
  574.  
  575.  # Until we can use sets
  576.  unique_materials= {}
  577.  unique_material_images= {}
  578.  unique_smooth_groups= {}
  579.  # unique_obects= {} - no use for this variable since the objects are stored in the face.
  580.  
  581.  # when there are faces that end with
  582.  # it means they are multiline-
  583.  # since we use xreadline we cant skip to the next line
  584.  # so we need to know weather
  585.  multi_line_face= False
  586.  
  587.  print ' passing obj file "%s"...' % filepath,
  588.  time_sub= sys.time()
  589.  file= open(filepath, 'rU')
  590.  for line in file: # .xreadlines()
  591.  
  592.   if line.startswith('v '):
  593.    line_split= line.split()
  594.    # rotate X90: (x,-z,y)
  595.    verts_loc.append( (float_func(line_split[1]), -float_func(line_split[3]), float_func(line_split[2])) )
  596.    
  597.   elif line.startswith('vn '):
  598.    pass
  599.  
  600.   elif line.startswith('vt '):
  601.    line_split= line.split()
  602.    verts_tex.append( (float_func(line_split[1]), float_func(line_split[2])) )
  603.  
  604.   # Handel faces lines (as faces) and the second+ lines of fa multiline face here
  605.   # use 'f' not 'f ' because some objs (very rare have 'fo ' for faces)
  606.   elif line.startswith('f') or (line.startswith('l ') and CREATE_EDGES) or multi_line_face:
  607.    
  608.    if multi_line_face:
  609.     # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
  610.     line_split= line.split()
  611.     multi_line_face= False
  612.    
  613.    else:
  614.     line_split= line[2:].split()
  615.     face_vert_loc_indicies= []
  616.     face_vert_tex_indicies= []
  617.    
  618.     # Instance a face
  619.     faces.append((
  620.     face_vert_loc_indicies,
  621.     face_vert_tex_indicies,
  622.     context_material,
  623.     context_smooth_group,
  624.     context_object
  625.     ))
  626.    
  627.    if line_split[-1][-1]== '':
  628.     multi_line_face= True
  629.     if len(line_split[-1])==1:
  630.      line_split.pop() # remove the  item
  631.     else:
  632.      line_split[-1]= line_split[-1][:-1] # remove the  from the end last number
  633.    
  634.    isline= line.startswith('l')
  635.    
  636.    for v in line_split:
  637.     obj_vert= v.split('/')
  638.    
  639.     vert_loc_index= int(obj_vert[0])-1
  640.    
  641.     # Make relative negative vert indicies absolute
  642.     if vert_loc_index < 0:
  643.      vert_loc_index= len(verts_loc) + vert_loc_index + 1
  644.    
  645.     face_vert_loc_indicies.append(vert_loc_index)
  646.    
  647.     if not isline:
  648.      if len(obj_vert)>1 and obj_vert[1]:
  649.       # formatting for faces with normals and textures us
  650.       # loc_index/tex_index/nor_index
  651.      
  652.       vert_tex_index= int(obj_vert[1])-1
  653.       # Make relative negative vert indicies absolute
  654.       if vert_tex_index < 0:
  655.        vert_tex_index= len(verts_tex) + vert_tex_index + 1
  656.      
  657.       face_vert_tex_indicies.append(vert_tex_index)
  658.      else:
  659.       # dummy
  660.       face_vert_tex_indicies.append(0)
  661.    
  662.    if len(face_vert_loc_indicies) > 4:
  663.     has_ngons= True
  664.    
  665.   elif line.startswith('s'):
  666.    if CREATE_SMOOTH_GROUPS:
  667.     context_smooth_group= line_value(line.split())
  668.     if context_smooth_group=='off':
  669.      context_smooth_group= None
  670.     elif context_smooth_group: # is not None
  671.      unique_smooth_groups[context_smooth_group]= None
  672.  
  673.   elif line.startswith('o'):
  674.    if SPLIT_OBJECTS:
  675.     context_object= line_value(line.split())
  676.     # unique_obects[context_object]= None
  677.    
  678.   elif line.startswith('g'):
  679.    if SPLIT_GROUPS:
  680.     context_object= line_value(line.split())
  681.     # print 'context_object', context_object
  682.     # unique_obects[context_object]= None
  683.  
  684.   elif line.startswith('usemtl'):
  685.    context_material= line_value(line.split())
  686.    unique_materials[context_material]= None
  687.   elif line.startswith('mtllib'): # usemap or usemat
  688.    material_libs.extend( line.split()[1:] ) # can have multiple mtllib filenames per line
  689.  
  690.   ''' # How to use usemap? depricated?
  691.  elif line.startswith('usema'): # usemap or usemat
  692.   context_image= line_value(line.split())
  693.  '''
  694.  
  695.  file.close()
  696.  time_new= sys.time()
  697.  print '%.4f sec' % (time_new-time_sub)
  698.  time_sub= time_new
  699.  
  700.  
  701.  print ' loading materials and images...',
  702.  create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH)
  703.  
  704.  time_new= sys.time()
  705.  print '%.4f sec' % (time_new-time_sub)
  706.  time_sub= time_new
  707.  
  708.  
  709.  # deselect all
  710.  scn = bpy.data.scenes.active
  711.  scn.objects.selected = []
  712.  new_objects= [] # put new objects here
  713.  
  714.  print ' building geometry...
  715. verts:%i faces:%i materials: %i smoothgroups:%i ...' % ( len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups) ),
  716.  # Split the mesh by objects/materials, may
  717.  if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True
  718.  else:        SPLIT_OB_OR_GROUP = False
  719.  
  720.  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):
  721.   # Create meshes from the data
  722.   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, dataname)
  723.  
  724.  axis_min= [ 1000000000]*3
  725.  axis_max= [-1000000000]*3
  726.  
  727.  if CLAMP_SIZE:
  728.   # Get all object bounds
  729.   for ob in new_objects:
  730.    for v in ob.getBoundBox():
  731.     for axis, value in enumerate(v):
  732.      if axis_min[axis] > value: axis_min[axis]= value
  733.      if axis_max[axis] < value: axis_max[axis]= value
  734.  
  735.   # Scale objects
  736.   max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2])
  737.   scale= 1.0
  738.  
  739.   while CLAMP_SIZE < max_axis * scale:
  740.    scale= scale/10.0
  741.  
  742.   for ob in new_objects:
  743.    ob.setSize(scale, scale, scale)
  744.  
  745.  for ob in new_objects:
  746.   ipo = Ipo.New('Object','ipo for %s' % ob.getIpo())
  747.   ob.setIpo(ipo)
  748.   curve = ipo.addCurve('Layer')
  749.   curve.append((0,1))
  750.   curve.append((FRAME,2))
  751.   curve.append((FRAME+1,1))
  752.  
  753.   print '%s
  754. ' % ob.getIpo()
  755.  
  756.  time_new= sys.time()
  757.  
  758.  print '%.4f sec' % (time_new-time_sub)
  759.  print 'finished importing: "%s" in %.4f sec.' % (filepath, (time_new-time_main))
  760.  
  761.  
  762. DEBUG= True
  763.  
  764.  
  765. def load_obj_ui(filepath, BATCH_LOAD= False):
  766.  if BPyMessages.Error_NoFile(filepath):
  767.   return
  768.  
  769.  
  770.  CREATE_SMOOTH_GROUPS= Draw.Create(0)
  771.  CREATE_FGONS= Draw.Create(1)
  772.  CREATE_EDGES= Draw.Create(1)
  773.  SPLIT_OBJECTS= Draw.Create(1)
  774.  SPLIT_GROUPS= Draw.Create(1)
  775.  SPLIT_MATERIALS= Draw.Create(1)
  776.  MORPH_TARGET= Draw.Create(0)
  777.  CLAMP_SIZE= Draw.Create(10.0)
  778.  IMAGE_SEARCH= Draw.Create(1)
  779.  
  780.  
  781.  # Get USER Options
  782.  pup_block= [
  783.  'Import...',
  784.  ('twak Groups', CREATE_SMOOTH_GROUPS, 'Surround smooth groups by sharp edges'),
  785.  ('Create FGons', CREATE_FGONS, 'Import faces with more then 4 verts as fgons.'),
  786.  ('Lines', CREATE_EDGES, 'Import lines and faces with 2 verts as edges'),
  787.  'Separate objects from obj...',
  788.  ('Object', SPLIT_OBJECTS, 'Import OBJ Objects into Blender Objects'),
  789.  ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),
  790.  ('Material', SPLIT_MATERIALS, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)'),
  791.  'Options...',
  792.  ('Morph Target', MORPH_TARGET, 'Keep vert and face order, disables some other options.'),
  793.  ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),
  794.  ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),
  795.  ]
  796.  
  797.  if not Draw.PupBlock('Import OBJ...', pup_block):
  798.   return
  799.  
  800.  if MORPH_TARGET.val:
  801.   SPLIT_OBJECTS.val = False
  802.   SPLIT_GROUPS.val = False
  803.   SPLIT_MATERIALS.val = False
  804.  
  805.  Window.WaitCursor(1)
  806.  
  807.  if BATCH_LOAD: # load the dir
  808.   try:
  809.    files= [ f for f in os.listdir(filepath) if f.lower().endswith('.obj') ]
  810.   except:
  811.    Window.WaitCursor(0)
  812.    Draw.PupMenu('Error%t|Could not open path ' + filepath)
  813.    return
  814.  
  815.   if not files:
  816.    Window.WaitCursor(0)
  817.    Draw.PupMenu('Error%t|No files at path ' + filepath)
  818.    return
  819.  
  820.   files.sort()
  821.  
  822.   scn= bpy.data.scenes.new( stripExt(f) )
  823.   scn.makeCurrent()
  824.    
  825.   i = 0
  826.   for f in files:
  827.    load_obj(sys.join(filepath, f),
  828.      CLAMP_SIZE.val,
  829.      CREATE_FGONS.val,
  830.      CREATE_SMOOTH_GROUPS.val,
  831.      CREATE_EDGES.val,
  832.      SPLIT_OBJECTS.val,
  833.      SPLIT_GROUPS.val,
  834.      SPLIT_MATERIALS.val,
  835.      IMAGE_SEARCH.val,
  836.      i
  837.    )
  838.    i=i+1
  839.  
  840.  else: # We don't do this anymore!
  841.   load_obj(filepath,
  842.     CLAMP_SIZE.val,
  843.     CREATE_FGONS.val,
  844.     CREATE_SMOOTH_GROUPS.val,
  845.     CREATE_EDGES.val,
  846.     SPLIT_OBJECTS.val,
  847.     SPLIT_GROUPS.val,
  848.     SPLIT_MATERIALS.val,
  849.     IMAGE_SEARCH.val,
  850.   )
  851.  
  852.  Window.WaitCursor(0)
  853.  
  854.  
  855. def load_obj_ui_batch(file):
  856.  load_obj_ui(file, True)
  857.  
  858. DEBUG= False
  859.  
  860. #if __name__=='__main__' and not DEBUG:
  861. # if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT:
  862. Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '')
  863. #' else:
  864. #  Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
  865.  

Parent PasteBin: 5692
Your Name:
Code Language:
Security Image:
Text seen in Image: