forked from bartvdbraak/blender
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.
This commit is contained in:
parent
642fea299b
commit
96c5f36eff
@ -236,9 +236,8 @@ def write_nurb(file, ob, ob_mat):
|
||||
pt_num += 1
|
||||
curve_ls.append(-1)
|
||||
else:
|
||||
val = DEG_ORDER_U - 1
|
||||
pt_num += val*2
|
||||
curve_ls = curve_ls[-val:] + curve_ls + curve_ls[0:val] # Blenders OrderU of 3 -> val==1, 4 -> 2 etc
|
||||
pt_num += DEG_ORDER_U-1
|
||||
curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U]
|
||||
|
||||
file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve
|
||||
|
||||
|
@ -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')
|
||||
def fileList(path):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
yield os.path.join(dirpath, filename)
|
||||
|
||||
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)
|
||||
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)
|
||||
'''
|
||||
|
Loading…
Reference in New Issue
Block a user