Can I turn weight paint(vertex group data) into vertex paint? I would like to take the weight paint value and convert it into a black and white grey scale vertex paint map.

  • you forgot a tag that may help a lot here -> Python! – MarcClintDion Aug 21 '14 at 17:16
  • @MarcClintDion Tag the question, not the answers. Even if the only solution is python, if the OP isn't specifically looking for a python solution, then I think the current tags are fine. – gandalf3 Aug 21 '14 at 21:08
  • True but for some reason I felt that GiantCowFilms would not have a problem with Python solutions as well. Maybe I'm remembering history wrong. Anyways, the reason I brought it up is because some people may just be skimming the tags only and moving past questions with no Python tag and I was pretty sure there was no built in tool to do this. – MarcClintDion Aug 22 '14 at 5:42
  • I don't mind python if there is no alternative. – GiantCowFilms Aug 22 '14 at 14:37
  • @MarcClintDion It seems there are differing opinions on this.. e.g. meta.stackexchange.com/q/59333/238438 and meta.stackexchange.com/q/184658/238438 (the second one has no answers, but links to a bunch of related/duplicate questions with answers) – gandalf3 Aug 22 '14 at 19:22
up vote 7 down vote accepted

I think you will still have to do a bit of scripting to get the following to work but it does most of what you want. A while back, someone posted a question about how to convert an existing script that turns Weight Paint to Vertex Color Paint, he posted the script link and there are a couple reasons why I decided to post this as an answer instead of only directing you to the link. First, there is an important step necessary to get this to work properly. Second, I'd like to also post the script here directly in case the link to the external site goes down, this way it will still be available here.

To start with, Vertex Color Paint starts off as all white and if you try to use the Addon with the Vertex Colors as all White then it fails weirdly. The first results I got looked like the following. It transitions from white to grey then back to white. It's not black where the blue is in Weight Paint mode.

enter image description here

However, if you first add a Color vertex group and then make that group black, the Addon works fine. Just set the brush color to black and use the Set Vertex Color shift +k

enter image description here

Now you will have all black vertex colors.

So now you can enter weight paint mode and use the Addon which can be found in the spacebar search menu under Weight2VertexCol

You should get results something like the following.

enter image description here

Now the fun part, you have to modify the Addon to invert black and white. Fortunately, the math for this is easy, unfortunately I don't know Python scripting very well and I'm mediocre with math. Now if I think correctly(which I don't always do) you can use (x*-1.0)+1.0 to invert black and white. So I assume if we find the place in the script that writes the Vertex Colors and we place that variable where the x is in the above formula then the script should do what you want.

I'll just post the script for now and then maybe someone can figure this last part out. I'll be really surprised if that code works without some indentation reformatting using a program like PyCharm CE since the code window here botched the copy and paste and I had to do a bunch of manual indentation. Anyways, here is the link to the script on the external site so people can just use this copy as a last resort.

https://bitbucket.org/kursad/blender_addons_weight2vertcolortransfer/src/42070d95e0063df441b4f2d617492669b690592c/src/vertex_color_weight_transfer.py?at=master

The script has the filename -> vertex_color_weight_transfer.py in case anyone from the future wants to Google it. His name is listed in the script below.

I put some notes after the script about how I think you can modify it to make Red = 0.0 and Blue = 1.0 instead of what it does now(Unless I'm confused and it already does.)

import bpy 
from mathutils import Color
import random
from bpy.props import *

import bmesh


bl_info = {
    "name": "Weight2VertexCol",
    "author": "Kursad Karatas",
    "version": (0, 1, 0),
    "blender": (2, 6 ,6),
    "location": "View3D > UI panel >CopyWeightColors",
    "description": "Transfers Weights as Vertex Colors",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "3D View"}


class Weight2VertexCol(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.weight2vertexcol"
    bl_label = "Weight2VertexCol"
    bl_space_type = "VIEW_3D"
    bl_options = {'REGISTER', 'UNDO'}

    method=bpy.props.BoolProperty(name="Color", description="Choose the coloring method", default=False)

@classmethod
def poll(cls, context):
    return context.active_object is not None

def execute(self, context):
    transferWeight2VertexCol(context, self.method)
    context.active_object.data.update()
    return {'FINISHED'}


def transferWeight2VertexCol(context, method):
    me=context.active_object
    verts=me.data.vertices

    col=Color()
   col.h=0
    col.s=1
col.v=1

#vcolgrp=bpy.context.active_object.data.vertex_colors.keys()

try:
    assert bpy.context.active_object.vertex_groups
    assert bpy.context.active_object.data.vertex_colors

except AssertionError:
    bpy.ops.error.message('INVOKE_DEFAULT', 
            type = "Error",
            message = 'you need at least one vertex group and one color group')
    return

vgrp=bpy.context.active_object.vertex_groups.keys()

vcolgrp=bpy.context.active_object.data.vertex_colors


#Check to see if we have at least one vertex group and one vertex color group
if len(vgrp) > 0 and len(vcolgrp) > 0: 
    print ("enough parameters")

    #Colored
    if method:
        for poly in me.data.polygons:
            for loop in poly.loop_indices:
                vertindex=me.data.loops[loop].vertex_index        

                #Check to see if the vertex has any geoup association
                try:
                    weight=me.vertex_groups.active.weight(vertindex)
                except:
                   continue

                #col=Color ((r, g, b )) 
                col.h=0.66*weight
                col.s=1
                col.v=1
                me.data.vertex_colors.active.data[loop].color = (col.b, col.g, col.r)


    if not method:
        for poly in me.data.polygons:
            for loop in poly.loop_indices:
                vertindex=me.data.loops[loop].vertex_index        
                #weight=me.vertex_groups['Group'].weight(vertindex)

                #Check to see if the vertex has any geoup association
                try:
                    weight=me.vertex_groups.active.weight(vertindex)
                except:
                    continue

                col.r=weight
                col.g=col.r
                col.b=col.r
                me.data.vertex_colors.active.data[loop].color = (col.b, col.g, col.r)


class MessageOperator(bpy.types.Operator):
    bl_idname = "error.message"
    bl_label = "Message"
    type = StringProperty()
    message = StringProperty()

    def execute(self, context):
        self.report({'INFO'}, self.message)
        print(self.message)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_popup(self, width=800, height=200)

    def draw(self, context):
        self.layout.label("A message has arrived")
        row = self.layout.split(0.25)
        row.prop(self, "type")
        row.prop(self, "message")
        row = self.layout.split(0.80)
        row.label("") 
        row.operator("error.ok")

#
#   The OK button in the error dialog
#
class OkOperator(bpy.types.Operator):
    bl_idname = "error.ok"
    bl_label = "OK"
    def execute(self, context):
        return {'FINISHED'}


def menu_draw(self, context): 
    self.layout.operator_context = 'INVOKE_REGION_WIN' 
    self.layout.operator(Bevel.bl_idname, "Weight2VertexCol") 

def register():
    bpy.utils.register_class(Weight2VertexCol)
    bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_draw) 

    #error window
    bpy.utils.register_class(OkOperator)
    bpy.utils.register_class(MessageOperator)


def unregister():
    bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_draw) 
    bpy.utils.unregister_class(Weight2VertexCol)

if __name__ == "Weight2VertexCol":
    register()

The following lines look like where the Red and Blue are being transferred to Black and White. The col.r = weight is a pretty good indication. So is the fact that all three color channels are being assigned the same information. That is how you make a grey scale color which is what we are looking for here.

col.r=weight

col.g=col.r

col.b=col.r

So, as a starting point, I would modify the first line of that snippet to be

col.r= (weight*-1.0)+1.0

and then I would test it. It should do what you want I think.

What would be even better is if you were to find a way to modify the code so that it automatically makes the Vertex Colors all black for you as part of the script which will save you a few steps.

UPDATE: I tested the invert formula and now the script seems to do what you want, here is the result. Also, with the greyscale inversion added, the initial Vertex Colors should start off white instead of black so this saves a bit of setup for you.

enter image description here

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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