0
$\begingroup$

I'm trying to color the vertices of an object. I have list of values like this: values_list = [0.1, 0.5, 0.2, 0.4, etc...] which means the vertex with index 0 has a value of 0.1, the vertex with index 1 has a value of 0.5 and so on. This value is the intensity of the color red. I'm using this code to get the work done but as you can see the result is kinda "pixelated". What's wrong with my code?

Short Code:

import bpy

# Obviosuly there should be some other numbers but for shortness I dont fully write vertices and faces
verts = [0,1,2,3,4 ...]
faces = [(0,1,2),(2,1,4), ...]

# Creating mesh
mesh = bpy.data.meshes.new("New mesh")
obj = bpy.data.objects.new("My object",mesh)
col = bpy.data.collections.get("Collection")
col.objects.link(obj)
bpy.context.view_layer.objects.active = obj
mesh.from_pydata(verts, [], faces)

# For shortness again I don't write every number
values_list = [0.1, 0.5, 0.2, 0.4 ...]


if not obj.data.vertex_colors:
   obj.data.vertex_colors.new()

color_layer = obj.data.vertex_colors.active 

i = 0
for poly in mesh.polygons:
   for idx in poly.loop_indices:
       loop = mesh.loops[idx]
       color_layer.data[i].color = (values_list[loop.vertex_index], 0, 0, 1)
       i += 1
       
# setting to vertex paint mode to see the result
bpy.ops.object.mode_set(mode='VERTEX_PAINT') 

Screenshot of the result: Screenshot of the result

Full code

import bpy
import vtkmodules.all as vtk
# The source file
file_name = "time_solution_stress_004.0.vtu"
# Read the source file.
reader = vtk.vtkXMLUnstructuredGridReader()
reader.SetFileName(file_name)
reader.Update()

output = reader.GetOutput()
points = output.GetPoints()

vms = output.GetPointData().GetArray("Von_Mises_stress") # get the array containing the von mises stress value for every vertex

# get vertices
verts = []
if points:
    for x in range(points.GetNumberOfPoints()):
        vertex=[0,0,0]
        points.GetPoint(x,vertex) # fill the vertex variable
        verts.append(vertex)
# get faces
faces = []
for i in range(output.GetNumberOfCells()):
    cell = output.GetCell(i)
    cell_points_ids = []
    for face_index in range(cell.GetNumberOfFaces()):
        idlist=[]
        for id_index in range( cell.GetFace(face_index).GetNumberOfPoints() ): #4
            idlist.append( cell.GetFace(face_index).GetPointIds().GetId(id_index) ) 
        faces.append(idlist)

mesh = bpy.data.meshes.new("New mesh")
obj = bpy.data.objects.new("Cube",mesh)
col = bpy.data.collections.get("Collection")
col.objects.link(obj)
bpy.context.view_layer.objects.active = obj
mesh.from_pydata(verts, [], faces)

# Creation of a list where the element with index i is the von mises stress value of the i vertex
# This value isn't the original but it's converted in 0 to 1 range (so i can use it as the intensity of the color red)
red_intensity_list = []
vms_min, vms_max = vms.GetRange()
input_start, input_end, output_start, output_end = vms_min, vms_max, 0, 1
slope = (output_end - output_start) / (input_end - input_start)
for i in range(vms.GetNumberOfTuples()):
    vms_value = vms.GetTuple1(i)
    zero_to_1_output = output_start + slope * (vms_value - input_start) 
    red_intensity_list.append(zero_to_1_output)

if not obj.data.vertex_colors:
    obj.data.vertex_colors.new()

color_layer = obj.data.vertex_colors.active 

i = 0
for poly in mesh.polygons:
    for idx in poly.loop_indices:
        loop = mesh.loops[idx]
        color_layer.data[i].color = (red_intensity_list[loop.vertex_index], 0, 0, 1)
        i += 1
# setting to vertex paint mode to see the result
bpy.ops.object.mode_set(mode='VERTEX_PAINT')
$\endgroup$

1 Answer 1

0
$\begingroup$

Try this one. I created a cube with 8 vertices and then applied your colors and it looks pretty:

enter image description here

import bpy

context = bpy.context

verts = ((1.0, 1.0, 1.0),
         (1.0, 1.0, -1.0),
         (1.0, -1.0, 1.0),
         (1.0, -1.0, -1.0),
         (-1.0, 1.0, 1.0),
         (-1.0, 1.0, -1.0),
         (-1.0, -1.0, 1.0),
         (-1.0, -1.0, -1.0))

faces = ((0, 4, 6, 2),
         (3, 2, 6, 7),
         (7, 6, 4, 5),
         (5, 1, 3, 7),
         (1, 0, 2, 3),
         (5, 4, 0, 1))

mesh = bpy.data.meshes.new("cube_mesh")
obj = bpy.data.objects.new("cube",mesh)
col = bpy.data.collections.get("Collection")
col.objects.link(obj)
bpy.context.view_layer.objects.active = obj

mesh.from_pydata(verts, [], faces)

values_list = [0.1, 0.5, 0.2, 0.4, 0.3, 0.0, 0.0, 0.0]

if not obj.data.vertex_colors:
   obj.data.vertex_colors.new()

color_layer = obj.data.vertex_colors.active 

i = 0
for poly in mesh.polygons:
   for idx in poly.loop_indices:
       loop = mesh.loops[idx]
       color_layer.data[i].color = (values_list[loop.vertex_index], 0, 0, 1)
       i += 1

bpy.ops.object.mode_set(mode='VERTEX_PAINT')
$\endgroup$
5
  • $\begingroup$ I tried it and yes, the cube looks good so the code works correctly. I guess the problem is my values_list (which i get from a vtk file). Probably I need to ask the question in the VTK forum with more details $\endgroup$ Aug 28, 2022 at 12:36
  • $\begingroup$ the verts were definitely wrong they need to be (x,y,z),(x,y,z) format. maybe the winding order of ur faces were wrong and inverted the normals. can u post the full code u used to get the pixelated result u have? $\endgroup$ Aug 28, 2022 at 15:11
  • $\begingroup$ edited the question with the full code $\endgroup$ Aug 28, 2022 at 15:57
  • $\begingroup$ how did you import vtk and how do i install it? pip install vtk ? $\endgroup$ Aug 28, 2022 at 16:12
  • $\begingroup$ yes, I accidentally didn't copy the first two lines when copypasting the full code, as you can see now you can import it as import vtkmodules.all as vtk $\endgroup$ Aug 28, 2022 at 21:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .