2009-11-01 15:21:20 +00:00
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
2009-12-13 14:00:39 +00:00
#
2009-11-01 15:21:20 +00:00
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
2009-12-13 14:00:39 +00:00
#
2009-11-01 15:21:20 +00:00
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
2010-02-12 13:34:04 +00:00
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2009-11-01 15:21:20 +00:00
#
# ##### END GPL LICENSE BLOCK #####
2009-12-13 14:38:30 +00:00
# <pep8 compliant>
2007-12-05 20:21:25 +00:00
import bpy
2006-01-12 21:33:42 +00:00
__author__ = " Bruce Merry "
2008-08-11 03:52:21 +00:00
__version__ = " 0.93 "
2006-01-12 21:33:42 +00:00
__bpydoc__ = """ \
2009-12-13 14:00:39 +00:00
This script exports Stanford PLY files from Blender . It supports normals ,
2007-01-09 16:01:38 +00:00
colours , and texture coordinates per face or per vertex .
Only one mesh can be exported at a time .
2006-01-12 21:33:42 +00:00
"""
# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
2010-02-12 13:34:04 +00:00
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2006-07-03 03:22:48 +00:00
# Vector rounding se we can use as keys
2007-01-09 16:01:38 +00:00
#
2008-08-11 03:52:21 +00:00
# Updated on Aug 11, 2008 by Campbell Barton
# - added 'comment' prefix to comments - Needed to comply with the PLY spec.
2007-01-09 16:01:38 +00:00
#
# Updated on Jan 1, 2007 by Gabe Ghearing
# - fixed normals so they are correctly smooth/flat
# - fixed crash when the model doesn't have uv coords or vertex colors
# - fixed crash when the model has vertex colors but doesn't have uv coords
# - changed float32 to float and uint8 to uchar for compatibility
# Errata/Notes as of Jan 1, 2007
# - script exports texture coords if they exist even if TexFace isn't selected (not a big deal to me)
# - ST(R) should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
#
# Updated on Jan 3, 2007 by Gabe Ghearing
# - fixed "sticky" vertex UV exporting
# - added pupmenu to enable/disable exporting normals, uv coords, and colors
# Errata/Notes as of Jan 3, 2007
# - ST(R) coords should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
# - edges should be exported since PLY files support them
# - code is getting spaghettish, it should be refactored...
#
2009-12-16 13:27:30 +00:00
def rvec3d ( v ) :
return round ( v [ 0 ] , 6 ) , round ( v [ 1 ] , 6 ) , round ( v [ 2 ] , 6 )
def rvec2d ( v ) :
return round ( v [ 0 ] , 6 ) , round ( v [ 1 ] , 6 )
2006-01-12 21:33:42 +00:00
2009-09-29 15:27:00 +00:00
def write ( filename , scene , ob , \
2009-12-16 13:27:30 +00:00
EXPORT_APPLY_MODIFIERS = True , \
EXPORT_NORMALS = True , \
EXPORT_UV = True , \
EXPORT_COLORS = True ) :
2009-12-13 14:00:39 +00:00
if not filename . lower ( ) . endswith ( ' .ply ' ) :
filename + = ' .ply '
if not ob :
raise Exception ( " Error, Select 1 active object " )
return
file = open ( filename , ' w ' )
#EXPORT_EDGES = Draw.Create(0)
"""
is_editmode = Blender . Window . EditMode ( )
if is_editmode :
Blender . Window . EditMode ( 0 , ' ' , 0 )
Window . WaitCursor ( 1 )
"""
2010-04-05 06:45:44 +00:00
bpy . ops . object . mode_set ( mode = ' OBJECT ' )
2009-12-13 14:00:39 +00:00
#mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) # XXX
if EXPORT_APPLY_MODIFIERS :
2010-04-06 01:28:39 +00:00
mesh = ob . create_mesh ( scene , True , ' PREVIEW ' )
2009-12-13 14:00:39 +00:00
else :
mesh = ob . data
if not mesh :
raise ( " Error, could not get mesh data from active object " )
return
# mesh.transform(ob.matrixWorld) # XXX
2009-12-16 13:27:30 +00:00
faceUV = ( len ( mesh . uv_textures ) > 0 )
vertexUV = ( len ( mesh . sticky ) > 0 )
2009-12-13 14:00:39 +00:00
vertexColors = len ( mesh . vertex_colors ) > 0
2009-12-16 13:27:30 +00:00
if ( not faceUV ) and ( not vertexUV ) :
EXPORT_UV = False
if not vertexColors :
EXPORT_COLORS = False
2009-12-13 14:00:39 +00:00
2009-12-16 13:27:30 +00:00
if not EXPORT_UV :
faceUV = vertexUV = False
if not EXPORT_COLORS :
vertexColors = False
2009-12-13 14:00:39 +00:00
if faceUV :
2010-02-12 12:57:58 +00:00
active_uv_layer = mesh . active_uv_texture
2009-12-13 14:00:39 +00:00
if not active_uv_layer :
EXPORT_UV = False
faceUV = None
2010-02-12 12:57:58 +00:00
else :
active_uv_layer = active_uv_layer . data
2009-12-13 14:00:39 +00:00
if vertexColors :
2010-02-12 12:57:58 +00:00
active_col_layer = mesh . active_vertex_color
2009-12-13 14:00:39 +00:00
if not active_col_layer :
EXPORT_COLORS = False
vertexColors = None
2010-02-12 12:57:58 +00:00
else :
active_col_layer = active_col_layer . data
2009-12-13 14:00:39 +00:00
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh . verts # save a lookup
ply_verts = [ ] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index
vdict = [ { } for i in range ( len ( mesh_verts ) ) ]
ply_faces = [ [ ] for f in range ( len ( mesh . faces ) ) ]
vert_count = 0
for i , f in enumerate ( mesh . faces ) :
smooth = f . smooth
if not smooth :
normal = tuple ( f . normal )
normal_key = rvec3d ( normal )
if faceUV :
uv = active_uv_layer [ i ]
uv = uv . uv1 , uv . uv2 , uv . uv3 , uv . uv4 # XXX - crufty :/
if vertexColors :
col = active_col_layer [ i ]
col = col . color1 , col . color2 , col . color3 , col . color4
2009-12-16 13:27:30 +00:00
f_verts = f . verts
2009-12-13 14:00:39 +00:00
2009-12-16 13:27:30 +00:00
pf = ply_faces [ i ]
2009-12-13 14:00:39 +00:00
for j , vidx in enumerate ( f_verts ) :
v = mesh_verts [ vidx ]
if smooth :
2009-12-16 13:27:30 +00:00
normal = tuple ( v . normal )
2009-12-13 14:00:39 +00:00
normal_key = rvec3d ( normal )
if faceUV :
2009-12-26 09:36:50 +00:00
uvcoord = uv [ j ] [ 0 ] , 1.0 - uv [ j ] [ 1 ]
2009-12-13 14:00:39 +00:00
uvcoord_key = rvec2d ( uvcoord )
elif vertexUV :
2009-12-16 13:27:30 +00:00
uvcoord = v . uvco [ 0 ] , 1.0 - v . uvco [ 1 ]
2009-12-13 14:00:39 +00:00
uvcoord_key = rvec2d ( uvcoord )
if vertexColors :
2009-12-16 13:27:30 +00:00
color = col [ j ]
color = int ( color [ 0 ] * 255.0 ) , int ( color [ 1 ] * 255.0 ) , int ( color [ 2 ] * 255.0 )
2009-12-13 14:00:39 +00:00
key = normal_key , uvcoord_key , color
vdict_local = vdict [ vidx ]
pf_vidx = vdict_local . get ( key ) # Will be None initially
if pf_vidx == None : # same as vdict_local.has_key(key)
2009-12-16 13:27:30 +00:00
pf_vidx = vdict_local [ key ] = vert_count
2009-12-13 14:00:39 +00:00
ply_verts . append ( ( vidx , normal , uvcoord , color ) )
vert_count + = 1
pf . append ( pf_vidx )
file . write ( ' ply \n ' )
file . write ( ' format ascii 1.0 \n ' )
2010-04-05 06:45:44 +00:00
file . write ( ' comment Created by Blender %s - www.blender.org, source file: %s \n ' % ( bpy . app . version_string , bpy . data . filename . split ( ' / ' ) [ - 1 ] . split ( ' \\ ' ) [ - 1 ] ) )
2009-12-13 14:00:39 +00:00
file . write ( ' element vertex %d \n ' % len ( ply_verts ) )
file . write ( ' property float x \n ' )
file . write ( ' property float y \n ' )
file . write ( ' property float z \n ' )
if EXPORT_NORMALS :
file . write ( ' property float nx \n ' )
file . write ( ' property float ny \n ' )
file . write ( ' property float nz \n ' )
if EXPORT_UV :
file . write ( ' property float s \n ' )
file . write ( ' property float t \n ' )
if EXPORT_COLORS :
file . write ( ' property uchar red \n ' )
file . write ( ' property uchar green \n ' )
file . write ( ' property uchar blue \n ' )
file . write ( ' element face %d \n ' % len ( mesh . faces ) )
file . write ( ' property list uchar uint vertex_indices \n ' )
file . write ( ' end_header \n ' )
for i , v in enumerate ( ply_verts ) :
file . write ( ' %.6f %.6f %.6f ' % tuple ( mesh_verts [ v [ 0 ] ] . co ) ) # co
if EXPORT_NORMALS :
file . write ( ' %.6f %.6f %.6f ' % v [ 1 ] ) # no
2009-12-16 13:27:30 +00:00
if EXPORT_UV :
file . write ( ' %.6f %.6f ' % v [ 2 ] ) # uv
if EXPORT_COLORS :
file . write ( ' %u %u %u ' % v [ 3 ] ) # col
2009-12-13 14:00:39 +00:00
file . write ( ' \n ' )
for pf in ply_faces :
2009-12-26 09:36:50 +00:00
if len ( pf ) == 3 :
2009-12-16 13:27:30 +00:00
file . write ( ' 3 %d %d %d \n ' % tuple ( pf ) )
else :
file . write ( ' 4 %d %d %d %d \n ' % tuple ( pf ) )
2009-12-13 14:00:39 +00:00
file . close ( )
print ( " writing " , filename , " done " )
if EXPORT_APPLY_MODIFIERS :
2010-01-09 23:44:01 +00:00
bpy . data . meshes . remove ( mesh )
2009-12-13 14:00:39 +00:00
# XXX
"""
if is_editmode :
Blender . Window . EditMode ( 1 , ' ' , 0 )
"""
2009-09-29 15:27:00 +00:00
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
from bpy . props import *
2009-11-04 18:35:32 +00:00
class ExportPLY ( bpy . types . Operator ) :
2009-12-13 14:00:39 +00:00
''' Export a single object as a stanford PLY with normals, colours and texture coordinates. '''
bl_idname = " export.ply "
bl_label = " Export PLY "
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
2009-12-16 13:27:30 +00:00
path = StringProperty ( name = " File Path " , description = " File path used for exporting the PLY file " , maxlen = 1024 , default = " " )
2010-02-01 22:04:33 +00:00
check_existing = BoolProperty ( name = " Check Existing " , description = " Check and warn on overwriting existing files " , default = True , options = { ' HIDDEN ' } )
2009-12-16 13:27:30 +00:00
use_modifiers = BoolProperty ( name = " Apply Modifiers " , description = " Apply Modifiers to the exported mesh " , default = True )
use_normals = BoolProperty ( name = " Normals " , description = " Export Normals for smooth and hard shaded faces " , default = True )
use_uvs = BoolProperty ( name = " UVs " , description = " Exort the active UV layer " , default = True )
use_colors = BoolProperty ( name = " Vertex Colors " , description = " Exort the active vertex color layer " , default = True )
2009-12-13 14:00:39 +00:00
def poll ( self , context ) :
return context . active_object != None
def execute ( self , context ) :
# print("Selected: " + context.active_object.name)
if not self . properties . path :
raise Exception ( " filename not set " )
write ( self . properties . path , context . scene , context . active_object , \
2009-12-16 13:27:30 +00:00
EXPORT_APPLY_MODIFIERS = self . properties . use_modifiers ,
EXPORT_NORMALS = self . properties . use_normals ,
EXPORT_UV = self . properties . use_uvs ,
EXPORT_COLORS = self . properties . use_colors ,
2009-12-13 14:00:39 +00:00
)
2009-12-24 19:50:43 +00:00
return { ' FINISHED ' }
2009-12-13 14:00:39 +00:00
def invoke ( self , context , event ) :
wm = context . manager
wm . add_fileselect ( self )
2009-12-24 21:17:14 +00:00
return { ' RUNNING_MODAL ' }
2009-12-13 14:00:39 +00:00
def draw ( self , context ) :
layout = self . layout
props = self . properties
row = layout . row ( )
row . prop ( props , " use_modifiers " )
row . prop ( props , " use_normals " )
row = layout . row ( )
row . prop ( props , " use_uvs " )
row . prop ( props , " use_colors " )
2009-11-29 01:49:22 +00:00
2009-09-29 15:27:00 +00:00
2009-11-04 18:35:32 +00:00
def menu_func ( self , context ) :
2009-12-13 14:00:39 +00:00
default_path = bpy . data . filename . replace ( " .blend " , " .ply " )
2010-02-15 09:53:02 +00:00
self . layout . operator ( ExportPLY . bl_idname , text = " Stanford (.ply) " ) . path = default_path
2009-11-04 18:35:32 +00:00
- add torus back from 2.4x as an operator
bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops - MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
2009-10-10 21:23:20 +00:00
2010-02-14 11:21:21 +00:00
def register ( ) :
bpy . types . register ( ExportPLY )
bpy . types . INFO_MT_file_export . append ( menu_func )
2010-02-22 23:32:58 +00:00
2010-02-14 11:21:21 +00:00
def unregister ( ) :
bpy . types . unregister ( ExportPLY )
bpy . types . INFO_MT_file_export . remove ( menu_func )
2010-02-16 09:55:07 +00:00
if __name__ == " __main__ " :
register ( )