Picking Instanced Geo based on proximity and keyboard command

Right now i am detecting clicks on my instanced geo using a renderpick chop. When some geo is clicked, a transition specific to that instance is triggered. Instead of clicking, i want the instanced geo to have a glowing outline when a null (that is controlling the camera, at the center of the camera view) is closest to that instanced geo object within a certain range, and then if the user hits the enter key then it will do the same as clicking does currently.

I am sure this has been done before. Does anyone know of any examples?

nevermind, figured it out! will try to remember to post my solution for others tomorrow

1 Like

Hi @nerk,

would be interesting to see your solution. My first instinct would be to follow the technique for picking in VR which is implemented in the rayPick component in the Palette>TDVR>System Components folder.
The summary of the component is that you are using a 1x1 pixel render with a camera that functions as your pointer. By increasing the Pick Radius you should be able to get objects in proximity to the camera view.

cheers
Markus

I knew there must have been something similar around somewhere for me to pick.

Here’s how “I” did it - with the help of AI (sorry if that offends anyone lol).

So I have my instance positions in the top row, middle row I have my null object that controls the camera via an object CHOP. I don’t think that constant at the bottom is doing anything i deleted it.
Pump them into a script CHOP (Code below) which gives me:

  1. A channel with the number instance closest to my null within a given threshold in the first sample
  2. A channel with the distance to that instance in the first sample
  3. A channel where the instance closest to the null within a threshold will have its corresponding sample set to 1. All other samples 0. A bit redundant to #1, but this all seems to work!

@snaut I am now trying to figure out how to get a nice outline around the geo closest to the null (or some other way to show that the particular instanced geo is “selected”). I am not familiar with GLSL which seems like it would be the easiest way to do it if I had those chops. Any chance you have any leads for me? Thanks!

# me - this DAT
# scriptOp - the OP which is cooking
#
# inputs[0] contains channels from instance_positions_chop
# inputs[1] contains channels from controller_pos_chop

def onCook(scriptOp):
    scriptOp.clear() # Clear previous channels

    # Get controller position (assuming it has only one sample)
    controller_x = scriptOp.inputs[1]['nx'][0]
    controller_y = scriptOp.inputs[1]['ny'][0]
    controller_z = scriptOp.inputs[1]['nz'][0]

    # Get instance positions
    inst_x = scriptOp.inputs[0]['tx']
    inst_y = scriptOp.inputs[0]['ty']
    inst_z = scriptOp.inputs[0]['tz']

    num_instances = len(inst_x)
    min_dist_sq = float('inf')
    closest_index = -1
    max_range = scriptOp.par.Valuea.eval() # Define a custom parameter 'Maxrange'
    max_range_sq = max_range * max_range

    if num_instances > 0:
        for i in range(num_instances):
            dx = inst_x[i] - controller_x
            dy = inst_y[i] - controller_y
            dz = inst_z[i] - controller_z
            dist_sq = dx*dx + dy*dy + dz*dz # Use squared distance for efficiency

            if dist_sq < min_dist_sq:
                min_dist_sq = dist_sq
                closest_index = i

        # Check if the closest is within range
        if min_dist_sq > max_range_sq:
            closest_index = -1 # Reset if too far

    # --- Output Channels ---
    # Index of the closest instance (-1 if none in range)
    out_index = scriptOp.appendChan('closest_index')
    out_index[0] = closest_index

    # Minimum distance (sqrt of squared distance)
    out_dist = scriptOp.appendChan('min_distance')
    out_dist[0] = 0.0 if closest_index == -1 else min_dist_sq**0.5

    # Create a highlight channel for all instances
    out_highlight = scriptOp.appendChan('highlight')
    # out_highlight['highlight'].numSamples = num_instances # Match number of instances
    for i in range(num_instances):
        out_highlight[i] = 1.0 if i == closest_index else 0.0

    return

# Add a custom parameter to the Script CHOP
# page = scriptOp.appendCustomPage('Custom')
# page.appendFloat('Maxrange', label='Max Selection Range')
# Set a default value, e.g., 5