2
$\begingroup$

I am trying to select a model vertex by the textures alpha trough the python.

But I cant figure out relationship between meshes vertex, uv-vertex and texture´s pixel rgba information. Can you help me with this please ?

$\endgroup$
1
$\begingroup$

So, after some time with the research i found the answers. It is for beginners like me, so pros please correct my mistakes if i have some. (From noob to noobs :D - for better understaning the fundamentals)

I am trying to made 2D puppet in blender, so mainly I created plane or grid and textures. Its not for a complex 3d puppet and materials.

A) Vertices + mesh - Vertices have index and [0,0,0] is the pivot point. Default in the middle of object.

There are awesome addon for vizualize numbers of vertices for better control:

https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/Index_Visualiser

code to find coordinations of vertices:

import bpy
obj=bpy.context.active_object
x=obj.data.vertices[0].co[0] #X
y=obj.data.vertices[0].co[1] #Y
z=obj.data.vertices[0].co[2] #Z
print("X:"+repr(x) +" Y:"+repr(y) +" Z:"+repr(z))

If we want to use infromation from vertexes for image and pixels, we need recalculate ratio position of the vertices. (0-1 from dimensions * scale)

For separate dimension from scale I must applied scale. In that case dimensions are setting as you choose but scale is reset to default 1.

Next stage is to move axis of coordination system for vertexes to the left-down corner, because imaxe X,Y coords is the same.

import bpy
obj=bpy.context.active_object
dimension = obj.dimensions
for i in range(len(obj.data.vertices)):
    a = []
    axis = [-(dimension[0]/2),-(dimension[1]/2),0]
    a.append(obj.data.vertices[i].co[0] * obj.scale[0] - axis[0])     # X 
    a.append(obj.data.vertices[i].co[1] * obj.scale[1] - axis[1])     # Y
    a.append(obj.data.vertices[i].co[2] * obj.scale[2] - axis[2])     # Z
    print(a)

Calculate the ratio is very easy now (everything is for the plane object):

    ratio_verts = []
    ratio_verts.append(a[0]/(dimension[0]))
    ratio_verts.append(a[1]/(dimension[1]))
    ratio_verts.append(0.0)

Challenge of this small research was to understang how is a PNG works it is the format which carry RGBA infromation. So at the begining I discovered that for 3x3 size of picture python give me 36 numbers. I was very confusing about that, because I though that every pixel have its own index and then under index are the information about RGBA.

import bpy image = "Test.png" print(bpy.data.images[image].pixels)

It was mistake, PNG RGBA infromation is saved like numbers in line. [1.0,1.0,1.0,1.0...] And how it works? Like this! [1R,1G,1B,1A,2R,2G,2B,2A,3R,3G,3B,3A...] 4 numbers next other for 1 pixel information. Yes, I know, I was dumb that I dont know it, but I never trying working with the pixels trough python.

So there are really nice maths about converting coordinates to this system :)

From coordination of pixel like X:3px Y:3px to number of the pixel in line. like: enter image description here

I created an function:

def sourxy(x,y,image_name,start):    
    imgX = bpy.data.images[image_name].size[0]
    PXindex = (y*imgX)-(imgX-x)
    return PXindex-1+start

when X and Y os coordination for searhed pixel. image_name > its name of my mum :D No, of course name of the image. And start is number if the start index (0 or 1 often) for next maths.

For some reasons maybe you would like to use recalc for X and Y:

x = PXindex + imgX - (y*imgX)
y = PXindex/imgX)+((imgX-x)/imgX

Perfect, I though, i am almost done. Byt computer says : nooooooo !

I finded problem between recalc coordinaion of the vertexes and the pixels. Vertexes have coords like [0,0], [0,1], [0,2] and its not only 9 vertices it can be like 100*100 vertices for more dense planes.

So if i rounded ratio to integers. I had coords of pixels on image without any color. Its every border down and left vertex.

Solution was simple function:

def imground(n):
    if n==0.0:
        return 1
    else: return math.ceil(n)

From vertex coords to imagme coords by vertex ratio between position and dimensions is like:

imageX=imground(bpy.data.images[image].size[0]*ratio_verts[0])
imageY=imground(bpy.data.images[image].size[1]*ratio_verts[1])

That give me right coords without zero.

From that stage its pretty simply, we need alpha exact pixel. But every pixel have 4 numbers so it need to be miltiplied by 4. And then we know that 4th number is the Alpha we found.

VertexAlpha =bpy.data.images[image].pixels[sourxy(imageX,imageY,image,0)*4+3]

So every vertex which have alpha more than 0 assign to first vertex group:

if VertexAlpha > 0:
        vrx_grp.append(i)        
obj.vertex_groups[0].add(vrx_grp,1.0,"REPLACE")       
vrx_grp=[]

# get all the verts that belong to a certain vertex group index:
vg_idx = 0
vs = [ v for v in obj.data.vertices if vg_idx in [ vg.group for vg in v.groups ] ]
print("vertex_group inside: " + repr(vs))

last part of code is from: Python - Finding Vertices in a Vertex Group

And Last part of question was UV vertex. For me and the puppet project its not usable, because every vertex in uv can hold multiple coordinations. It is because Many parts of unwrapping. And trough the vertex can be created line of the seam.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.