[Bf-committers] Extracting correct UV coordinates

Spencer Parkin spencertparkin at gmail.com
Sun Dec 11 05:42:50 CET 2016


Hi.

I'm trying to write a PLY exporter plugin for Blender using Python.  (I've
attached it for reference; I hope that's okay.)  In short, I can't get the
UVs to come out correctly.  Not only does the exported PLY file import
incorrectly into a different program, but I've verified that the exported
UVs are just plain wrong by comparing my exported output with what I find
in the UV/Image editor when kept in sync with the 3D View in edit mode.

I'm at a complete loss.  Any help would be greatly appreciated.

--Sp
-------------- next part --------------
# PLYExport.py

bl_info = {
    'name' : 'PLYExport',
    'description' : 'Exports active object to PLY format.',
    'author' : 'Spencer',
    'version' : ( 0, 1 ),
    'blender' : ( 2, 28, 0 ),
    'location' : 'File > Import-Export',
    'category' : 'Import-Export'
}

import bpy
from bpy_extras.io_utils import ExportHelper

class PLYExportOperator( bpy.types.Operator, ExportHelper ):
    """Export object to PLY format."""
    
    bl_idname = "model.ply"
    bl_label = "Export PLY"
    bl_options = { 'PRESET' }
    filename_ext = '.ply'

    @classmethod
    def poll( cls, context ):
        if context.active_object is None:
            return False
        if context.active_object.data.uv_layers.active is None:
            return False
        return True

    def execute( self, context ):
        
        bpy.ops.object.mode_set( mode = 'OBJECT' )

        obj = context.active_object

        vert_list = obj.data.vertices
        poly_list = obj.data.polygons
        uv_list = obj.data.uv_layers.active.data

        ply_export = 'ply\n'
        ply_export += 'format ascii 1.0\n'
        ply_export += 'comment Generated by PLYExportOperator registered with Blender.\n'
        ply_export += 'element vertex ' + str( len( vert_list ) ) + '\n'
        ply_export += 'property float x\n'
        ply_export += 'property float y\n'
        ply_export += 'property float z\n'
        ply_export += 'property float nx\n'
        ply_export += 'property float ny\n'
        ply_export += 'property float nz\n'
        ply_export += 'property float u\n'
        ply_export += 'property float v\n'
        ply_export += 'element face ' + str( len( poly_list ) ) + '\n'
        ply_export += 'property list uchar int vertex_indices\n'
        ply_export += 'end_header\n'

        class PlyVertex:
            def __init__( self, co, nm, uv ):
                self.co = co
                self.nm = nm
                self.uv = uv

        ply_vert_array = []
        for vert in vert_list:
            co = obj.matrix_world * vert.co
            nm = obj.matrix_world * vert.normal		# Use inverse transpose?
            ply_vert_array.append( PlyVertex( co, nm, None ) )
            
        for poly in poly_list:
            loop_stop = poly.loop_start + poly.loop_total
            for loop_index in range( poly.loop_start, loop_stop ):
                vert_index = obj.data.loops[ loop_index ].vertex_index
                uv = uv_list[ loop_index ].uv
                ply_vert_array[ vert_index ].uv = uv

        for i in range( len( ply_vert_array ) ):
            ply_vert = ply_vert_array[i]
            ply_export += '%f %f %f %f %f %f %f %f\n' % (
                    ply_vert.co.x, ply_vert.co.y, ply_vert.co.z,
                    ply_vert.nm.x, ply_vert.nm.y, ply_vert.nm.z,
                    ply_vert.uv.x, ply_vert.uv.y )

        for poly in poly_list:
            ply_export += str( poly.loop_total ) + ' '
            loop_stop = poly.loop_start + poly.loop_total
            for loop_index in range( poly.loop_start, loop_stop ):
                ply_export += str( obj.data.loops[ loop_index ].vertex_index ) + ' '
            ply_export += '\n'

        with open( self.filepath, 'w' ) as file:
            file.write( ply_export )

        return{ 'FINISHED' }

def menu_func( self, context ):
    self.layout.operator( PLYExportOperator.bl_idname, text = 'PLY (.ply)' )

def register():
    bpy.utils.register_class( PLYExportOperator )
    bpy.types.INFO_MT_file_export.append( menu_func )

def unregister():
    bpy.utils.unregister_class( PLYExportOperator )
    bpy.types.INFO_MT_file_export.remove( menu_func )

if __name__ == "__main__":
    register()


More information about the Bf-committers mailing list