- tweak Object.create_render_mesh params

- svn merge -r 20124:20998 \
https://svn.blender.org/svnroot/bf-blender/branches/blender2.5/blender/release/scripts/export_obj.py \
export_obj-2.5.py to make sure I don't miss new OBJ exporter features ;)
This commit is contained in:
Arystanbek Dyussenov 2009-06-20 05:52:19 +00:00
commit a7f914d25a
2 changed files with 188 additions and 39 deletions

@ -7,9 +7,9 @@ Group: 'Export'
Tooltip: 'Save a Wavefront OBJ File'
"""
__author__ = "Campbell Barton, Jiri Hnidek"
__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
__version__ = "1.2"
__version__ = "1.21"
__bpydoc__ = """\
This script is an exporter to OBJ file format.
@ -184,12 +184,89 @@ def copy_images(dest_dir):
copyCount+=1
print '\tCopied %d images' % copyCount
def write(filename, objects,
EXPORT_TRI=False, EXPORT_EDGES=False,
EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,
EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,
EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False):
def test_nurbs_compat(ob):
if ob.type != 'Curve':
return False
for nu in ob.data:
if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
return True
return False
def write_nurb(file, ob, ob_mat):
tot_verts = 0
cu = ob.data
# use negative indices
Vector = Blender.Mathutils.Vector
for nu in cu:
if nu.type==0: DEG_ORDER_U = 1
else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct
if nu.type==1:
print "\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported"
continue
if nu.knotsV:
print "\tWarning, surface:", ob.name, "only poly and nurbs curves supported"
continue
if len(nu) <= DEG_ORDER_U:
print "\tWarning, orderU is lower then vert count, skipping:", ob.name
continue
pt_num = 0
do_closed = (nu.flagU & 1)
do_endpoints = (do_closed==0) and (nu.flagU & 2)
for pt in nu:
pt = Vector(pt[0], pt[1], pt[2]) * ob_mat
file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2]))
pt_num += 1
tot_verts += pt_num
file.write('g %s\n' % (fixName(ob.name))) # fixName(ob.getData(1)) could use the data name too
file.write('cstype bspline\n') # not ideal, hard coded
file.write('deg %d\n' % DEG_ORDER_U) # not used for curves but most files have it still
curve_ls = [-(i+1) for i in xrange(pt_num)]
# 'curv' keyword
if do_closed:
if DEG_ORDER_U == 1:
pt_num += 1
curve_ls.append(-1)
else:
pt_num += DEG_ORDER_U
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
# 'parm' keyword
tot_parm = (DEG_ORDER_U + 1) + pt_num
tot_parm_div = float(tot_parm-1)
parm_ls = [(i/tot_parm_div) for i in xrange(tot_parm)]
if do_endpoints: # end points, force param
for i in xrange(DEG_ORDER_U+1):
parm_ls[i] = 0.0
parm_ls[-(1+i)] = 1.0
file.write('parm u %s\n' % ' '.join( [str(i) for i in parm_ls] ))
file.write('end\n')
return tot_verts
def write(filename, objects,\
EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\
EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\
EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False,\
EXPORT_POLYGROUPS=False, EXPORT_CURVE_AS_NURBS=True):
'''
Basic write function. The context and options must be alredy set
This can be accessed externaly
@ -203,6 +280,29 @@ def write(filename, objects,
def veckey2d(v):
return round(v.x, 6), round(v.y, 6)
def findVertexGroupName(face, vWeightMap):
"""
Searches the vertexDict to see what groups is assigned to a given face.
We use a frequency system in order to sort out the name because a given vetex can
belong to two or more groups at the same time. To find the right name for the face
we list all the possible vertex group names with their frequency and then sort by
frequency in descend order. The top element is the one shared by the highest number
of vertices is the face's group
"""
weightDict = {}
for vert in face:
vWeights = vWeightMap[vert.index]
for vGroupName, weight in vWeights:
weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight
if weightDict:
alist = [(weight,vGroupName) for vGroupName, weight in weightDict.iteritems()] # sort least to greatest amount of weight
alist.sort()
return(alist[-1][1]) # highest value last
else:
return '(null)'
print 'OBJ Export path: "%s"' % filename
temp_mesh_name = '~tmp-mesh'
@ -248,12 +348,23 @@ def write(filename, objects,
globalNormals = {}
# Get all meshs
# Get all meshes
for ob_main in objects:
for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
# Nurbs curve support
if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
if EXPORT_ROTX90:
ob_mat = ob_mat * mat_xrot90
totverts += write_nurb(file, ob, ob_mat)
continue
# end nurbs
# Will work for non meshes now! :)
# getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn)
me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn)
if not me:
continue
@ -406,6 +517,17 @@ def write(filename, objects,
if not faceuv:
f_image = None
if EXPORT_POLYGROUPS:
# Retrieve the list of vertex groups
vertGroupNames = me.getVertGroupNames()
currentVGroup = ''
# Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to
vgroupsMap = [[] for _i in xrange(len(me.verts))]
for vertexGroupName in vertGroupNames:
for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1):
vgroupsMap[vIdx].append((vertexGroupName, vWeight))
for f_index, f in enumerate(faces):
f_v= f.v
f_smooth= f.smooth
@ -420,9 +542,18 @@ def write(filename, objects,
else:
key = materialNames[f_mat], None # No image, use None instead.
# Write the vertex group
if EXPORT_POLYGROUPS:
if vertGroupNames:
# find what vertext group the face belongs to
theVGroup = findVertexGroupName(f,vgroupsMap)
if theVGroup != currentVGroup:
currentVGroup = theVGroup
file.write('g %s\n' % theVGroup)
# CHECK FOR CONTEXT SWITCH
if key == contextMat:
pass # Context alredy switched, dont do anythoing
pass # Context alredy switched, dont do anything
else:
if key[0] == None and key[1] == None:
# Write a null material, since we know the context has changed.
@ -447,6 +578,7 @@ def write(filename, objects,
if EXPORT_GROUP_BY_MAT:
file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
contextMat = key
@ -548,7 +680,8 @@ def write_ui(filename):
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
EXPORT_APPLY_MODIFIERS = Draw.Create(0)
EXPORT_ROTX90 = Draw.Create(1)
@ -566,6 +699,9 @@ def write_ui(filename):
EXPORT_GROUP_BY_OB = Draw.Create(0)
EXPORT_GROUP_BY_MAT = Draw.Create(0)
EXPORT_KEEP_VERT_ORDER = Draw.Create(1)
EXPORT_POLYGROUPS = Draw.Create(0)
EXPORT_CURVE_AS_NURBS = Draw.Create(1)
# Old UI
'''
@ -616,7 +752,7 @@ def write_ui(filename):
GLOBALS['EVENT'] = e
def do_split(e,v):
global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER
global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER, EXPORT_POLYGROUPS
if EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val:
EXPORT_KEEP_VERT_ORDER.val = 0
else:
@ -630,6 +766,7 @@ def write_ui(filename):
if not (EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val):
EXPORT_KEEP_VERT_ORDER.val = 1
def do_help(e,v):
url = __url__[0]
print 'Trying to open web browser with documentation at this address...'
@ -646,43 +783,47 @@ def write_ui(filename):
# Center based on overall pup size
ui_x -= 165
ui_y -= 110
ui_y -= 140
global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
Draw.Label('Context...', ui_x+9, ui_y+209, 220, 20)
Draw.Label('Context...', ui_x+9, ui_y+239, 220, 20)
Draw.BeginAlign()
EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+189, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+189, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+189, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+219, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+219, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+219, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
Draw.EndAlign()
Draw.Label('Output Options...', ui_x+9, ui_y+159, 220, 20)
Draw.Label('Output Options...', ui_x+9, ui_y+189, 220, 20)
Draw.BeginAlign()
EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+140, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+140, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+140, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+170, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+170, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+170, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
Draw.EndAlign()
Draw.Label('Export...', ui_x+9, ui_y+109, 220, 20)
Draw.Label('Export...', ui_x+9, ui_y+139, 220, 20)
Draw.BeginAlign()
EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+90, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+90, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+120, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+120, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
Draw.EndAlign()
Draw.BeginAlign()
EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+90, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+90, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+120, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+120, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
Draw.EndAlign()
Draw.BeginAlign()
EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+90, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+90, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+120, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+120, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
Draw.EndAlign()
EXPORT_POLYGROUPS = Draw.Toggle('Polygroups', EVENT_REDRAW, ui_x+9, ui_y+95, 120, 20, EXPORT_POLYGROUPS.val, 'Export vertex groups as OBJ groups (one group per face approximation).')
EXPORT_CURVE_AS_NURBS = Draw.Toggle('Nurbs', EVENT_NONE, ui_x+139, ui_y+95, 100, 20, EXPORT_CURVE_AS_NURBS.val, 'Export 3D nurbs curves and polylines as OBJ curves, (bezier not supported).')
Draw.Label('Blender Objects as OBJ:', ui_x+9, ui_y+59, 220, 20)
@ -736,7 +877,8 @@ def write_ui(filename):
EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val
EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val
EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val
EXPORT_POLYGROUPS = EXPORT_POLYGROUPS.val
EXPORT_CURVE_AS_NURBS = EXPORT_CURVE_AS_NURBS.val
base_name, ext = splitExt(filename)
@ -785,7 +927,8 @@ def write_ui(filename):
EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
EXPORT_ROTX90, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER)
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS)
Blender.Set('curframe', orig_frame)

@ -46,20 +46,27 @@
#define OBJECT_API_PROP_DUPLILIST "dupli_list"
/* copied from init_render_mesh (render code) */
Mesh *rna_Object_create_render_mesh(Object *ob, Scene *scene)
Mesh *rna_Object_create_render_mesh(Object *ob, bContext *C, ReportList *reports)
{
CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
DerivedMesh *dm;
Mesh *me;
Scene *sce;
sce= CTX_data_scene(C);
/* TODO: other types */
if(ob->type != OB_MESH)
if(ob->type != OB_MESH) {
BKE_report(reports, RPT_ERROR, "Object should be of type MESH.");
return NULL;
}
dm= mesh_create_derived_render(scene, ob, mask);
dm= mesh_create_derived_render(sce, ob, mask);
if(!dm)
if(!dm) {
/* TODO: report */
return NULL;
}
me= add_mesh("tmp_render_mesh");
me->id.us--; /* we don't assign it to anything */
@ -133,11 +140,10 @@ void RNA_api_object(StructRNA *srna)
func= RNA_def_function(srna, "create_render_mesh", "rna_Object_create_render_mesh");
RNA_def_function_ui_description(func, "Create a Mesh datablock with all modifiers applied.");
parm= RNA_def_pointer(func, "scene", "Scene", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);
parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export.");
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "create_dupli_list", "rna_Object_create_duplilist");
RNA_def_function_ui_description(func, "Create a list of dupli objects for this object. When no longer needed, it should be freed with free_dupli_list.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS);