[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20825] trunk/blender/release/scripts: OBJ import support for nurbs curves

Campbell Barton ideasman42 at gmail.com
Fri Jun 12 06:16:13 CEST 2009


Revision: 20825
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20825
Author:   campbellbarton
Date:     2009-06-12 06:16:12 +0200 (Fri, 12 Jun 2009)

Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/release/scripts/export_obj.py
    trunk/blender/release/scripts/import_obj.py

Modified: trunk/blender/release/scripts/export_obj.py
===================================================================
--- trunk/blender/release/scripts/export_obj.py	2009-06-12 02:49:21 UTC (rev 20824)
+++ trunk/blender/release/scripts/export_obj.py	2009-06-12 04:16:12 UTC (rev 20825)
@@ -236,9 +236,8 @@
 				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
 		

Modified: trunk/blender/release/scripts/import_obj.py
===================================================================
--- trunk/blender/release/scripts/import_obj.py	2009-06-12 02:49:21 UTC (rev 20824)
+++ trunk/blender/release/scripts/import_obj.py	2009-06-12 04:16:12 UTC (rev 20825)
@@ -536,6 +536,96 @@
 		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 @@
 	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 @@
 	# 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 @@
 		
 		# 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,15 +742,11 @@
 				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
+			if strip_slash(line_split):
+				context_multi_line = 'f'
+			else:
+				context_multi_line = ''
 			
-			isline= line.startswith('l')
-			
 			for v in line_split:
 				obj_vert= v.split('/')
 				
@@ -672,24 +762,60 @@
 				
 				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,7 +846,63 @@
 			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
 			context_image= line_value(line.split())
@@ -754,6 +936,11 @@
 		# 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 @@
 	else:
 		Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
 
-
+# For testing compatibility
 '''
-# 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]

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list