diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-06-12 08:16:12 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-06-12 08:16:12 +0400 |
commit | 96c5f36eff4ee85aad90c507070447a6ad5bdda9 (patch) | |
tree | c3b6550785d3e5e2895b6f99b9a33ea21d46e8fd /release/scripts/import_obj.py | |
parent | 642fea299b7ce108783d1075c6c1a3d94eab3f7d (diff) |
OBJ import support for nurbs curves
Imports nurbs with orderU and endpointU (inferred from weights).
No support for vert-weights, surfaces, 2D curves or non-bspline's yet.
fix for exporting closed nurbs, was overlapping too much of the curve.
Diffstat (limited to 'release/scripts/import_obj.py')
-rw-r--r-- | release/scripts/import_obj.py | 275 |
1 files changed, 228 insertions, 47 deletions
diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index 31501173fda..5234fe80a91 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -536,6 +536,96 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l me.addVertGroup(group_name) me.assignVertsToGroup(group_name, group_indicies,1.00, Mesh.AssignModes.REPLACE) + +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 '\tWarning, cstype not found' + return + if cstype != 'bspline': + print '\tWarning, cstype is not supported (only bspline)' + return + if not curv_idx: + print '\tWarning, curv argument empty or not set' + return + if len(deg) > 1 or parm_v: + print '\tWarning, surfaces not supported' + return + + cu = bpy.data.curves.new(name, 'Curve') + 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) + + +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 + + + def get_float_func(filepath): ''' find the float function for this obj file @@ -590,6 +680,11 @@ def load_obj(filepath, context_smooth_group= None context_object= None context_vgroup = None + + # Nurbs + context_nurbs = {} + nurbs = [] + context_parm = '' # used by nurbs too but could be used elsewhere has_ngons= False # has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0 @@ -604,7 +699,7 @@ def load_obj(filepath, # it means they are multiline- # since we use xreadline we cant skip to the next line # so we need to know weather - multi_line_face= False + context_multi_line= '' print '\tparsing obj file "%s"...' % filepath, time_sub= sys.time() @@ -627,12 +722,11 @@ def load_obj(filepath, # 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) - elif line.startswith('f') or (line.startswith('l ') and CREATE_EDGES) or multi_line_face: + elif line.startswith('f') or context_multi_line == 'f': - if multi_line_face: + 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() - multi_line_face= False else: line_split= line[2:].split() @@ -648,14 +742,10 @@ def load_obj(filepath, context_object\ )) - if line_split[-1][-1]== '\\': - multi_line_face= True - 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 - - isline= line.startswith('l') + if strip_slash(line_split): + context_multi_line = 'f' + else: + context_multi_line = '' for v in line_split: obj_vert= v.split('/') @@ -672,24 +762,60 @@ def load_obj(filepath, face_vert_loc_indicies.append(vert_loc_index) - if not isline: - 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) + 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) if len(face_vert_loc_indicies) > 4: has_ngons= True + + elif CREATE_EDGES and (line.startswith('l ') or context_multi_line == 'l'): + # very similar to the face load function above with some parts removed + 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) + elif line.startswith('s'): if CREATE_SMOOTH_GROUPS: context_smooth_group= line_value(line.split()) @@ -720,6 +846,62 @@ def load_obj(filepath, 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 + + + # 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 + context_nurbs['name'] = context_object + nurbs.append(context_nurbs) + context_nurbs = {} + context_parm = '' ''' # How to use usemap? depricated? elif line.startswith('usema'): # usemap or usemat @@ -754,6 +936,11 @@ def load_obj(filepath, # 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) + # nurbs support + for context_nurbs in nurbs: + create_nurbs(scn, context_nurbs, verts_loc, new_objects) + + axis_min= [ 1000000000]*3 axis_max= [-1000000000]*3 @@ -989,34 +1176,28 @@ if __name__=='__main__' and not DEBUG: else: Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj') - -''' # For testing compatibility +''' else: # DEBUG ONLY TIME= sys.time() + DIR = '/fe/obj' import os print 'Searching for files' - os.system('find /fe/obj -iname "*.obj" > /tmp/temp3ds_list') - - print '...Done' - file= open('/tmp/temp3ds_list', 'rU') - lines= file.readlines() - file.close() - - def between(v,a,b): - if v <= max(a,b) and v >= min(a,b): - return True - return False - - for i, _obj in enumerate(lines): - if between(i, 0,20): - _obj= _obj[:-1] - print 'Importing', _obj, '\nNUMBER', i, 'of', len(lines) - _obj_file= _obj.split('/')[-1].split('\\')[-1] - newScn= bpy.data.scenes.new(_obj_file) + 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, '\nNUMBER', i, 'of', len(files) + newScn= bpy.data.scenes.new(os.path.basename(obj_file)) newScn.makeCurrent() - load_obj(_obj, False) + load_obj(obj_file, False) print 'TOTAL TIME: %.6f' % (sys.time() - TIME) ''' |