def build_resources(self): # ray line node line_loader = avango.gua.nodes.LineStripLoader() self.ray_line = line_loader.create_empty_geometry( 'ray_line', 'ray.lob') self.ray_line.ScreenSpaceLineWidth.value = 5.0 self.ray_line.RenderVolumetric.value = False self.ray_line.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.ray_line.Tags.value.append('invisible') self.controller_node.Children.value.append(self.ray_line) # intersection geometry self.intersection_pos_node = avango.gua.nodes.TransformNode( Name='intersection_position') self.scenegraph.Root.value.Children.value.append( self.intersection_pos_node) loader = avango.gua.nodes.TriMeshLoader() self.intersection_sphere = loader.create_geometry_from_file( 'intersection_sphere', 'data/objects/sphere.obj', avango.gua.LoaderFlags.LOAD_MATERIALS) self.intersection_sphere.Transform.value = avango.gua.make_scale_mat( 0.1) self.intersection_sphere.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.intersection_sphere.Tags.value.append('invisible') self.intersection_pos_node.Children.value.append( self.intersection_sphere) # picker self.picker = Picker(self.scenegraph) self.always_evaluate(True)
def evaluate(self): now = time.time() picker = Picker(self.scenegraph) temporary_sf_output_matrix_value = self.sf_output_matrix.value elapsed = now - self.lf_time self.lf_time = now # Height alignment vertical_pick = picker.compute_pick_result( self.scenegraph['/navigation_node/avatar'].WorldTransform.value. get_translate(), avango.gua.Vec3(0, -1, 0), 100, ['invisible']) self.climbing_lock = False if vertical_pick and vertical_pick.Object.value.Name.value == 'ball': #Checking balls vertical_pick.Object.value.Tags.value.append('invisible') self.collected_balls += 1 if self.collected_balls >= 6: print("Task completed in", time.time() - self.start_time, "seconds") elif vertical_pick and vertical_pick.Distance.value < 2: #Climb temporary_sf_output_matrix_value *= avango.gua.make_trans_mat( 0, .01, 0) self.falling_velocity = 0 self.climbing_lock = True else: #Fall self.falling_velocity += 0.00005 temporary_sf_output_matrix_value *= avango.gua.make_trans_mat( 0, -self.falling_velocity, 0) self.velocity.x = self.sf_input_x.value * .000025 self.velocity.z = self.sf_input_z.value * .000025 starting_position = self.scenegraph[ '/navigation_node/avatar'].WorldTransform.value target_movement = avango.gua.make_trans_mat(self.velocity.x, 0, self.velocity.z) target_position = starting_position * target_movement direction = target_position.get_translate( ) - starting_position.get_translate() normalized_direction = direction normalized_direction.normalize() horizontal_pick = picker.compute_pick_result( starting_position.get_translate(), normalized_direction, 10.0, ['ball']) if not horizontal_pick or horizontal_pick.Distance.value > .5: if not self.climbing_lock: temporary_sf_output_matrix_value *= target_movement self.sf_output_matrix.value = temporary_sf_output_matrix_value self.rotation_velocity.y = self.sf_input_ry.value * -0.0005 rx_rotation = self.sf_input_rx.value * (90 / 350) - 25 self.sf_rotation_output_matrix.value = avango.gua.make_rot_mat( rx_rotation, 1, 0, 0) self.sf_output_matrix.value *= avango.gua.make_rot_mat( self.rotation_velocity.y, 0, 1, 0)
def set_inputs(self, scenegraph, head_node, controller_node, controller_sensor): # store references and add geometries to scenegraph self.scenegraph = scenegraph self.head_node = head_node self.controller_node = controller_node self.controller_sensor = controller_sensor self.controller_node.Children.value.append(self.hand_node_translate) self.sf_dragging_trigger.connect_from(self.controller_sensor.Button4) # create picker self.picker = Picker(self.scenegraph) self.always_evaluate(True)
def set_inputs(self, scenegraph, head_node, controller_node, controller_sensor): # store references and add geometries to scenegraph self.scenegraph = scenegraph self.head_node = head_node self.controller_node = controller_node self.controller_sensor = controller_sensor self.controller_node.Children.value.append(self.ray_line) self.controller_node.Children.value.append(self.depth_marker) self.sf_touchpad_button.connect_from(self.controller_sensor.Button4) self.sf_touchpad_y.connect_from(self.controller_sensor.Value2) self.sf_grip_button.connect_from(self.controller_sensor.Button2) # create picker self.picker = Picker(self.scenegraph) self.always_evaluate(True)
class JumpingNavigation(avango.script.Script): # input field sf_touchpad_button = avango.SFBool() sf_touchpad_button.value = False # output field sf_navigation_matrix = avango.gua.SFMatrix4() sf_navigation_matrix.value = avango.gua.make_identity_mat() def __init__(self): self.super(JumpingNavigation).__init__() self.transition_mode = 'instant' self.ray_max_distance = 2000.0 # m self.animation_speed = 20.0 # m/s self.active = False self.animation_start_time = None self.animation_start_pos = None self.animation_target_pos = None # sets the inputs to be used for navigation def set_inputs(self, scenegraph, navigation_node, head_node, controller_node, controller_sensor): self.scenegraph = scenegraph self.navigation_node = navigation_node self.head_node = head_node self.controller_node = controller_node self.controller_sensor = controller_sensor self.build_resources() self.sf_touchpad_button.connect_from(self.controller_sensor.Button4) # builds the line node and intersection geometries def build_resources(self): # ray line node line_loader = avango.gua.nodes.LineStripLoader() self.ray_line = line_loader.create_empty_geometry( 'ray_line', 'ray.lob') self.ray_line.ScreenSpaceLineWidth.value = 5.0 self.ray_line.RenderVolumetric.value = False self.ray_line.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.ray_line.Tags.value.append('invisible') self.controller_node.Children.value.append(self.ray_line) # intersection geometry self.intersection_pos_node = avango.gua.nodes.TransformNode( Name='intersection_position') self.scenegraph.Root.value.Children.value.append( self.intersection_pos_node) loader = avango.gua.nodes.TriMeshLoader() self.intersection_sphere = loader.create_geometry_from_file( 'intersection_sphere', 'data/objects/sphere.obj', avango.gua.LoaderFlags.LOAD_MATERIALS) self.intersection_sphere.Transform.value = avango.gua.make_scale_mat( 0.1) self.intersection_sphere.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.intersection_sphere.Tags.value.append('invisible') self.intersection_pos_node.Children.value.append( self.intersection_sphere) # picker self.picker = Picker(self.scenegraph) self.always_evaluate(True) # enables or disables the navigation technique def enable(self, boolean): if boolean: self.sf_navigation_matrix.value = self.navigation_node.Transform.value self.navigation_node.Transform.disconnect() self.navigation_node.Transform.connect_from( self.sf_navigation_matrix) self.active = boolean # switches between instant and animated transition def set_transition_mode(self, mode): if mode == 'instant': self.transition_mode = 'instant' elif mode == 'animated': self.transition_mode = 'animated' self.animation_start_time = None self.animation_start_pos = None self.animation_target_pos = None # called every frame because of self.always_evaluate(True) # updates sf_navigation_matrix by processing the inputs # YOUR CODE - BEGIN (Exercises 6.2, 6.3 - Jumping Navigation) def evaluate(self): ray_direction = ( self.controller_node.WorldTransform.value * avango.gua.make_trans_mat(0, 0, -1)).get_translate( ) - self.controller_node.WorldTransform.value.get_translate() pick_results = self.picker.compute_all_pick_results( self.controller_node.WorldTransform.value.get_translate(), ray_direction, self.ray_max_distance, []) if pick_results: self.intersection_pos_node.Transform.value = avango.gua.make_trans_mat( pick_results[0].WorldPosition.value) self.ray_line.start_vertex_list() self.ray_line.enqueue_vertex(0.0, 0.0, 0.0) self.ray_line.enqueue_vertex(0.0, 0.0, -pick_results[0].Distance.value) self.ray_line.end_vertex_list() else: self.ray_line.start_vertex_list() self.ray_line.enqueue_vertex(0.0, 0.0, 0.0) self.ray_line.enqueue_vertex(0.0, 0.0, -self.ray_max_distance) self.ray_line.end_vertex_list() if self.animation_start_pos: path = self.animation_target_pos - self.animation_start_pos travel_time = path.length() / self.animation_speed elapsed_time = time.time() - self.animation_start_time self.navigation_node.Transform.value = avango.gua.make_trans_mat( self.animation_start_pos.x + (elapsed_time / travel_time) * path.x, 0, self.animation_start_pos.z + (elapsed_time / travel_time) * path.z) if elapsed_time > travel_time: self.animation_start_time = None self.animation_start_pos = None self.animation_target_pos = None # called whenever sf_touchpad_button changes @field_has_changed(sf_touchpad_button) def sf_touchpad_button_changed(self): if self.active: if self.sf_touchpad_button.value: self.ray_line.Tags.value.remove('invisible') self.intersection_sphere.Tags.value.remove('invisible') else: destination = self.navigation_node.Transform.value destination.set_element( 0, 3, self.intersection_pos_node.WorldTransform.value. get_translate().x - self.head_node.Transform.value.get_translate().x) destination.set_element( 2, 3, self.intersection_pos_node.WorldTransform.value. get_translate().z - self.head_node.Transform.value.get_translate().z) if self.transition_mode == 'animated': self.animation_start_time = time.time() self.animation_start_pos = self.head_node.WorldTransform.value.get_translate( ) self.animation_target_pos = destination.get_translate() else: self.navigation_node.Transform.value = destination self.ray_line.Tags.value.append('invisible') self.intersection_sphere.Tags.value.append('invisible')
def evaluate(self): now = time.time() elapsed = now - self.lf_time rocker_value = self.controller1_sensor.Value3.value button_value = self.controller1_sensor.Value1.value self.lf_time = now picker = Picker(self.scenegraph) # Check state change if button_value != 0.0: head_angle = self.get_y_rotation(self.head_node) target_position = self.navigation_node.WorldTransform.value * avango.gua.make_rot_mat( head_angle, 0, 1, 0) * avango.gua.make_trans_mat( 0, 0, -.005) * avango.gua.make_rot_mat( -head_angle, 0, 1, 0) starting_position = self.navigation_node.WorldTransform.value direction = target_position.get_translate( ) - starting_position.get_translate() normalized_direction = direction normalized_direction.normalize() horizontal_pick = picker.compute_pick_result( starting_position.get_translate(), normalized_direction, direction.length(), ['ball']) if not horizontal_pick: self.sf_output_matrix.value = target_position # Rocker Button if rocker_value != 0.0: pointer_position = self.controller1_node.WorldTransform.value.get_translate( ) head_position = self.head_node.WorldTransform.value.get_translate() pointer_direction = pointer_position - head_position pointer_direction *= 0.01 starting_position = self.scenegraph[ '/navigation_node'].WorldTransform.value target_position = self.sf_output_matrix.value * avango.gua.make_trans_mat( pointer_direction.x, 0, pointer_direction.z) direction = target_position.get_translate( ) - starting_position.get_translate() normalized_direction = direction normalized_direction.normalize() horizontal_pick = picker.compute_pick_result( starting_position.get_translate(), normalized_direction, direction.length(), ['ball']) if not horizontal_pick: self.sf_output_matrix.value = target_position # Height alignment vertical_pick = picker.compute_pick_result( self.scenegraph['/navigation_node'].WorldTransform.value. get_translate(), avango.gua.Vec3(0, -1, 0), 20, ['invisible']) if vertical_pick and vertical_pick.Object.value.Name.value == 'ball': vertical_pick.Object.value.Tags.value.append('invisible') self.collected_balls += 1 if self.collected_balls >= 6: print("Task completed in", time.time() - self.start_time, "seconds") elif vertical_pick and vertical_pick.Distance.value <= 2: self.sf_output_matrix.value *= avango.gua.make_trans_mat( 0, 0.005, 0) self.falling_velocity = 0 else: self.falling_velocity += 0.000007 self.sf_output_matrix.value *= avango.gua.make_trans_mat( 0, -self.falling_velocity, 0)
class VirtualHandInteraction(avango.script.Script): # input field sf_dragging_trigger = avango.SFBool() sf_dragging_trigger.value = False def __init__(self): self.super(VirtualHandInteraction).__init__() # YOUR CODE - BEGIN (Add additional variables if necessary) # ... # YOUR CODE - END (Add additional variables if necessary) self.highlighted_object = None self.dragging_object = None self.enable_flag = False self.create_resources() # enables and disables this interaction technique def enable(self, boolean): if boolean: self.hand_node.Tags.value.remove('invisible') else: self.hand_node.Tags.value.append('invisible') self.enable_flag = boolean # creates the necessary geometries for this interaction technique def create_resources(self): self.hand_node_translate = avango.gua.nodes.TransformNode( Name='hand_translate') self.hand_node_translate.Transform.value = avango.gua.make_identity_mat( ) loader = avango.gua.nodes.TriMeshLoader() self.hand_node = loader.create_geometry_from_file( 'hand_node', 'data/objects/hand.obj', avango.gua.LoaderFlags.LOAD_MATERIALS) self.hand_node.Material.value.set_uniform('Roughness', 0.6) self.hand_node.Tags.value.append('invisible') self.hand_node_translate.Children.value.append(self.hand_node) # sets the correct inputs to be used for this interaction technique def set_inputs(self, scenegraph, head_node, controller_node, controller_sensor): # store references and add geometries to scenegraph self.scenegraph = scenegraph self.head_node = head_node self.controller_node = controller_node self.controller_sensor = controller_sensor self.controller_node.Children.value.append(self.hand_node_translate) self.sf_dragging_trigger.connect_from(self.controller_sensor.Button4) # create picker self.picker = Picker(self.scenegraph) self.always_evaluate(True) # called every frame because of self.always_evaluate(True) def evaluate(self): if self.enable_flag: self.apply_gogo(0.5) if self.dragging_object is not None: self.dragging_update() else: pick_result = self.compute_pick_result() self.update_highlights(pick_result) # updates the position of the virtual hand with respect to the GoGo mapping def apply_gogo(self, threshold): hand_pos = self.controller_node.WorldTransform.value.get_translate() head_pos = self.head_node.WorldTransform.value.get_translate() # YOUR CODE - BEGIN (Exercise 5.3 - GoGo) orientation = hand_pos - head_pos orientation.y = 0 distance = orientation.length() if distance >= 0.3: self.hand_node_translate.Transform.value = avango.gua.make_trans_mat( 0, 0, -20 * (distance - 0.3)**2) # YOUR CODE - END (Exercise 5.3 - GoGo) # computes intersections of the hand with the scene def compute_pick_result(self): # YOUR CODE - BEGIN (Exercise 5.1 - Compute pick result) direction = (self.hand_node.WorldTransform.value * avango.gua.make_trans_mat(0, 0, -1)).get_translate( ) - self.hand_node.WorldTransform.value.get_translate() result = self.picker.compute_all_pick_results( self.hand_node.WorldTransform.value.get_translate(), direction, 0.2, []) if result: return result[0] return None # YOUR CODE - END (Exercise 5.1 - Compute pick result) # updates the object highlights with respect to a pick result def update_highlights(self, pick_result): if pick_result is not None: if self.highlighted_object is not None and \ pick_result.Object.value.Name.value != self.highlighted_object.Name.value: self.remove_highlight() self.highlight_object(pick_result.Object.value) else: self.remove_highlight() # highlights an object def highlight_object(self, node): node.Material.value.set_uniform('Color', avango.gua.Vec4(1.0, 1.0, 1.0, 1.0)) self.highlighted_object = node # removes the current object highlight def remove_highlight(self): if self.highlighted_object is not None: color_id = int(self.highlighted_object.Tags.value[0]) self.highlighted_object.Material.value.set_uniform( 'Color', config.OBJECT_COLORS[color_id]) self.highlighted_object = None # called once when the dragging button is pressed def start_dragging(self): if self.highlighted_object is not None: # YOUR CODE - BEGIN (Exercise 5.2 - Object Dragging) self.dragging_object = self.highlighted_object position = avango.gua.make_inverse_mat( self.hand_node.WorldTransform.value ) * self.dragging_object.Transform.value self.hand_node.Children.value.append(self.dragging_object) self.dragging_object.Transform.value = position self.scenegraph.Root.value.Children.value.remove( self.dragging_object) # YOUR CODE - END (Exercise 5.2 - Object Dragging) # called during every frame of a dragging operation def dragging_update(self): # YOUR CODE - BEGIN (Exercise 5.2 - Object Dragging) pass # YOUR CODE - END (Exercise 5.2 - Object Dragging) # called once when the dragging button is released def stop_dragging(self): # YOUR CODE - BEGIN (Exercise 5.2 - Object Dragging) if self.dragging_object: position = self.dragging_object.WorldTransform.value self.scenegraph.Root.value.Children.value.append( self.dragging_object) self.dragging_object.Transform.value = position self.hand_node.Children.value.remove(self.dragging_object) self.dragging_object = None # YOUR CODE - END (Exercise 5.2 - Object Dragging) # called whenever sf_dragging_trigger changes and calls start_dragging() # or stop_dragging() depending on the current button state @field_has_changed(sf_dragging_trigger) def sf_dragging_trigger_changed(self): if self.sf_dragging_trigger.value: self.start_dragging() else: self.stop_dragging()
class VirtualRayInteraction(avango.script.Script): # input fields sf_touchpad_button = avango.SFBool() sf_touchpad_button.value = False sf_touchpad_y = avango.SFFloat() sf_touchpad_y.value = 0.0 sf_grip_button = avango.SFBool() sf_grip_button.value = False def __init__(self): self.super(VirtualRayInteraction).__init__() # YOUR CODE - BEGIN (Add additional variables if necessary) self.teleportable_object = None # YOUR CODE - END (Add additional variables if necessary) self.ray_max_distance = 10.0 self.highlighted_object = None self.enable_flag = False self.create_resources() # enables and disables this interaction technique def enable(self, boolean): if boolean: self.ray_line.Tags.value.remove('invisible') self.depth_marker.Tags.value.remove('invisible') else: self.ray_line.Tags.value.append('invisible') self.depth_marker.Tags.value.append('invisible') self.enable_flag = boolean # creates the necessary geometries for this interaction technique def create_resources(self): line_loader = avango.gua.nodes.LineStripLoader() self.ray_line = line_loader.create_empty_geometry('ray_line', 'ray.lob') self.ray_line.ScreenSpaceLineWidth.value = 5.0 self.ray_line.RenderVolumetric.value = False self.ray_line.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.ray_line.start_vertex_list() self.ray_line.enqueue_vertex(0.0, 0.0, 0.0) self.ray_line.enqueue_vertex(0.0, 0.0, -self.ray_max_distance) self.ray_line.end_vertex_list() self.ray_line.Tags.value.append('invisible') loader = avango.gua.nodes.TriMeshLoader() self.depth_marker = loader.create_geometry_from_file('depth_marker', 'data/objects/sphere.obj', avango.gua.LoaderFlags.LOAD_MATERIALS) self.depth_marker.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 0.0, 0.0, 1.0)) self.depth_marker.Tags.value.append('invisible') # sets the correct inputs to be used for this interaction technique def set_inputs(self, scenegraph, head_node, controller_node, controller_sensor): # store references and add geometries to scenegraph self.scenegraph = scenegraph self.head_node = head_node self.controller_node = controller_node self.controller_sensor = controller_sensor self.controller_node.Children.value.append(self.ray_line) self.controller_node.Children.value.append(self.depth_marker) self.sf_touchpad_button.connect_from(self.controller_sensor.Button4) self.sf_touchpad_y.connect_from(self.controller_sensor.Value2) self.sf_grip_button.connect_from(self.controller_sensor.Button2) # create picker self.picker = Picker(self.scenegraph) self.always_evaluate(True) # called every frame because of self.always_evaluate(True) def evaluate(self): if self.enable_flag: self.update_depth_marker() pick_result = self.compute_pick_result() self.update_highlights(pick_result) # updates the depth marker with respect to button inputs def update_depth_marker(self): # YOUR CODE - BEGIN (Exercises 5.5 - Depth Marker) if self.sf_touchpad_button.value: temporary_transform = self.depth_marker.Transform.value * avango.gua.make_trans_mat(0,0,-self.sf_touchpad_y.value*0.01) if temporary_transform.get_translate().z > -self.ray_max_distance and temporary_transform.get_translate().z < 0: self.depth_marker.Transform.value = temporary_transform # YOUR CODE - END (Exercises 5.5 - Depth Marker) # computes intersections of the ray with the scene def compute_pick_result(self): # YOUR CODE - BEGIN (Exercises 5.4, 5.5 - Compute pick result) direction = (self.controller_node.WorldTransform.value * avango.gua.make_trans_mat(0,0,-1)).get_translate() - self.controller_node.WorldTransform.value.get_translate() results = self.picker.compute_all_pick_results(self.controller_node.WorldTransform.value.get_translate(),direction,self.ray_max_distance,[]) result = None minimum = self.ray_max_distance for pick in results: vector = pick.Object.value.WorldTransform.value.get_translate() - self.depth_marker.WorldTransform.value.get_translate() distance = vector.length() if distance < minimum: result = pick minimum = distance if distance > minimum: break if result: return result # YOUR CODE - END (Exercises 5.4, 5.5 - Compute pick result) # updates the object highlights with respect to a pick result def update_highlights(self, pick_result): if pick_result is not None: if self.highlighted_object is not None and \ pick_result.Object.value.Name.value != self.highlighted_object.Name.value: self.remove_highlight() self.highlight_object(pick_result.Object.value) else: self.remove_highlight() # highlights an object when hit with the intersection ray def highlight_object(self, node): node.Material.value.set_uniform( 'Color', avango.gua.Vec4(1.0, 1.0, 1.0, 1.0)) self.highlighted_object = node # removes the current object highlight def remove_highlight(self): if self.highlighted_object is not None: color_id = int(self.highlighted_object.Tags.value[0]) self.highlighted_object.Material.value.set_uniform( 'Color', config.OBJECT_COLORS[color_id]) self.highlighted_object = None # called whenever sf_grip_button button changes @field_has_changed(sf_grip_button) def sf_grip_button_changed(self): if self.sf_grip_button.value: # YOUR CODE - BEGIN (Exercise 5.6 - Object Teleport) if self.teleportable_object: new_mat = self.teleportable_object.Transform.value new_mat.set_element(0,3,self.depth_marker.WorldTransform.value.get_translate().x) new_mat.set_element(1,3,self.depth_marker.WorldTransform.value.get_translate().y) new_mat.set_element(2,3,self.depth_marker.WorldTransform.value.get_translate().z) self.teleportable_object.Transform.value = new_mat self.teleportable_object.Tags.value.remove('invisible') self.teleportable_object = None elif self.highlighted_object: self.teleportable_object = self.highlighted_object self.teleportable_object.Tags.value.append('invisible')