3

All,

I've recently started dabbling in Blender to do some scientific visualization, like ParaView but 1000x prettier :)

At the moment I'm trying to tackle adding a color ramp to a 3D surface. As of now, I've been able to figure out how to use the surface's vertex geometry as the input for coloring. My current node setup looks something like this:

current

This separates the z-values from the geometry and uses them as input for the color map (after normalizing them in the map range node).

I want to do this exact same process, but instead of using the z-values, I want to use arbitrary values.

If I have a surface with n points, I will have an array with n values. These may represent temperature, salinity, velocity etc.

How could I go about doing this? Both GUI and python based solutions welcome! Would like to learn it first by GUI but will eventually be coded.

Derek Eden
  • 413
  • 3
  • 19
  • 2
    Hi! Seems like your question titles are pretty much the same for all of your latest questions. Please make them specific, thanks. Consider that this is not a regular forum, please read: https://blender.stackexchange.com/help/how-to-ask – brockmann Apr 18 '20 at 07:22
  • there are several questions that are related but are distinct questions, I ask them individually otherwise I get penalized for putting too much in one... trying to do one thing with multiple steps...any idea how to do this? – Derek Eden Apr 18 '20 at 16:56
  • I've ediited the titles to be more clear for my previous questions, made them a direct one question, and took out any subquestions at the bottom of each..this specific question was a subquestion to another question which didn't actually get answered..on the recommendation of the person who solved that question, I posted a specific question for this.. they may be related but they are all distinct questions...any help is appreciated – Derek Eden Apr 18 '20 at 17:01
  • 1
    Your edit doesn't really help. Again, please take the time, read the link of my first comment and make your question useful for all of us by trying to find a specific title. – brockmann Apr 18 '20 at 17:03
  • I don't understand? each question is a separate distinct question trying to solve one step of a multistep probelm? the titles are clear and unique? – Derek Eden Apr 18 '20 at 17:04
  • how to modify / customize a coloramp?, Why is my color map gradient (by node xyz value) working for x and y but not z?, how to use external values as input for color ramp shader node? .. these are all different questions, with different answers and no overlap of the questions in each.. in fact I had overlap before and others who helped on those questions suggested I separate them out and ask individually.. I understand whee you're coming from but I don't know how I can ask these questions without asking multiple questions at once – Derek Eden Apr 18 '20 at 17:06
  • Sorry for being a nitpicker, it is like it is here on stackexchange land. However, in most cases there is a good reason Derek... – brockmann Apr 18 '20 at 17:15
  • 1
    I feel like I'm somewhat responsible for this. It did seem to me that @DerekEden had two related, yet nevertheless distinct questions in a previous post. If reaching two goals requires two (potentially) distinct approaches, should there not be a separate question associated with each? – Jeremy Hilgar Apr 18 '20 at 18:23
  • I wish there was this much traffic with people posting answers XD – Derek Eden Apr 18 '20 at 19:52
  • @DerekEden I'm actually still working on trying to find an answer. I'm sure that it's easy to do - but I'm not a Blender wizard :( - hopefully something will come up soon – Jeremy Hilgar Apr 18 '20 at 22:56
  • @DerekEden Also, your "Similar Question" link simply links to the photo in your question. – Jeremy Hilgar Apr 18 '20 at 23:04
  • thanks, fixed that.. I don't know if I'm breaking rules now but I'm going to post my current approach, which almost achieves what I want, maybe it'll help you think or maybe you can help me solve the last step – Derek Eden Apr 18 '20 at 23:32
  • 1
    Related https://blender.stackexchange.com/questions/161664/using-float-property-layers-value-in-node-editor-similar-to-vertex-color Can also use UV layer u, v data. – batFINGER Apr 19 '20 at 10:06

1 Answers1

4

You can loop over every vertex after initializing different arrays for each of your vertex color layers. You can parse the init data from a file (eg .csv) with python but this is not covered in this answer.

import bpy
import bmesh

obj = bpy.context.selected_objects[0]  # Get the currently selected object

vertex_colors = obj.data.vertex_colors
while vertex_colors:
    vertex_colors.remove(vertex_colors[0])  # Remove all vertex color layers form the mesh data

bm = bmesh.new()  # Create new bmesh object
bm.from_mesh(obj.data)  # Init the bmesh with the current mesh

verts_count = len(bm.verts)  # Get the number of vertices in the mesh 
# Not obligatory, I just use this to populate the vertex color layers)

# This dictionary will map each vertex color layer name to the data for each vertex
data_layers = {
    'Temperature':  # vertex color layer name 1
        [
        (1, 0, 0, 1),  # Color of vertex index 0
        (0, 1, 0, 1),  # Color of vertex index 1
        (0, 0, 1, 1),  # Color of vertex index 2
        (1, 1, 1, 1),  # Color of vertex index 3...
        ],    
    'Velocity':  # vertex color layer name 2
        [(i / verts_count, i / verts_count, i / verts_count, 1) for i in range(verts_count)],
    'Salinity':  # vertex color layer name 3
        [(i / verts_count, 1 - (i / verts_count), 0.5, 1) for i in range(verts_count)],        
    }

color_layers = {}
for layer_name in data_layers:
    # Create the vertex color layers and store them in a dictionary for easy access by name
    color_layers[layer_name] = bm.loops.layers.color.new(layer_name)

for layer_name, layer in color_layers.items():
    # Loop over each vertex color layer
    for v in bm.verts:
        # Loop over every vertex
        for loop in v.link_loops:
            # Loop over every loop of this vertex (the corners of the faces in which this vertex exists)  
            try:
                loop[layer] = data_layers[layer_name][v.index]
                # Get the value from the init dictionary
            except IndexError:
                loop[layer] = (1, 0, 1, 1)
                # Set a placeholder (magenta) value if the mapping array is not long enough

bm.to_mesh(obj.data)  # Give the data back to the actual mesh

Then to acces the vertex colors in your material, use the vertex color node :

enter image description here

Note that the "Temperature" layer was initialized with only 4 values, so only a few vertices in the right eye got colored and the rest of the vertices got mapped to a magenta color.

Also note that you can store 4 values in each of the 4 channels of your color. Example with the 'Velocity' vertex color layer used before :

enter image description here

Gorgious
  • 30,723
  • 2
  • 44
  • 101
  • 1
    looks insane...going to attempt this after dinner, will get back to you..thanks for input – Derek Eden Apr 19 '20 at 00:14
  • 1
    seriously thank you, this worked like a charm. – Derek Eden Apr 19 '20 at 01:23
  • @DerekEden I'm glad it helped you ! I have added a tip to add more information in each color's channel if you are intersted – Gorgious Apr 19 '20 at 08:43
  • @Gorgious This is a very nice answer. Do you know off-hand if the same can be done without using bmesh? I don't see any list like link_loops within an object's data property. – Jeremy Hilgar Apr 20 '20 at 22:52
  • @JeremyHilgar Mesh has a loops attribute and then you can check the current loop's vertex_index attribute for mapping. But I'd rather use bmesh, any reason why you can't use this ? If it's an edit-mode problem, you can create a from-edit-meshbmesh – Gorgious Apr 21 '20 at 07:23
  • @Gorgious No real reason why I can't use bmesh. I have been importing vertex/face data using from_pydata and it feels clunky to me to have to initialize a bmesh afterward. I guess I'm just trying to save time/lines of code - as well as learning to do things as many ways as possible. Thanks for your input! – Jeremy Hilgar Apr 21 '20 at 17:01