2
$\begingroup$

I am trying to render CFD data in blender, where the CFD code generates output files that consist of particle positions and scalars. I have successfully loaded the data into blender and used a particle system to place a sphere at each vertex. Next, I want to color each particle using a scalar (temperature, velocity, etc.). So I created a nparticles x 1 image where the colors are the same order as I added the vertices. I tried using the particle system index to map to that image and color the particles. This works except that something in the ordering of the particles is wrong.

This image should have a nice linear coloring from bottom to top based on the particles height, however it has bands of color: particles colored by height

Here is the material nodes for the duplicated object (sphere): enter image description here

Any ideas on how I can map the vertex order to the particle order?

Most of this has been derived from this add-on: https://github.com/SBCV/Blender-Addon-Photogrammetry-Importer/blob/master/photogrammetry_importer/utils/blender_point_utils.py

For creating the image:

def set_image_data(obj, data, cmap='viridis', limits=[0, 1]):
    '''
    Given an array of data, convert to colors using the color map, create an
    image and asign the image to the 'Image Texture' node in the objects
    material.
    '''
    node_tree = obj.data.materials[-1].node_tree

    data = data.flatten()
    npoints = len(data)

    # create the image to color the objects
    w, h = npoints, 1
    image = bpy.data.images.new('ParticleColor', width=w, height=h)

    # map data to colors
    rgba = map_colors(data, 'viridis', limits)

    # set the pixels
    image.pixels = rgba.flatten()

    # add image to Image Texture node
    image_node = node_tree.nodes.get('Image Texture', None)
    if image_node is not None:
        image_node.image = image

    # update divide node
    math_node = node_tree.nodes.get('Math', None)
    if math_node is not None:
        math_node.inputs[1].default_value = npoints

For creating the particle system:

def make_hair(parent, child, npoints=100):
    '''
    Make a Hair particle system, inspired from:
    https://github.com/SBCV/Blender-Addon-Photogrammetry-Impoarter/blob/master/photogrammetry_importer/blender_point_utils.py
    '''
    parent.modifiers.new("particle sys", type='PARTICLE_SYSTEM')
    particle_sys = parent.particle_systems[-1]
    settings = particle_sys.settings
    settings.type = 'HAIR'
    settings.use_advanced_hair = True
    settings.emit_from = 'VERT'
    settings.count = npoints
    settings.hair_length = 1  # This must not be 0
    settings.particle_size = 1
    settings.use_emit_random = False
    settings.render_type = 'OBJECT'
    settings.dupli_object = child
$\endgroup$
  • $\begingroup$ Why do you use Image texture? Divide node should output nice gradient on its own, just plug Colorramp before shader to colorize it. $\endgroup$ – Serge L Oct 21 at 15:44
  • 1
    $\begingroup$ This is just an example. In the real application I have an array of data (particle temperature) that I need to map to specific particles. So something like particle(50) has a temperature of 600C... $\endgroup$ – Onlyjus Oct 21 at 17:49
  • $\begingroup$ Maybe 32bit depth will help when creating new image, float=True. Also uncheck "random" emission in particle system. $\endgroup$ – Serge L Oct 21 at 20:19
  • $\begingroup$ I am using 2.79 (Latest that works on our machines) so I tired float_buffer=True when creating the image. That didn't seem to change anything. $\endgroup$ – Onlyjus Oct 21 at 21:03

Your Answer

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

Browse other questions tagged or ask your own question.