Profile
Pastes: 44965
Members: 629

Oh, look!

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

Short URL: N/A

Pasted as text by antonio on Monday, April 20th, 2009 6:31am ( 3 years ago )

  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.  

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