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?
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.
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:
A channel with the number instance closest to my null within a given threshold in the first sample
A channel with the distance to that instance in the first sample
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