def show(molecule, width=500, height=500, show_bonds=True, bonds_method='radii', bonds_param=None, camera=None, title='mogli'): """ Interactively show the given molecule with OpenGL. By default, bonds are drawn, if this is undesired the show_bonds parameter can be set to False. For information on the bond calculation, see Molecule.calculate_bonds. If you pass a tuple of camera position, center of view and an up vector to the camera parameter, the camera will be set accordingly. Otherwise the molecule will be viewed in the direction of the z axis, with the y axis pointing upward. """ global _camera molecule.positions -= np.mean(molecule.positions, axis=0) max_atom_distance = np.max(la.norm(molecule.positions, axis=1)) if show_bonds: molecule.calculate_bonds(bonds_method, bonds_param) # If GR3 was initialized earlier, it would use a different context, so # it will be terminated first. gr3.terminate() # Initialize GLFW and create an OpenGL context glfw.init() glfw.window_hint(glfw.SAMPLES, 16) window = glfw.create_window(width, height, title, None, None) glfw.make_context_current(window) glEnable(GL_MULTISAMPLE) # Set up the camera (it will be changed during mouse rotation) if camera is None: camera_distance = -max_atom_distance*2.5 camera = ((0, 0, camera_distance), (0, 0, 0), (0, 1, 0)) camera = np.array(camera) _camera = camera # Create the GR3 scene gr3.setbackgroundcolor(255, 255, 255, 0) _create_gr3_scene(molecule, show_bonds) # Configure GLFW glfw.set_cursor_pos_callback(window, _mouse_move_callback) glfw.set_mouse_button_callback(window, _mouse_click_callback) glfw.swap_interval(1) # Start the GLFW main loop while not glfw.window_should_close(window): glfw.poll_events() width, height = glfw.get_window_size(window) glViewport(0, 0, width, height) _set_gr3_camera() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) gr3.drawimage(0, width, 0, height, width, height, gr3.GR3_Drawable.GR3_DRAWABLE_OPENGL) glfw.swap_buffers(window) glfw.terminate() gr3.terminate()
def start(self): if not glfw.init(): return glfw.window_hint(glfw.SAMPLES, 4) # try stereo if refresh rate is at least 100Hz window = None stereo_available = False _, _, refresh_rate = glfw.get_video_mode(glfw.get_primary_monitor()) if refresh_rate >= 100: glfw.window_hint(glfw.STEREO, 1) window = glfw.create_window(500, 500, "Simulate", None, None) if window: stereo_available = True # no stereo: try mono if not window: glfw.window_hint(glfw.STEREO, 0) window = glfw.create_window(500, 500, "Simulate", None, None) if not window: glfw.terminate() return self.running = True # Make the window's context current glfw.make_context_current(window) width, height = glfw.get_framebuffer_size(window) width1, height = glfw.get_window_size(window) self._scale = width * 1.0 / width1 self.window = window mjlib.mjv_makeObjects(byref(self.objects), 1000) mjlib.mjv_defaultCamera(byref(self.cam)) mjlib.mjv_defaultOption(byref(self.vopt)) mjlib.mjr_defaultOption(byref(self.ropt)) mjlib.mjr_defaultContext(byref(self.con)) if self.model: mjlib.mjr_makeContext(self.model.ptr, byref(self.con), 150) self.autoscale() else: mjlib.mjr_makeContext(None, byref(self.con), 150) glfw.set_cursor_pos_callback(window, self.handle_mouse_move) glfw.set_mouse_button_callback(window, self.handle_mouse_button) glfw.set_scroll_callback(window, self.handle_scroll)
def __init__(self, sim): super().__init__(sim) self._gui_lock = Lock() self._button_left_pressed = False self._button_right_pressed = False self._last_mouse_x = 0 self._last_mouse_y = 0 framebuffer_width, _ = glfw.get_framebuffer_size(self.window) window_width, _ = glfw.get_window_size(self.window) self._scale = framebuffer_width * 1.0 / window_width glfw.set_cursor_pos_callback(self.window, self._cursor_pos_callback) glfw.set_mouse_button_callback( self.window, self._mouse_button_callback) glfw.set_scroll_callback(self.window, self._scroll_callback) glfw.set_key_callback(self.window, self.key_callback)
def _mouse_move_callback(window, x, y): """ Mouse move event handler for GLFW. """ global _previous_mouse_position, _camera if _mouse_dragging and _camera is not None: width, height = glfw.get_window_size(window) dx = (x-_previous_mouse_position[0])/width dy = (y-_previous_mouse_position[1])/height rotation_intensity = la.norm((dx, dy)) * 2 eye, center, up = _camera camera_distance = la.norm(center-eye) forward = (center-eye)/camera_distance right = np.cross(forward, up) rotation_axis = (up*dx+right*dy) rotation_matrix = _create_rotation_matrix(-rotation_intensity, rotation_axis[0], rotation_axis[1], rotation_axis[2]) forward = np.dot(rotation_matrix, forward) up = np.dot(rotation_matrix, up) eye = center-forward*camera_distance _camera = eye, center, up _previous_mouse_position = (x, y)
def __init__(self, window): super(Client, self).__init__() self.window = window self.width, self.height = glfw.get_window_size(window) self.init()
def process(self, path=False, vertices=False, indices=False, info= False): if path: vertices, element_dict, info = read_model(path) indices = element_dict["triangles"] print(f"Reading {path}") else: assert (type(vertices) ==np.ndarray and type(indices) ==np.ndarray), "Define path or both vertices and indices" pre_box = indices.size bounding_rect_vertices, bounding_rect_indices = bounding_box(vertices,indices) vertices = np.append(vertices,bounding_rect_vertices) indices = np.append(indices,bounding_rect_indices) vertex_normals = pyrr.vector3.generate_vertex_normals(vertices.reshape((-1,3)), indices.reshape((-1,3)), normalize_result=True).flatten() vertices_final = np.append(vertices,vertex_normals) # initializing glfw library if not glfw.init(): raise Exception("glfw can not be initialized!") # creating the window window = glfw.create_window(1280, 720, "My OpenGL window", None, None) input_handler = InputHandler(window) # check if window was created if not window: glfw.terminate() raise Exception("glfw window can not be created!") # set window's position glfw.set_window_pos(window, 400, 200) # set the callback function for window resize glfw.set_window_size_callback(window, self.window_resize) # make the context current glfw.make_context_current(window) as_points = vertices.reshape(-1, 3) barycenter = as_points.mean(axis=0) max_x, max_y, max_z = as_points.max(axis=0) min_x, min_y, min_z = as_points.min(axis=0) middle_point = np.array( [min_x + (max_x-min_x)/2, min_y + (max_y-min_y)/2, min_z + (max_z-min_z)/2]) shader = shader_loader.compile_shader("src/shaders/vert.vs", "src/shaders/frag.fs") # Vertex Buffer Object VBO = glGenBuffers(1) VA0 = glGenVertexArrays(1) glBindBuffer(GL_ARRAY_BUFFER, VBO) glBufferData(GL_ARRAY_BUFFER, vertices_final.nbytes, vertices_final, GL_STATIC_DRAW) #positions glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*4, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) #normals glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3*4, ctypes.c_void_p(4*len(vertices))) glEnableVertexAttribArray(1) # Element Buffer Object EBO = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO) glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_STATIC_DRAW) glUseProgram(shader) glClearColor(0, 0.1, 0.1, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glEnable(GL_DEPTH_TEST) ## Shader matrices model_loc = glGetUniformLocation(shader, "model") self.proj_loc = glGetUniformLocation(shader, "projection") view_loc = glGetUniformLocation(shader, "view") color_loc = glGetUniformLocation(shader,"color") transform_loc = glGetUniformLocation(shader, "transform") light_loc = glGetUniformLocation(shader, "light") window_height = glfw.get_window_size(window)[1] window_width = glfw.get_window_size(window)[0] projection = pyrr.matrix44.create_perspective_projection_matrix( fovy=45, aspect=window_width/window_height, near=0.1, far=100) #projection = pyrr.matrix44.create_orthogonal_projection_matrix(0,1280,0,720,-1000,1000) scale = pyrr.matrix44.create_from_scale(pyrr.Vector3([1]*3)) # eye pos , target, up view = pyrr.matrix44.create_look_at(pyrr.Vector3( [0, 0, 3]), pyrr.Vector3([0, 0, 0]), pyrr.Vector3([0, 1, 0])) proj_matrix = glGetUniformLocation(shader, "projection") initial_offset = middle_point translation = pyrr.matrix44.create_from_translation( pyrr.Vector3(-initial_offset)) ## Input rotation = pyrr.matrix44.create_from_axis_rotation(np.array([0, 1, 0]), 0) glfw.set_key_callback(window, input_handler.keyboard_handler) glfw.set_scroll_callback(window, input_handler.scroll_handler) glfw.set_mouse_button_callback(window, input_handler.mouse_handler) previous_displacement = np.zeros(2) rot_y = pyrr.Matrix44.from_y_rotation(0.8 * glfw.get_time() ) glUniformMatrix4fv(transform_loc, 1, GL_FALSE, rot_y) glEnable(GL_LIGHTING) glEnable(GL_COLOR_MATERIAL) while not glfw.window_should_close(window): glfw.poll_events() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) if input_handler.right_key_pressed: current_cursor_position = glfw.get_cursor_pos(window) cursor_displacement = np.array(current_cursor_position) - np.array( input_handler.start_cursor_position) - previous_displacement input_handler.rotation_list[0] += input_handler.rotations_per_screen_hor * \ cursor_displacement[0]/window_width input_handler.rotation_list[1] += input_handler.rotations_per_screen_vert * \ cursor_displacement[1]/window_height previous_displacement = cursor_displacement rot_x = pyrr.Matrix44.from_x_rotation(input_handler.rotation_list[1]) rot_y = pyrr.Matrix44.from_y_rotation(input_handler.rotation_list[0]) rotation = pyrr.matrix44.multiply(rot_x, rot_y) view = pyrr.matrix44.create_look_at(pyrr.Vector3(input_handler.eye), pyrr.Vector3( input_handler.target), pyrr.Vector3(input_handler.up)) light = pyrr.matrix44.create_identity() glUniformMatrix4fv(light_loc, 1, GL_FALSE, light) model = pyrr.matrix44.multiply(scale, translation) model = pyrr.matrix44.multiply(model, rotation) glUniformMatrix4fv(model_loc, 1, GL_FALSE, model) glUniformMatrix4fv(view_loc, 1, GL_FALSE, view) glUniformMatrix4fv(proj_matrix, 1, GL_FALSE, projection) default_RGB = np.zeros(shape=(3,),dtype=np.float32) +1 color = pyrr.Vector3(default_RGB) glUniform3fv(color_loc,1,color) if input_handler.mode == "default": glDrawElements(GL_TRIANGLES, pre_box, GL_UNSIGNED_INT, None) elif input_handler.mode == "point_cloud": glDrawElements(GL_POINTS, pre_box, GL_UNSIGNED_INT, None) elif input_handler.mode=="wireframe": glEnable(GL_POLYGON_OFFSET_FILL) glPolygonOffset(1.0, 2) glDrawElements(GL_TRIANGLES, pre_box, GL_UNSIGNED_INT, None) RGB = np.zeros(shape=(3,),dtype=np.float32) color = pyrr.Vector3(RGB) glUniform3fv(color_loc,1,RGB) glDrawElements(GL_LINES, pre_box, GL_UNSIGNED_INT, None) elif input_handler.mode == "bounding_box": glDrawElements(GL_LINES, len(indices), GL_UNSIGNED_INT, None) else: raise Exception("Invalid Mode!") glfw.swap_buffers(window) # terminate glfw, free up allocated resources glfw.terminate()
def height(self): return glfw.get_window_size(self.window)[1]
def world( timebase, eye_procs_alive, ipc_pub_url, ipc_sub_url, ipc_push_url, user_dir, version, preferred_remote_port, hide_ui, debug, ): """Reads world video and runs plugins. Creates a window, gl context. Grabs images from a capture. Maps pupil to gaze data Can run various plug-ins. Reacts to notifications: ``eye_process.started`` ``start_plugin`` ``should_stop`` Emits notifications: ``eye_process.should_start`` ``eye_process.should_stop`` ``world_process.started`` ``world_process.stopped`` ``recording.should_stop``: Emits on camera failure ``launcher_process.should_stop`` Emits data: ``gaze``: Gaze data from current gaze mapping plugin.`` ``*``: any other plugin generated data in the events that it not [dt,pupil,gaze]. """ # We defer the imports because of multiprocessing. # Otherwise the world process each process also loads the other imports. # This is not harmful but unnecessary. # general imports from time import sleep import logging # networking import zmq import zmq_tools # zmq ipc setup zmq_ctx = zmq.Context() ipc_pub = zmq_tools.Msg_Dispatcher(zmq_ctx, ipc_push_url) notify_sub = zmq_tools.Msg_Receiver(zmq_ctx, ipc_sub_url, topics=("notify",)) # log setup logging.getLogger("OpenGL").setLevel(logging.ERROR) logger = logging.getLogger() logger.handlers = [] logger.setLevel(logging.NOTSET) logger.addHandler(zmq_tools.ZMQ_handler(zmq_ctx, ipc_push_url)) # create logger for the context of this function logger = logging.getLogger(__name__) def launch_eye_process(eye_id, delay=0): n = { "subject": "eye_process.should_start.{}".format(eye_id), "eye_id": eye_id, "delay": delay, } ipc_pub.notify(n) def stop_eye_process(eye_id): n = { "subject": "eye_process.should_stop.{}".format(eye_id), "eye_id": eye_id, "delay": 0.2, } ipc_pub.notify(n) def start_stop_eye(eye_id, make_alive): if make_alive: launch_eye_process(eye_id) else: stop_eye_process(eye_id) def detection_enabled_getter() -> bool: return g_pool.pupil_detection_enabled def detection_enabled_setter(is_on: bool): g_pool.pupil_detection_enabled = is_on n = {"subject": "set_pupil_detection_enabled", "value": is_on} ipc_pub.notify(n) try: from background_helper import IPC_Logging_Task_Proxy IPC_Logging_Task_Proxy.push_url = ipc_push_url from tasklib.background.patches import IPCLoggingPatch IPCLoggingPatch.ipc_push_url = ipc_push_url from OpenGL.GL import GL_COLOR_BUFFER_BIT # display import glfw glfw.ERROR_REPORTING = "raise" from version_utils import parse_version from pyglui import ui, cygl, __version__ as pyglui_version assert parse_version(pyglui_version) >= parse_version( "1.27" ), "pyglui out of date, please upgrade to newest version" from pyglui.cygl.utils import Named_Texture import gl_utils # helpers/utils from file_methods import Persistent_Dict from methods import normalize, denormalize, delta_t, get_system_info, timer from uvc import get_time_monotonic logger.info("Application Version: {}".format(version)) logger.info("System Info: {}".format(get_system_info())) logger.debug(f"Debug flag: {debug}") import audio # Plug-ins from plugin import ( Plugin, System_Plugin_Base, Plugin_List, import_runtime_plugins, ) from plugin_manager import Plugin_Manager from calibration_choreography import ( available_calibration_choreography_plugins, CalibrationChoreographyPlugin, patch_loaded_plugins_with_choreography_plugin, ) available_choreography_plugins = available_calibration_choreography_plugins() from gaze_mapping import registered_gazer_classes from gaze_mapping.gazer_base import GazerBase from pupil_detector_plugins.detector_base_plugin import PupilDetectorPlugin from fixation_detector import Fixation_Detector from recorder import Recorder from display_recent_gaze import Display_Recent_Gaze from time_sync import Time_Sync from network_api import NetworkApiPlugin from pupil_groups import Pupil_Groups from surface_tracker import Surface_Tracker_Online from log_display import Log_Display from annotations import Annotation_Capture from log_history import Log_History from blink_detection import Blink_Detection from video_capture import ( source_classes, manager_classes, Base_Manager, Base_Source, ) from pupil_data_relay import Pupil_Data_Relay from remote_recorder import Remote_Recorder from accuracy_visualizer import Accuracy_Visualizer from system_graphs import System_Graphs from camera_intrinsics_estimation import Camera_Intrinsics_Estimation from hololens_relay import Hololens_Relay from head_pose_tracker.online_head_pose_tracker import Online_Head_Pose_Tracker # UI Platform tweaks if platform.system() == "Linux": scroll_factor = 10.0 window_position_default = (30, 30) elif platform.system() == "Windows": scroll_factor = 10.0 window_position_default = (8, 90) else: scroll_factor = 1.0 window_position_default = (0, 0) process_was_interrupted = False def interrupt_handler(sig, frame): import traceback trace = traceback.format_stack(f=frame) logger.debug(f"Caught signal {sig} in:\n" + "".join(trace)) nonlocal process_was_interrupted process_was_interrupted = True signal.signal(signal.SIGINT, interrupt_handler) icon_bar_width = 50 window_size = None camera_render_size = None content_scale = 1.0 # g_pool holds variables for this process they are accessible to all plugins g_pool = SimpleNamespace() g_pool.debug = debug g_pool.app = "capture" g_pool.process = "world" g_pool.user_dir = user_dir g_pool.version = version g_pool.timebase = timebase g_pool.zmq_ctx = zmq_ctx g_pool.ipc_pub = ipc_pub g_pool.ipc_pub_url = ipc_pub_url g_pool.ipc_sub_url = ipc_sub_url g_pool.ipc_push_url = ipc_push_url g_pool.eye_procs_alive = eye_procs_alive g_pool.preferred_remote_port = preferred_remote_port def get_timestamp(): return get_time_monotonic() - g_pool.timebase.value g_pool.get_timestamp = get_timestamp g_pool.get_now = get_time_monotonic # manage plugins runtime_plugins = import_runtime_plugins( os.path.join(g_pool.user_dir, "plugins") ) runtime_plugins = [ p for p in runtime_plugins if not issubclass(p, PupilDetectorPlugin) ] user_plugins = [ Pupil_Groups, NetworkApiPlugin, Time_Sync, Surface_Tracker_Online, Annotation_Capture, Log_History, Fixation_Detector, Blink_Detection, Remote_Recorder, Accuracy_Visualizer, Camera_Intrinsics_Estimation, Hololens_Relay, Online_Head_Pose_Tracker, ] system_plugins = ( [ Log_Display, Display_Recent_Gaze, Recorder, Pupil_Data_Relay, Plugin_Manager, System_Graphs, ] + manager_classes + source_classes ) plugins = ( system_plugins + user_plugins + runtime_plugins + available_choreography_plugins + registered_gazer_classes() ) user_plugins += [ p for p in runtime_plugins if not isinstance( p, ( Base_Manager, Base_Source, System_Plugin_Base, CalibrationChoreographyPlugin, GazerBase, ), ) ] g_pool.plugin_by_name = {p.__name__: p for p in plugins} default_capture_name = "UVC_Source" default_capture_settings = { "preferred_names": [ "Pupil Cam1 ID2", "Logitech Camera", "(046d:081d)", "C510", "B525", "C525", "C615", "C920", "C930e", ], "frame_size": (1280, 720), "frame_rate": 30, } default_plugins = [ (default_capture_name, default_capture_settings), ("Pupil_Data_Relay", {}), ("UVC_Manager", {}), ("NDSI_Manager", {}), ("HMD_Streaming_Manager", {}), ("File_Manager", {}), ("Log_Display", {}), ("Dummy_Gaze_Mapper", {}), ("Display_Recent_Gaze", {}), # Calibration choreography plugin is added below by calling # patch_loaded_plugins_with_choreography_plugin ("Recorder", {}), ("NetworkApiPlugin", {}), ("Fixation_Detector", {}), ("Blink_Detection", {}), ("Accuracy_Visualizer", {}), ("Plugin_Manager", {}), ("System_Graphs", {}), ] def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *camera_render_size) for p in g_pool.plugins: p.gl_display() gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() except (AttributeError, glfw.GLFWError): # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, camera_render_size) # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for plugin in g_pool.plugins: if plugin.on_click(pos, button, action): break for key, scancode, action, mods in user_input.keys: for plugin in g_pool.plugins: if plugin.on_key(key, scancode, action, mods): break for char_ in user_input.chars: for plugin in g_pool.plugins: if plugin.on_char(char_): break glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): nonlocal window_size nonlocal camera_render_size nonlocal content_scale if w == 0 or h == 0: return # Always clear buffers on resize to make sure that there are no overlapping # artifacts from previous frames. gl_utils.glClear(GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) content_scale = gl_utils.get_content_scale(window) framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h camera_render_size = w - int(icon_bar_width * g_pool.gui.scale), h g_pool.gui.update_window(*window_size) g_pool.gui.collect_menus() for p in g_pool.plugins: p.on_window_resize(window, *camera_render_size) # Minimum window size required, otherwise parts of the UI can cause openGL # issues with permanent effects. Depends on the content scale, which can # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) glfw.set_window_size_limits( window, min_size, min_size, glfw.DONT_CARE, glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing consume_events_and_render_buffer() def on_window_key(window, key, scancode, action, mods): g_pool.gui.update_key(key, scancode, action, mods) def on_window_char(window, char): g_pool.gui.update_char(char) def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) pos = x, y pos = normalize(pos, camera_render_size) # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for p in g_pool.plugins: p.on_pos(pos) def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) def on_drop(window, paths): for plugin in g_pool.plugins: if plugin.on_drop(paths): break tick = delta_t() def get_dt(): return next(tick) # load session persistent settings session_settings = Persistent_Dict( os.path.join(g_pool.user_dir, "user_settings_world") ) if parse_version(session_settings.get("version", "0.0")) != g_pool.version: logger.info( "Session setting are from a different version of this app. I will not use those." ) session_settings.clear() g_pool.min_data_confidence = 0.6 g_pool.min_calibration_confidence = session_settings.get( "min_calibration_confidence", 0.8 ) g_pool.pupil_detection_enabled = session_settings.get( "pupil_detection_enabled", True ) g_pool.active_gaze_mapping_plugin = None g_pool.capture = None audio.set_audio_mode( session_settings.get("audio_mode", audio.get_default_audio_mode()) ) def handle_notifications(noti): subject = noti["subject"] if subject == "set_pupil_detection_enabled": g_pool.pupil_detection_enabled = noti["value"] elif subject == "start_plugin": try: g_pool.plugins.add( g_pool.plugin_by_name[noti["name"]], args=noti.get("args", {}) ) except KeyError as err: logger.error(f"Attempt to load unknown plugin: {err}") elif subject == "stop_plugin": for p in g_pool.plugins: if p.class_name == noti["name"]: p.alive = False g_pool.plugins.clean() elif subject == "eye_process.started": noti = { "subject": "set_pupil_detection_enabled", "value": g_pool.pupil_detection_enabled, } ipc_pub.notify(noti) elif subject == "set_min_calibration_confidence": g_pool.min_calibration_confidence = noti["value"] elif subject.startswith("meta.should_doc"): ipc_pub.notify( {"subject": "meta.doc", "actor": g_pool.app, "doc": world.__doc__} ) for p in g_pool.plugins: if ( p.on_notify.__doc__ and p.__class__.on_notify != Plugin.on_notify ): ipc_pub.notify( { "subject": "meta.doc", "actor": p.class_name, "doc": p.on_notify.__doc__, } ) elif subject == "world_process.adapt_window_size": set_window_size() elif subject == "world_process.should_stop": glfw.set_window_should_close(main_window, True) width, height = session_settings.get( "window_size", (1280 + icon_bar_width, 720) ) # window and gl setup glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: glfw.window_hint(glfw.VISIBLE, 0) # hide window main_window = glfw.create_window( width, height, "Pupil Capture - World", None, None ) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( window=main_window, default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) glfw.make_context_current(main_window) cygl.utils.init() g_pool.main_window = main_window def reset_restart(): logger.warning("Resetting all settings and restarting Capture.") glfw.set_window_should_close(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify({"subject": "world_process.should_start", "delay": 2.0}) def toggle_general_settings(collapsed): # this is the menu toggle logic. # Only one menu can be open. # If no menu is opened, the menubar should collapse. g_pool.menubar.collapsed = collapsed for m in g_pool.menubar.elements: m.collapsed = True general_settings.collapsed = collapsed # setup GUI g_pool.gui = ui.UI() g_pool.menubar = ui.Scrolling_Menu( "Settings", pos=(-400, 0), size=(-icon_bar_width, 0), header_pos="left" ) g_pool.iconbar = ui.Scrolling_Menu( "Icons", pos=(-icon_bar_width, 0), size=(0, 0), header_pos="hidden" ) g_pool.quickbar = ui.Stretching_Menu("Quick Bar", (0, 100), (120, -100)) g_pool.gui.append(g_pool.menubar) g_pool.gui.append(g_pool.iconbar) g_pool.gui.append(g_pool.quickbar) general_settings = ui.Growing_Menu("General", header_pos="headline") def set_window_size(): # Get current capture frame size f_width, f_height = g_pool.capture.frame_size # Get current display scale factor content_scale = gl_utils.get_content_scale(main_window) framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor f_width *= display_scale_factor f_height *= display_scale_factor # Increas the width to account for the added scaled icon bar width f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append( ui.Selector( "Audio mode", None, getter=audio.get_audio_mode, setter=audio.set_audio_mode, selection=audio.get_audio_mode_list(), ) ) general_settings.append( ui.Switch( "pupil_detection_enabled", label="Pupil detection", getter=detection_enabled_getter, setter=detection_enabled_setter, ) ) general_settings.append( ui.Switch( "eye0_process", label="Detect eye 0", setter=lambda alive: start_stop_eye(0, alive), getter=lambda: eye_procs_alive[0].value, ) ) general_settings.append( ui.Switch( "eye1_process", label="Detect eye 1", setter=lambda alive: start_stop_eye(1, alive), getter=lambda: eye_procs_alive[1].value, ) ) general_settings.append( ui.Info_Text("Capture Version: {}".format(g_pool.version)) ) general_settings.append( ui.Button("Restart with default settings", reset_restart) ) g_pool.menubar.append(general_settings) icon = ui.Icon( "collapsed", general_settings, label=chr(0xE8B8), on_val=False, off_val=True, setter=toggle_general_settings, label_font="pupil_icons", ) icon.tooltip = "General Settings" g_pool.iconbar.append(icon) user_plugin_separator = ui.Separator() user_plugin_separator.order = 0.35 g_pool.iconbar.append(user_plugin_separator) loaded_plugins = session_settings.get("loaded_plugins", default_plugins) # Resolve the active calibration choreography plugin loaded_plugins = patch_loaded_plugins_with_choreography_plugin( loaded_plugins, app=g_pool.app ) session_settings["loaded_plugins"] = loaded_plugins # plugins that are loaded based on user settings from previous session g_pool.plugins = Plugin_List(g_pool, loaded_plugins) if not g_pool.capture: # Make sure we always have a capture running. Important if there was no # capture stored in session settings. g_pool.plugins.add( g_pool.plugin_by_name[default_capture_name], default_capture_settings ) # Register callbacks main_window glfw.set_framebuffer_size_callback(main_window, on_resize) glfw.set_key_callback(main_window, on_window_key) glfw.set_char_callback(main_window, on_window_char) glfw.set_mouse_button_callback(main_window, on_window_mouse_button) glfw.set_cursor_pos_callback(main_window, on_pos) glfw.set_scroll_callback(main_window, on_scroll) glfw.set_drop_callback(main_window, on_drop) # gl_state settings gl_utils.basic_gl_setup() g_pool.image_tex = Named_Texture() toggle_general_settings(True) # now that we have a proper window we can load the last gui configuration g_pool.gui.configuration = session_settings.get("ui_config", {}) # If previously selected plugin was not loaded this time, we will have an # expanded menubar without any menu selected. We need to ensure the menubar is # collapsed in this case. if all(submenu.collapsed for submenu in g_pool.menubar.elements): g_pool.menubar.collapsed = True # create a timer to control window update frequency window_update_timer = timer(1 / 60) def window_should_update(): return next(window_update_timer) # trigger setup of window and gl sizes on_resize(main_window, *glfw.get_framebuffer_size(main_window)) if session_settings.get("eye1_process_alive", True): launch_eye_process(1, delay=0.6) if session_settings.get("eye0_process_alive", True): launch_eye_process(0, delay=0.3) ipc_pub.notify({"subject": "world_process.started"}) logger.warning("Process started.") if platform.system() == "Darwin": # On macOS, calls to glfw.swap_buffers() deliberately take longer in case of # occluded windows, based on the swap interval value. This causes an FPS drop # and leads to problems when recording. To side-step this behaviour, the swap # interval is set to zero. # # Read more about window occlusion on macOS here: # https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/WorkWhenVisible.html glfw.swap_interval(0) # Event loop while not glfw.window_should_close(main_window) and not process_was_interrupted: # fetch newest notifications new_notifications = [] while notify_sub.new_data: t, n = notify_sub.recv() new_notifications.append(n) # notify each plugin if there are new notifications: for n in new_notifications: handle_notifications(n) for p in g_pool.plugins: p.on_notify(n) # a dictionary that allows plugins to post and read events events = {} # report time between now and the last loop interation events["dt"] = get_dt() # allow each Plugin to do its work. for p in g_pool.plugins: p.recent_events(events) # check if a plugin need to be destroyed g_pool.plugins.clean() # "blacklisted" events that were already sent del events["pupil"] del events["gaze"] # delete if exists. More expensive than del, so only use it when key might not exist events.pop("annotation", None) # send new events to ipc: if "frame" in events: del events["frame"] # send explicitly with frame publisher if "depth_frame" in events: del events["depth_frame"] if "audio_packets" in events: del events["audio_packets"] del events["dt"] # no need to send this for data in events.values(): assert isinstance(data, (list, tuple)) for d in data: ipc_pub.send(d) glfw.make_context_current(main_window) # render visual feedback from loaded plugins glfw.poll_events() if window_should_update() and gl_utils.is_window_visible(main_window): gl_utils.glViewport(0, 0, *camera_render_size) for p in g_pool.plugins: p.gl_display() gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() except (AttributeError, glfw.GLFWError): # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, camera_render_size) # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for plugin in g_pool.plugins: if plugin.on_click(pos, button, action): break for key, scancode, action, mods in user_input.keys: for plugin in g_pool.plugins: if plugin.on_key(key, scancode, action, mods): break for char_ in user_input.chars: for plugin in g_pool.plugins: if plugin.on_char(char_): break glfw.swap_buffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["ui_config"] = g_pool.gui.configuration session_settings["version"] = str(g_pool.version) session_settings["eye0_process_alive"] = eye_procs_alive[0].value session_settings["eye1_process_alive"] = eye_procs_alive[1].value session_settings[ "min_calibration_confidence" ] = g_pool.min_calibration_confidence session_settings["pupil_detection_enabled"] = g_pool.pupil_detection_enabled session_settings["audio_mode"] = audio.get_audio_mode() if not hide_ui: glfw.restore_window(main_window) # need to do this for windows os session_settings["window_position"] = glfw.get_window_pos(main_window) session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): f_width, f_height = ( f_width / content_scale, f_height / content_scale, ) session_settings["window_size"] = int(f_width), int(f_height) session_settings.close() # de-init all running plugins for p in g_pool.plugins: p.alive = False g_pool.plugins.clean() g_pool.gui.terminate() glfw.destroy_window(main_window) glfw.terminate() except Exception: import traceback trace = traceback.format_exc() logger.error("Process Capture crashed with trace:\n{}".format(trace)) finally: # shut down eye processes: stop_eye_process(0) stop_eye_process(1) logger.info("Process shutting down.") ipc_pub.notify({"subject": "world_process.stopped"}) sleep(1.0)
def get_window_content_rect(window) -> _Rectangle: x, y = glfw.get_window_pos(window) w, h = glfw.get_window_size(window) return _Rectangle(x=x, y=y, width=w, height=h)
def main(): init() window = glfw.create_window(800, 600, "Chapter6", None, None) if not window: glfw.terminate() return glfw.make_context_current(window) glfw.set_input_mode(window, glfw.STICKY_KEYS, GL_TRUE) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glDepthFunc(GL_LESS) glClearColor(0.3, 0.3, 0.3, 1) vertex_array_id = glGenVertexArrays(1) glBindVertexArray(vertex_array_id) program_id = load_shaders('res/glsl/chapter6.vs', 'res/glsl/chapter6.fs') tex = texture.load('res/texture/dice.png') texture_id = glGetUniformLocation(program_id, 'TextureSampler') res_x, res_y = glfw.get_window_size(window) #projection = camera.ortho(-4,4,-3,3,0.1,10.0) projection = camera.perspective(45.0, res_x/res_y, 0.1, 100.0) view = camera.look_at( np.matrix([2,2,2], dtype=np.float32), np.matrix([0,0,0], dtype=np.float32), np.matrix([0,1,0], dtype=np.float32)) model = np.matrix(np.identity(4), dtype=np.float32) projection_id = glGetUniformLocation(program_id, 'projection') view_id = glGetUniformLocation(program_id, 'view') model_id = glGetUniformLocation(program_id, 'model') vertex = np.array([ #back -1,-1,1, 1,-1,1, 1,1,1, -1,1,1, -1,-1,1, 1,1,1, #bottom -1,-1,-1, 1,-1,-1, 1,-1,1, 1,-1,1, -1,-1,1, -1,-1,-1, #right 1,-1,1, 1,-1,-1, 1,1,-1, 1,1,-1, 1,1,1, 1,-1,1, #left -1,-1,-1, -1,-1,1, -1,1,-1, -1,1,-1, -1,-1,1, -1,1,1, #top -1,1,1, 1,1,1, 1,1,-1, 1,1,-1, -1,1,-1, -1,1,1, #front 1,-1,-1, -1,-1,-1, -1,1,-1, -1,1,-1, 1,1,-1, 1,-1,-1, ], dtype=np.float32) uv = np.array([ #back 0.25, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 0.25, #bottom 0.25, 0.25, 0.5, 0.25, 0.5, 0.0, 0.5, 0.0, 0.25, 0.0, 0.25, 0.25, #right 0.0, 0.5, 0.25, 0.5, 0.25, 0.25, 0.25, 0.25, 0.0, 0.25, 0.0, 0.5, #left 0.5, 0.5, 0.75, 0.5, 0.5, 0.25, 0.5, 0.25, 0.75, 0.5, 0.75, 0.25, #top 0.25, 0.75, 0.5, 0.75, 0.5, 0.5, 0.5, 0.5, 0.25, 0.5, 0.25, 0.75, #front 0.75,0.5, 1.0,0.5, 1.0,0.25, 1.0,0.25, 0.75,0.25, 0.75,0.5, ], dtype=np.float32) vertex_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glBufferData(GL_ARRAY_BUFFER, vertex.nbytes, vertex, GL_STATIC_DRAW) uv_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, uv_buffer) glBufferData(GL_ARRAY_BUFFER, uv.nbytes, uv, GL_STATIC_DRAW) while not glfw.window_should_close(window) and glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(program_id) glUniformMatrix4fv(projection_id, 1, GL_FALSE, projection) glUniformMatrix4fv(view_id, 1, GL_FALSE, view) glUniformMatrix4fv(model_id, 1, GL_FALSE, model) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, tex) glUniform1i(texture_id, 0) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(1) glBindBuffer(GL_ARRAY_BUFFER, uv_buffer) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, None) glDrawArrays(GL_TRIANGLES, 0, int(len(vertex)/3)) glDisableVertexAttribArray(0) glDisableVertexAttribArray(1) glfw.swap_buffers(window) glfw.poll_events() glfw.terminate()
def demo(): global quit quit = False # Callback functions def on_resize(window, w, h): h = max(h, 1) w = max(w, 1) hdpi_factor = (glfw.get_framebuffer_size(window)[0] / glfw.get_window_size(window)[0]) w, h = w * hdpi_factor, h * hdpi_factor gui.update_window(w, h) active_window = glfw.get_current_context() glfw.make_context_current(active_window) # norm_size = normalize((w,h),glfw.get_window_size(window)) # fb_size = denormalize(norm_size,glfw.get_framebuffer_size(window)) adjust_gl_view(w, h, window) glfw.make_context_current(active_window) def on_iconify(window, iconfied): pass def on_key(window, key, scancode, action, mods): gui.update_key(key, scancode, action, mods) if action == glfw.PRESS: if key == glfw.KEY_ESCAPE: on_close(window) if mods == glfw.MOD_SUPER: if key == 67: # copy value to system clipboard # ideally copy what is in our text input area test_val = "copied text input" glfw.set_clipboard_string(window, test_val) print("set clipboard to: %s" % (test_val)) if key == 86: # copy from system clipboard clipboard = glfw.get_clipboard_string(window) print("pasting from clipboard: %s" % (clipboard)) def on_char(window, char): gui.update_char(char) def on_button(window, button, action, mods): gui.update_button(button, action, mods) # pos = normalize(pos,glfw.get_window_size(window)) # pos = denormalize(pos,(frame.img.shape[1],frame.img.shape[0]) ) # Position in img pixels def on_pos(window, x, y): hdpi_factor = float( glfw.get_framebuffer_size(window)[0] / glfw.get_window_size(window)[0]) x, y = x * hdpi_factor, y * hdpi_factor gui.update_mouse(x, y) def on_scroll(window, x, y): gui.update_scroll(x, y) def on_close(window): global quit quit = True logger.info("Process closing from window") # get glfw started glfw.init() window = glfw.create_window(width, height, "pyglui demo", None, None) if not window: exit() glfw.set_window_pos(window, 0, 0) # Register callbacks for the window glfw.set_window_size_callback(window, on_resize) glfw.set_window_close_callback(window, on_close) glfw.set_window_iconify_callback(window, on_iconify) glfw.set_key_callback(window, on_key) glfw.set_char_callback(window, on_char) glfw.set_mouse_button_callback(window, on_button) glfw.set_cursor_pos_callback(window, on_pos) glfw.set_scroll_callback(window, on_scroll) # test out new paste function glfw.make_context_current(window) init() basic_gl_setup() print(glGetString(GL_VERSION)) class Temp(object): """Temp class to make objects""" def __init__(self): pass foo = Temp() foo.bar = 34 foo.sel = "mi" foo.selection = ["€", "mi", u"re"] foo.mytext = "some text" foo.T = True foo.L = False def set_text_val(val): foo.mytext = val # print 'setting to :',val def pr(): print("pyglui version: %s" % (ui.__version__)) gui = ui.UI() gui.scale = 1.0 thumbbar = ui.Scrolling_Menu("ThumbBar", pos=(-80, 0), size=(0, 0), header_pos="hidden") menubar = ui.Scrolling_Menu("MenueBar", pos=(-500, 0), size=(-90, 0), header_pos="left") gui.append(menubar) gui.append(thumbbar) T = ui.Growing_Menu("T menu", header_pos="headline") menubar.append(T) L = ui.Growing_Menu("L menu", header_pos="headline") menubar.append(L) M = ui.Growing_Menu("M menu", header_pos="headline") menubar.append(M) def toggle_menu(collapsed, menu): menubar.collapsed = collapsed for m in menubar.elements: m.collapsed = True menu.collapsed = collapsed thumbbar.append( ui.Thumb( "collapsed", T, label="T", on_val=False, off_val=True, setter=lambda x: toggle_menu(x, T), )) thumbbar.append( ui.Thumb( "collapsed", L, label="L", on_val=False, off_val=True, setter=lambda x: toggle_menu(x, L), )) thumbbar.append( ui.Thumb( "collapsed", M, label="M", on_val=False, off_val=True, setter=lambda x: toggle_menu(x, M), )) # thumbbar.elements[-1].order = -10.0 print("order" + str(thumbbar.elements[-1].order)) T.append(ui.Button("T test", pr)) T.append( ui.Info_Text( "T best finerfpiwnesdco'n wfo;ineqrfo;inwefo'qefr voijeqfr'p9qefrp'i 'iqefr'ijqfr eqrfiqerfn'ioer" )) L.append(ui.Button("L test", pr)) L.append(ui.Button("L best", pr)) M.append(ui.Button("M test", pr)) M.append(ui.Button("M best", pr)) MM = ui.Growing_Menu("MM menu", pos=(0, 0), size=(0, 400)) M.append(MM) for x in range(20): MM.append(ui.Button("M test%s" % x, pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) M.append(ui.Button("M best", pr)) # label = 'Ï' # label = 'R' # gui.append( import os import psutil pid = os.getpid() ps = psutil.Process(pid) ts = time.time() from pyglui import graph print(graph.__version__) cpu_g = graph.Line_Graph() cpu_g.pos = (50, 100) cpu_g.update_fn = ps.cpu_percent cpu_g.update_rate = 5 cpu_g.label = "CPU %0.1f" fps_g = graph.Line_Graph() fps_g.pos = (50, 100) fps_g.update_rate = 5 fps_g.label = "%0.0f FPS" fps_g.color[:] = 0.1, 0.1, 0.8, 0.9 on_resize(window, *glfw.get_window_size(window)) while not quit: gui.update() # print(T.collapsed,L.collapsed,M.collapsed) # T.collapsed = True # glfw.make_context_current(window) glfw.swap_buffers(window) glfw.poll_events() # adjust_gl_view(1280,720,window) glClearColor(0.3, 0.4, 0.1, 1) glClear(GL_COLOR_BUFFER_BIT) gui.terminate() glfw.terminate() logger.debug("Process done")
def size(self): return glfw.get_window_size(self.window)
def main(): glfw.init() window = glfw.create_window(640, 320, "Chip8", None, None) glfw.make_context_current(window) program = glCreateProgram() with open("vertex.glsl") as source: vertex = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertex, source.read()) glCompileShader(vertex) glAttachShader(program, vertex) with open("fragment.glsl") as source: fragment = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragment, source.read()) glCompileShader(fragment) glAttachShader(program, fragment) glLinkProgram(program) vbo = glGenBuffers(1) vao = glGenVertexArrays(1) glBindVertexArray(vao) glBindBuffer(GL_ARRAY_BUFFER, vbo) glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(0) glBindVertexArray(0) program_counter = 0x200 index = 0 display = [[0] * 64 for _ in range(32)] memory = [0] * 4096 variables = [0] * 16 stack = [ ] delay_timer = 0 sound_timer = 0 memory[0: 80] = [ 0xF0, 0x90, 0x90, 0x90, 0xF0, # 0 0x20, 0x60, 0x20, 0x20, 0x70, # 1 0xF0, 0x10, 0xF0, 0x80, 0xF0, # 2 0xF0, 0x10, 0xF0, 0x10, 0xF0, # 3 0x90, 0x90, 0xF0, 0x10, 0x10, # 4 0xF0, 0x80, 0xF0, 0x10, 0xF0, # 5 0xF0, 0x80, 0xF0, 0x90, 0xF0, # 6 0xF0, 0x10, 0x20, 0x40, 0x40, # 7 0xF0, 0x90, 0xF0, 0x90, 0xF0, # 8 0xF0, 0x90, 0xF0, 0x10, 0xF0, # 9 0xF0, 0x90, 0xF0, 0x90, 0x90, # A 0xE0, 0x90, 0xE0, 0x90, 0xE0, # B 0xF0, 0x80, 0x80, 0x80, 0xF0, # C 0xE0, 0x90, 0x90, 0x90, 0xE0, # D 0xF0, 0x80, 0xF0, 0x80, 0xF0, # E 0xF0, 0x80, 0xF0, 0x80, 0x80 # F ] binary = open("roms/" + input("Program? :> ") + ".ch8", "rb") for i, byte in enumerate(binary.read()): memory[0x200 + i] = byte binary.close() timer_clock = time.time() cycle_clock = time.time() while not glfw.window_should_close(window): if time.time() - timer_clock >= 1 / 60: if sound_timer > 0: sound_timer -= 1 if delay_timer > 0: delay_timer -= 1 timer_clock = time.time() if time.time() - cycle_clock >= 1 / 500: glfw.poll_events() opcode = memory[program_counter] << 8 | memory[program_counter + 1] x = (opcode & 0x0F00) >> 8 y = (opcode & 0x00F0) >> 4 n = (opcode & 0x000F) nn = (opcode & 0x00FF) nnn = (opcode & 0x0FFF) if (opcode & 0xF00F) == 0x0000: display = [[0] * 64 for _ in range(32)] if (opcode & 0xF00F) == 0x000E: program_counter = stack.pop() if (opcode & 0xF000) == 0x1000: program_counter = nnn - 2 if (opcode & 0xF000) == 0x2000: stack.append(program_counter) program_counter = nnn - 2 if (opcode & 0xF000) == 0x3000: if variables[x] == nn: program_counter += 2 if (opcode & 0xF000) == 0x4000: if variables[x] != nn: program_counter += 2 if (opcode & 0xF000) == 0x5000: if variables[x] == variables[y]: program_counter += 2 if (opcode & 0xF000) == 0x6000: variables[x] = nn if (opcode & 0xF000) == 0x7000: variables[x] = (variables[x] + nn) % 256 if (opcode & 0xF00F) == 0x8000: variables[x] = variables[y] if (opcode & 0xF00F) == 0x8001: variables[x] = variables[x] | variables[y] if (opcode & 0xF00F) == 0x8002: variables[x] = variables[x] & variables[y] if (opcode & 0xF00F) == 0x8003: variables[x] = variables[x] ^ variables[y] if (opcode & 0xF00F) == 0x8004: if variables[x] + variables[y] > 255: variables[0xF] = 1 else: variables[0xF] = 0 variables[x] = (variables[x] + variables[y]) % 256 if (opcode & 0xF00F) == 0x8005: if variables[x] > variables[y]: variables[0xF] = 1 else: variables[0xF] = 0 variables[x] = (variables[x] - variables[y]) % 256 if (opcode & 0xF00F) == 0x8006: variables[0xF] = variables[x] & 1 variables[x] = variables[x] >> 1 if (opcode & 0xF00F) == 0x8007: if variables[y] > variables[x]: variables[0xF] = 1 else: variables[0xF] = 0 variables[x] = (variables[y] - variables[x]) % 256 if (opcode & 0xF00F) == 0x800E: variables[0xF] = variables[x] >> 7 variables[x] = (variables[x] << 1) % 256 if (opcode & 0xF000) == 0x9000: if variables[x] != variables[y]: program_counter += 2 if (opcode & 0xF000) == 0xA000: index = nnn if (opcode & 0xF000) == 0xB000: program_counter = nnn + variables[0] - 2 if (opcode & 0xF000) == 0xC000: variables[x] = random.randint(0, 255) & nn if (opcode & 0xF000) == 0xD000: # todo variables[0xF] = 0 x_pos, y_pos = variables[x] % 64, variables[y] % 32 sprite = memory[index: index + n] for y_sprite, row in enumerate(sprite): for x_sprite, pixel in enumerate(bin(row)[2:].zfill(8)): pixel_x = x_pos + x_sprite pixel_y = y_pos + y_sprite if pixel_x >= 64 or pixel_y >= 32: continue if display[pixel_y][pixel_x] == 1 and int(pixel) == 1: variables[0xF] = 1 display[pixel_y][pixel_x] ^= int(pixel) if (opcode & 0xF00F) == 0xE00E: if keyboard(window)[variables[x]] == 1: program_counter += 2 if (opcode & 0xF00F) == 0xE001: if keyboard(window)[variables[x]] == 0: program_counter += 2 if opcode & 0xF0FF == 0xF007: variables[x] = delay_timer if opcode & 0xF0FF == 0xF00A: key_press = False while not key_press: for key, value in keyboard(window).items(): if value == 1: variables[x] = key key_press = True break if opcode & 0xF0FF == 0xF015: delay_timer = variables[x] if opcode & 0xF0FF == 0xF018: sound_timer = variables[x] if opcode & 0xF0FF == 0xF01E: index = variables[x] + index if opcode & 0xF0FF == 0xF029: index = variables[x] * 5 if opcode & 0xF0FF == 0xF033: memory[index + 0] = (variables[x] // 100) % 10 memory[index + 1] = (variables[x] // 10) % 10 memory[index + 2] = (variables[x] // 1) % 10 if opcode & 0xF0FF == 0xF055: memory[index: index + x + 1] = variables[:x + 1] if opcode & 0xF0FF == 0xF065: variables[:x + 1] = memory[index: index + x + 1] glClear(GL_COLOR_BUFFER_BIT) glUseProgram(program) width, height = glfw.get_window_size(window) matrix = glm.ortho(0, width, height, 0) location = glGetUniformLocation(program, "ortho_matrix") glUniformMatrix4fv(location, 1, GL_FALSE, glm.value_ptr(matrix)) verticies = [] for x in range(64): for y in range(32): if display[y][x] == 1: verticies.extend([ (x ) * 10, (y ) * 10, (x + 1) * 10, (y ) * 10, (x ) * 10, (y + 1) * 10, (x + 1) * 10, (y + 1) * 10, (x ) * 10, (y + 1) * 10, (x + 1) * 10, (y ) * 10 ]) verticies = numpy.array(verticies, dtype=numpy.float32) glBindVertexArray(vao) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, verticies.nbytes, verticies, GL_DYNAMIC_DRAW) glDrawArrays(GL_TRIANGLES, 0, len(verticies)) glBindVertexArray(0) glUseProgram(0) glfw.swap_buffers(window) program_counter += 2 cycle_clock = time.time() glfw.terminate()
def __init__(self, width=640, height=480, name="Window"): glfw.window_hint(glfw.RESIZABLE, True) glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) self.width, self.height = width, height self.win = glfw.create_window(width, height, name, None, None) if not self.win: glfw.terminate() exit() glfw.make_context_current(self.win) glfw.set_key_callback(self.win, self.on_key) glfw.set_window_size_callback(self.win, self.window_resize) # glfw.set_input_mode(self.win, glfw.CURSOR, glfw.CURSOR_NORMAL) glfw.set_cursor_pos_callback(self.win, self.on_mouse) glfw.set_scroll_callback(self.win, self.on_scroll) glfw.set_mouse_button_callback(self.win, self.on_mouse_button) print('OpenGL', glGetString(GL_VERSION).decode() + ', GLSL', glGetString(GL_SHADING_LANGUAGE_VERSION).decode() + ', Renderer', glGetString(GL_RENDERER).decode(), '\n') glClearColor(0, 0, 0, 1) glEnable(GL_CULL_FACE) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST) # glEnable(GL_ALPHA_TEST) glDepthFunc(GL_LEQUAL) # glDepthMask(GL_FALSE) self.elements = list() self.colored_elements = list() # self.colored_elements.append(Pyramid()) self.camera = Camera(self.win) self.trackball = Trackball() winsize = glfw.get_window_size(self.win) self.projection = self.trackball.projection_matrix(winsize) self.mouse_picker = MousePicker(self.camera, self.projection) self.texture_shader = Shader("res/shaders/basicShader") self.color_shader = Shader("res/shaders/grid") self.shaders = { "color": self.color_shader, "texture": self.texture_shader } self.map_pointer = None self.keys = { "e": False } self.clicks = {} self.delta_time = 0 self.last_frame = 0 self.last_x = 400 self .last_y = 300 self.first_mouse = True self.move_x = 0 self.move_y = 0 self.map = BasicMap(5) main_planet = MainPlanet(1.0) main_planet_pos = (0, 0) self.map.set_entity(main_planet_pos, main_planet) # Trying to enter the main planet at the launch # self.map.selected_tile = self.map.get_tile(main_planet_pos) # self.map_pointer = main_planet self.elements.append(self.map) self.elements.extend(( Background(1, 20), Background(2, 20), Background(3, 20))) self.pyramid = Pyramid()
def window_resize(self, _window, _width, _height): self.width, self.height = _width, _height glViewport(0, 0, _width, _height) winsize = glfw.get_window_size(self.win) self.projection = self.trackball.projection_matrix(winsize) self.mouse_picker.projection_matrix = self.projection
def main(): init() window = glfw.create_window(800, 600, "Chapter7", None, None) if not window: glfw.terminate() return glfw.make_context_current(window) glfw.set_input_mode(window, glfw.STICKY_KEYS, GL_TRUE) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glClearColor(0.3, 0.3, 0.3, 1) vertex_array_id = glGenVertexArrays(1) glBindVertexArray(vertex_array_id) program_id = load_shaders('res/glsl/chapter7.vs', 'res/glsl/chapter7.fs') res_x, res_y = glfw.get_window_size(window) #projection = camera.ortho(-4,4,-3,3,0.1,5.0) projection = camera.perspective(45.0, res_x / res_y, 0.1, 100.0) view = camera.look_at(np.matrix([2, 2, 2], dtype=np.float32), np.matrix([0, 0, 0], dtype=np.float32), np.matrix([0, 1, 0], dtype=np.float32)) model = np.matrix(np.identity(4), dtype=np.float32) projection_id = glGetUniformLocation(program_id, 'projection') view_id = glGetUniformLocation(program_id, 'view') model_id = glGetUniformLocation(program_id, 'model') vertex = np.array([ -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, ], dtype=np.float32) color = np.array([ 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, ], dtype=np.float32) index = np.array( [ #top 7, 6, 2, 2, 3, 7, #bottom 0, 1, 5, 5, 4, 0, #left 0, 4, 7, 7, 3, 0, #right 5, 1, 2, 2, 6, 5, #front 1, 0, 3, 3, 2, 1, #back 4, 5, 6, 6, 7, 4, ], dtype=np.uint32) vertex_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glBufferData(GL_ARRAY_BUFFER, vertex.nbytes, vertex, GL_STATIC_DRAW) color_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, color_buffer) glBufferData(GL_ARRAY_BUFFER, color.nbytes, color, GL_STATIC_DRAW) element_buffer = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer) glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index, GL_STATIC_DRAW) while not glfw.window_should_close(window) and glfw.get_key( window, glfw.KEY_ESCAPE) != glfw.PRESS: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(program_id) glUniformMatrix4fv(projection_id, 1, GL_FALSE, projection) glUniformMatrix4fv(view_id, 1, GL_FALSE, view) glUniformMatrix4fv(model_id, 1, GL_FALSE, model) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(1) glBindBuffer(GL_ARRAY_BUFFER, color_buffer) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, None) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer) glDrawElements(GL_TRIANGLES, index.nbytes, GL_UNSIGNED_INT, None) glDisableVertexAttribArray(0) glDisableVertexAttribArray(1) glfw.swap_buffers(window) glfw.poll_events() glfw.terminate()
def render(self): rendertime = time.time() GL.glClearColor(0, 0, 0, 1) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # active shader program GL.glUseProgram(self.window.shader) # Bind Texture GL.glBindTexture(GL.GL_TEXTURE_2D, self.window.texture); # Create transformations # transform = pyrr.Matrix44().identity() # Coordinates ''' Local space (Object space) World space View space (Eye space) Clip space Screen space ''' # Model Matrix #rad = numpy.radians(glfw.get_time() * -30.0) rad = numpy.radians(-50.0) model = pyrr.matrix44.create_from_axis_rotation([1.0, 0.0, 0.0], rad) loc = GL.glGetUniformLocation(self.window.shader, 'model') GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE, model) # View Matrix view = pyrr.matrix44.create_from_translation([0.0, 0.0, -3.0]) loc = GL.glGetUniformLocation(self.window.shader, 'view') GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE, view) # Projection Matrix fovy = 45.0 (width, height) = glfw.get_window_size(self.w) aspect_ratio = (width * 1.0) / height near = 0.1 far = 100.0 projection = pyrr.matrix44.create_perspective_projection_matrix(fovy, aspect_ratio, near, far) loc = GL.glGetUniformLocation(self.window.shader, 'projection') GL.glUniformMatrix4fv(loc, 1, GL.GL_FALSE, projection) try: GL.glBindVertexArray(self.VAO) # Draw a triangle # GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3) # draw triangle, starting index of the vertex array, # of vertices (6 = indexData.size), # EBO indexes remain the same (accounts for stride of extra data GL.glDrawElements(GL.GL_TRIANGLES, self.index_size, GL.GL_UNSIGNED_INT, None) finally: # Unbind when we finish GL.glBindVertexArray(0) GL.glUseProgram(0) self.rendertime = 1000 * (time.time() - rendertime)
def __init__( self, module, width, height, caption, scale, palette, fps, border_width, border_color, ): if glfw.get_version() < tuple(map(int, GLFW_VERSION.split("."))): raise RuntimeError( "glfw version is lower than {}".format(GLFW_VERSION)) if width > APP_SCREEN_MAX_SIZE or height > APP_SCREEN_MAX_SIZE: raise ValueError("screen size is larger than {}x{}".format( APP_SCREEN_MAX_SIZE, APP_SCREEN_MAX_SIZE)) self._module = module self._palette = palette[:] self._pil_palette = self._get_pil_palette(palette) self._fps = fps self._border_width = border_width self._border_color = border_color self._next_update_time = 0 self._one_frame_time = 1 / fps self._key_state = {} self._update = None self._draw = None self._capture_start = 0 self._capture_index = 0 self._capture_images = [None] * APP_GIF_CAPTURE_COUNT self._perf_monitor_is_enabled = False self._perf_fps_count = 0 self._perf_fps_start_time = 0 self._perf_fps = 0 self._perf_update_count = 0 self._perf_update_total_time = 0 self._perf_update_time = 0 self._perf_draw_count = 0 self._perf_draw_total_time = 0 self._perf_draw_time = 0 module.width = width module.height = height module.mouse_x = 0 module.mouse_y = 0 module.frame_count = 0 # initialize window if not glfw.init(): exit() monitor = glfw.get_primary_monitor() display_width, display_height = glfw.get_video_mode(monitor)[0] if scale == 0: scale = max( min( (display_width // width) - APP_SCREEN_SCALE_CUTDOWN, (display_height // height) - APP_SCREEN_SCALE_CUTDOWN, ), APP_SCREEN_SCALE_MINIMUM, ) window_width = width * scale + border_width window_height = height * scale + border_width self._window = glfw.create_window(window_width, window_height, caption, None, None) if not self._window: glfw.terminate() exit() glfw.set_window_pos( self._window, (display_width - window_width) // 2, (display_height - window_height) // 2, ) glfw.make_context_current(self._window) glfw.set_window_size_limits(self._window, width, height, glfw.DONT_CARE, glfw.DONT_CARE) self._hidpi_scale = (glfw.get_framebuffer_size(self._window)[0] / glfw.get_window_size(self._window)[0]) self._update_viewport() glfw.set_key_callback(self._window, self._key_callback) glfw.set_cursor_pos_callback(self._window, self._cursor_pos_callback) glfw.set_mouse_button_callback(self._window, self._mouse_button_callback) glfw.set_window_icon(self._window, 1, [self._get_icon_image()]) # initialize renderer self._renderer = Renderer(width, height) # initialize audio player self._audio_player = AudioPlayer() # export module functions module.btn = self.btn module.btnp = self.btnp module.btnr = self.btnr module.run = self.run module.run_with_profiler = self.run_with_profiler module.quit = self.quit module.save = self.save module.load = self.load module.image = self._renderer.image module.tilemap = self._renderer.tilemap module.clip = self._renderer.draw_command.clip module.pal = self._renderer.draw_command.pal module.cls = self._renderer.draw_command.cls module.pix = self._renderer.draw_command.pix module.line = self._renderer.draw_command.line module.rect = self._renderer.draw_command.rect module.rectb = self._renderer.draw_command.rectb module.circ = self._renderer.draw_command.circ module.circb = self._renderer.draw_command.circb module.blt = self._renderer.draw_command.blt module.bltm = self._renderer.draw_command.bltm module.text = self._renderer.draw_command.text module.sound = self._audio_player.sound module.play = self._audio_player.play # module.playm = self._audio_player.playm module.stop = self._audio_player.stop
def _before_make_current(self, width, height): previous_context = glfw.get_current_context() glfw.make_context_current(self._context) if (width, height) != glfw.get_window_size(self._context): glfw.set_window_size(self._context, width, height) return previous_context
if simulation_running: agents.step() if current_time - previous_time >= 1.0: title = "Crowd Simulation ( " + str(frame_count) + " FPS | Number Of Agents: " + str( len(agents.agent_list)) + " )" + " intensity: " + str(global_intensity) glfw.set_window_title(window, title) frame_count = 0 previous_time = current_time glfw.poll_events() glClearColor(0.0, 0.0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT) w, h = glfw.get_window_size(window) if w != w_prev or h != h_prev: w_prev = w h_prev = h tile_size[0] = (w - 2 * (offset + 1)) / len(maze[0]) tile_size[1] = (h - 2 * (offset + 1)) / len(maze) agents.set_client_tile_size(w, h, tile_size) mazeTexture.reconstruct(w, h, tile_size) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, w, 0, h, -10, 10) glMatrixMode(GL_MODELVIEW)
def on_pos(window, x, y): hdpi_factor = float( glfw.get_framebuffer_size(window)[0] / glfw.get_window_size(window)[0]) x, y = x * hdpi_factor, y * hdpi_factor gui.update_mouse(x, y)
glfw.set_mouse_button_callback(window, on_mouse_button) shader, VAO, texture, texture_locn = prepare_shader() imgui.set_window_focus() for j in range(19): add_fg_element(load_image('images/heli%d.png' % j), label='heli%d' % j) original_bg_im_data = np.copy(bg_im_data) active_fg_element = 0 while not glfw.window_should_close(window): glfw.poll_events() impl.process_inputs() imgui.new_frame() curr_width, curr_height = glfw.get_window_size(window) if curr_width != width or curr_height != height: width, height = curr_width, curr_height timestep_changed = False if not hide_panel: # Timeline timeline_height = 80 imgui.set_next_window_position(0, height - timeline_height) imgui.set_next_window_size(width, timeline_height) imgui.set_next_window_bg_alpha(0.8) imgui.begin('timeline', False, imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_RESIZE) n_frames = max([len(t) for t in traces]) timestep_changed, timestep = imgui.slider_int('timestep', timestep,
vms = glfw.get_video_modes(pm) print("Available video modes:\n%s\n" % "\n".join(map(str, vms))) vm = glfw.get_video_mode(pm) print("Desktop video mode:\n%s\n" % str(vm)) print("GLFW Version: %d.%d.%d" % glfw.get_version()) w = glfw.create_window(800, 600, 'test', None, None) #print("OpenGL version: %d.%d.%d\n" % glfw.get_gl_version()) #glfw.ext.set_icons([(icon_data, icon_width, icon_height)]) glfw.set_window_title(w, "pyglfw test") #glfw.disable(w, glfw.AUTO_POLL_EVENTS) #glfw.enable(w, glfw.KEY_REPEAT) center_x = int(vm[0][0] / 2 - glfw.get_window_size(w)[0] / 2) center_y = int(vm[0][1] / 2 - glfw.get_window_size(w)[1] / 2) print("new window position: {!s}, {!s}".format(center_x, center_y)) glfw.set_window_pos(w, center_x, center_y) glfw.set_window_size_callback(w, on_resize) glfw.set_window_close_callback(w, on_close) glfw.set_window_refresh_callback(w, on_refresh) glfw.set_key_callback(w, on_key) glfw.set_char_callback(w, on_char) glfw.set_mouse_button_callback(w, on_button) glfw.set_cursor_pos_callback(w, on_pos) glfw.set_scroll_callback(w, on_scroll) while not glfw.window_should_close(w): glfw.poll_events()
def run(self): # Loop until the user closes the window while not glfw.window_should_close(self.window): # Poll for and process events glfw.poll_events() # build gui. self.impl.process_inputs() w, h = glfw.get_window_size(self.window) glViewport(0, 0, w, h) imgui.new_frame() timeline_height = 35 imgui.push_style_var(imgui.STYLE_WINDOW_ROUNDING, 0) imgui.push_style_var(imgui.STYLE_FRAME_ROUNDING, 0) imgui.set_next_window_position(0, h - timeline_height - 10) imgui.set_next_window_size(w, timeline_height) imgui.begin( "Timeline", False, imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_NO_SCROLLBAR) imgui.columns(1) imgui.same_line(0, 0) imgui.push_item_width(-50) changed, value = imgui.slider_int("", self.sliderValue, 0, self.num_scans - 1) if changed: self.sliderValue = value if self.sliderValue != self.currentTimestep: self.currentTimestep = self.sliderValue imgui.push_style_var(imgui.STYLE_FRAME_ROUNDING, 3) play_delay = 1 refresh_rate = 0.05 current_time = time.time() imgui.same_line(spacing=5) changed = imgui.button("<", 20) if self.currentTimestep > 0: # just a click if changed: self.currentTimestep = self.sliderValue = self.currentTimestep - 1 self.lastUpdate = current_time # button pressed. if imgui.is_item_active() and not self.button_backward_hold: self.hold_start = current_time self.button_backward_hold = True if not imgui.is_item_active() and self.button_backward_hold: self.button_backward_hold = False # start playback when button pressed long enough if self.button_backward_hold and ( (current_time - self.hold_start) > play_delay): if (current_time - self.lastUpdate) > refresh_rate: self.currentTimestep = self.sliderValue = self.currentTimestep - 1 self.lastUpdate = current_time imgui.same_line(spacing=2) changed = imgui.button(">", 20) if self.currentTimestep < self.num_scans - 1: # just a click if changed: self.currentTimestep = self.sliderValue = self.currentTimestep + 1 self.lastUpdate = current_time # button pressed. if imgui.is_item_active() and not self.button_forward_hold: self.hold_start = current_time self.button_forward_hold = True if not imgui.is_item_active() and self.button_forward_hold: self.button_forward_hold = False # start playback when button pressed long enough if self.button_forward_hold and ( (current_time - self.hold_start) > play_delay): if (current_time - self.lastUpdate) > refresh_rate: self.currentTimestep = self.sliderValue = self.currentTimestep + 1 self.lastUpdate = current_time imgui.pop_style_var(3) imgui.end() imgui.set_next_window_position(20, 20, imgui.FIRST_USE_EVER) imgui.set_next_window_size(200, 150, imgui.FIRST_USE_EVER) imgui.begin("Show Data") if len(self.subdirs) > 1: for i, subdir in enumerate(self.subdirs): changed, value = imgui.checkbox(subdir, self.current_subdir == i) if i < len(self.subdirs) - 1: imgui.same_line() if changed and value: self.current_subdir = i subdir = self.subdirs[self.current_subdir] data_available = "input" in self.availableData[subdir] if data_available: imgui.push_style_var(imgui.STYLE_ALPHA, 1.0) else: imgui.push_style_var(imgui.STYLE_ALPHA, 0.3) changed, value = imgui.checkbox("input", self.showInput) if changed and value and data_available: self.showInput = True self.showLabels = False imgui.pop_style_var() data_available = "labels" in self.availableData[subdir] if data_available: imgui.push_style_var(imgui.STYLE_ALPHA, 1.0) else: imgui.push_style_var(imgui.STYLE_ALPHA, 0.3) changed, value = imgui.checkbox("labels", self.showLabels) if changed and value and data_available: self.showInput = False self.showLabels = True imgui.pop_style_var() data_available = "invalid" in self.availableData[subdir] if data_available: imgui.push_style_var(imgui.STYLE_ALPHA, 1.0) else: imgui.push_style_var(imgui.STYLE_ALPHA, 0.3) changed, value = imgui.checkbox("invalid", self.showInvalid) if changed and data_available: self.showInvalid = value imgui.pop_style_var() data_available = "occluded" in self.availableData[subdir] if data_available: imgui.push_style_var(imgui.STYLE_ALPHA, 1.0) else: imgui.push_style_var(imgui.STYLE_ALPHA, 0.3) changed, value = imgui.checkbox("occluded", self.showOccluded) if changed and data_available: self.showOccluded = value imgui.pop_style_var() imgui.end() # imgui.show_demo_window() showData = [] if self.showInput: showData.append("input") if self.showOccluded: showData.append("occluded") if self.showInvalid: showData.append("invalid") mvp = self.projection_ @ self.cam.matrix @ self.conversion_ glClearColor(1.0, 1.0, 1.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBindVertexArray(self.vao) self.program.bind() self.program["mvp"] = mvp.transpose() self.program["view_mat"] = ( self.cam.matrix @ self.conversion_).transpose() self.program["lightPos"] = glow.vec3(10, 10, 10) self.program["voxel_scale"] = 0.8 self.program["voxel_alpha"] = 1.0 self.program["use_label_colors"] = True self.label_colors.bind(0) if self.showLabels: self.setCurrentBufferData("labels", self.currentTimestep) glDrawArraysInstanced(GL_TRIANGLES, 0, 36, self.num_instances) self.program["use_label_colors"] = False self.program["voxel_color"] = glow.vec3(0.3, 0.3, 0.3) self.program["voxel_alpha"] = 0.5 for data_name in showData: self.program["voxel_scale"] = 0.5 if data_name == "input": self.program["voxel_scale"] = 0.8 self.setCurrentBufferData(data_name, self.currentTimestep) glDrawArraysInstanced(GL_TRIANGLES, 0, 36, self.num_instances) self.program.release() self.label_colors.release(0) glBindVertexArray(self.vao_no_points) self.prgDrawPose.bind() self.prgDrawPose["mvp"] = mvp.transpose() self.prgDrawPose["pose"] = np.identity(4, dtype=np.float32) self.prgDrawPose["size"] = 1.0 glDrawArrays(GL_POINTS, 0, 1) self.prgDrawPose.release() glBindVertexArray(0) # draw gui ontop. imgui.render() self.impl.render(imgui.get_draw_data()) # Swap front and back buffers glfw.swap_buffers(self.window)
def get_normalized_device_coords(self, mouse_x, mouse_y): width, height = glfw.get_window_size(self.camera.window) x = (2 * mouse_x) / width - 1 y = -((2 * mouse_y) / height - 1) return vec(x, y)
vms = glfw.get_video_modes( pm ) print("Available video modes:\n%s\n" % "\n".join(map(str, vms))) vm = glfw.get_video_mode( pm ) print( "Desktop video mode:\n%s\n" % str(vm) ) print( "GLFW Version: %d.%d.%d" % glfw.get_version() ) w = glfw.create_window(800, 600, 'test', None, None) #print("OpenGL version: %d.%d.%d\n" % glfw.get_gl_version()) #glfw.ext.set_icons([(icon_data, icon_width, icon_height)]) glfw.set_window_title(w, "pyglfw test") #glfw.disable(w, glfw.AUTO_POLL_EVENTS) #glfw.enable(w, glfw.KEY_REPEAT) center_x = int(vm[0][0] / 2 - glfw.get_window_size(w)[0] / 2) center_y = int(vm[0][1] / 2 - glfw.get_window_size(w)[1] / 2) print( "new window position: {!s}, {!s}".format(center_x, center_y) ) glfw.set_window_pos(w, center_x, center_y) glfw.set_window_size_callback(w, on_resize) glfw.set_window_close_callback(w, on_close) glfw.set_window_refresh_callback(w, on_refresh) glfw.set_key_callback(w, on_key) glfw.set_char_callback(w, on_char) glfw.set_mouse_button_callback(w, on_button) glfw.set_cursor_pos_callback(w, on_pos) glfw.set_scroll_callback(w, on_scroll) while not glfw.window_should_close(w): glfw.poll_events()
def width(self): return glfw.get_window_size(self.window)[0]
def __init__(self, module, width, height, caption, scale, palette, fps, border_width, border_color): self._module = module self._palette = palette[:] self._pil_palette = self._get_pil_palette(palette) self._fps = fps self._border_width = border_width self._border_color = border_color self._next_update_time = 0 self._one_frame_time = 1 / fps self._key_state = {} self._update = None self._draw = None self._capture_start = 0 self._capture_index = 0 self._capture_images = [None] * APP_SCREEN_CAPTURE_COUNT self._perf_monitor_is_enabled = False self._perf_fps_count = 0 self._perf_fps_start_time = 0 self._perf_fps = 0 self._perf_update_count = 0 self._perf_update_total_time = 0 self._perf_update_time = 0 self._perf_draw_count = 0 self._perf_draw_total_time = 0 self._perf_draw_time = 0 module.width = width module.height = height module.mouse_x = 0 module.mouse_y = 0 module.frame_count = 0 # initialize window if not glfw.init(): exit() window_width = width * scale + border_width window_height = height * scale + border_width self._window = glfw.create_window(window_width, window_height, caption, None, None) if not self._window: glfw.terminate() exit() glfw.make_context_current(self._window) glfw.set_window_size_limits(self._window, width, height, glfw.DONT_CARE, glfw.DONT_CARE) self._hidpi_scale = (glfw.get_framebuffer_size(self._window)[0] / glfw.get_window_size(self._window)[0]) self._update_viewport() glfw.set_key_callback(self._window, self._key_callback) glfw.set_cursor_pos_callback(self._window, self._cursor_pos_callback) glfw.set_mouse_button_callback(self._window, self._mouse_button_callback) glfw.set_window_icon(self._window, 1, [self._get_icon_image()]) # initialize renderer self._renderer = Renderer(width, height) # initialize audio player self._audio_player = AudioPlayer() # export module functions module.btn = self.btn module.btnp = self.btnp module.btnr = self.btnr module.run = self.run module.quit = self.quit module.image = self._renderer.image module.clip = self._renderer.draw_command.clip module.pal = self._renderer.draw_command.pal module.cls = self._renderer.draw_command.cls module.pix = self._renderer.draw_command.pix module.line = self._renderer.draw_command.line module.rect = self._renderer.draw_command.rect module.rectb = self._renderer.draw_command.rectb module.circ = self._renderer.draw_command.circ module.circb = self._renderer.draw_command.circb module.blt = self._renderer.draw_command.blt module.text = self._renderer.draw_command.text module.sound = self._audio_player.sound module.play = self._audio_player.play module.stop = self._audio_player.stop
def controller(self, window): if self.__last_time is None: self.__last_time = glfw.get_time() current_time = glfw.get_time() delta_time = current_time - self.__last_time width, height = glfw.get_window_size(window) self.__aspect = width / float(height) xpos, ypos = glfw.get_cursor_pos(window) if self.__last_xpos is None or self.__last_ypos is None: self.__last_xpos, self.__last_ypos = xpos, ypos self.__horizontal_angle += self.__mouse_speed * float( self.__last_xpos - xpos) self.__vertical_angle += self.__mouse_speed * float(self.__last_ypos - ypos) # カメラの向いている方向:球面座標から直交座標への変換 self.direction = np.matrix([ np.cos(self.__vertical_angle) * np.sin(self.__horizontal_angle), np.sin(self.__vertical_angle), np.cos(self.__vertical_angle) * np.cos(self.__horizontal_angle) ], dtype=np.float32) # カメラの右方向 right = np.matrix([ np.sin(self.__horizontal_angle - np.pi / 2.0), 0, np.cos(self.__horizontal_angle - np.pi / 2.0) ], dtype=np.float32) # カメラの上方向:右方向と正面方向の外積 self.__up = np.cross(right, self.direction) if glfw.get_key(window, glfw.KEY_DOWN) is glfw.PRESS: self.position -= self.__up * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_UP) is glfw.PRESS: self.position += self.__up * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_S) is glfw.PRESS: self.position -= self.direction * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_W) is glfw.PRESS: self.position += self.direction * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_A) is glfw.PRESS: self.position -= right * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_D) is glfw.PRESS: self.position += right * delta_time * self.__speed if glfw.get_key(window, glfw.KEY_I) is glfw.PRESS and self.__fov > 1.0: self.__fov -= 1.0 if glfw.get_key(window, glfw.KEY_O) is glfw.PRESS and self.__fov < 180.0: self.__fov += 1.0 self.__target = self.position + self.direction self.projection = perspective(self.__fov, self.__aspect, self.__near, self.__far) self.view = look_at(self.position, self.__target, self.__up) self.__last_xpos, self.__last_ypos = xpos, ypos self.__last_time = current_time
def main(): init() window = glfw.create_window(800, 600, "Chapter8", None, None) if not window: glfw.terminate() return glfw.make_context_current(window) glfw.set_input_mode(window, glfw.STICKY_KEYS, GL_TRUE) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glClearColor(0.3, 0.3, 0.3, 1) vertex_array_id = glGenVertexArrays(1) glBindVertexArray(vertex_array_id) program_id = load_shaders('res/glsl/chapter8.vs', 'res/glsl/chapter8.fs') tex = texture.load('res/texture/eye.bmp') #tex = texture.load('res/texture/earth.bmp') texture_id = glGetUniformLocation(program_id, 'TextureSampler') res_x, res_y = glfw.get_window_size(window) #projection = camera.ortho(-4,4,-3,3,0.1,5.0) projection = camera.perspective(45.0, res_x / res_y, 0.1, 100.0) view = camera.look_at(np.matrix([0, 0, 2], dtype=np.float32), np.matrix([0, 0, 0], dtype=np.float32), np.matrix([0, 1, 0], dtype=np.float32)) model = np.matrix(np.identity(4), dtype=np.float32) projection_id = glGetUniformLocation(program_id, 'projection') view_id = glGetUniformLocation(program_id, 'view') model_id = glGetUniformLocation(program_id, 'model') scene = load('res/model/sphere.obj') mesh = scene.meshes[0] vertex = mesh.vertices uv = mesh.texturecoords normal = mesh.normals index = mesh.faces vertex_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glBufferData(GL_ARRAY_BUFFER, vertex.nbytes, vertex, GL_STATIC_DRAW) uv_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, uv_buffer) glBufferData(GL_ARRAY_BUFFER, uv.nbytes, uv, GL_STATIC_DRAW) normal_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, normal_buffer) glBufferData(GL_ARRAY_BUFFER, normal.nbytes, normal, GL_STATIC_DRAW) element_buffer = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer) glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index, GL_STATIC_DRAW) while not glfw.window_should_close(window) and glfw.get_key( window, glfw.KEY_ESCAPE) != glfw.PRESS: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(program_id) glUniformMatrix4fv(projection_id, 1, GL_FALSE, projection) glUniformMatrix4fv(view_id, 1, GL_FALSE, view) glUniformMatrix4fv(model_id, 1, GL_FALSE, model) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, tex) glUniform1i(texture_id, 0) glEnableVertexAttribArray(0) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(1) glBindBuffer(GL_ARRAY_BUFFER, uv_buffer) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(2) glBindBuffer(GL_ARRAY_BUFFER, normal_buffer) glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, None) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer) glDrawElements(GL_TRIANGLES, index.nbytes, GL_UNSIGNED_INT, None) glDisableVertexAttribArray(0) glDisableVertexAttribArray(1) glDisableVertexAttribArray(2) glfw.swap_buffers(window) glfw.poll_events() glfw.terminate()
def __init__( self, module, width, height, caption, scale, palette, fps, border_width, border_color, ): if glfw.get_version() < tuple(map(int, GLFW_VERSION.split("."))): raise RuntimeError( "glfw version is lower than {}".format(GLFW_VERSION)) if width > APP_SCREEN_MAX_SIZE or height > APP_SCREEN_MAX_SIZE: raise ValueError("screen size is larger than {}x{}".format( APP_SCREEN_MAX_SIZE, APP_SCREEN_MAX_SIZE)) global pyxel pyxel = module self._palette = palette[:] self._fps = fps self._border_width = border_width self._border_color = border_color self._next_update_time = 0 self._one_frame_time = 1 / fps self._key_state = {} self._is_mouse_visible = False self._update = None self._draw = None self._capture_start = 0 self._capture_count = 0 self._capture_images = [None] * APP_GIF_CAPTURE_COUNT self._perf_monitor_is_enabled = False self._perf_fps_count = 0 self._perf_fps_start_time = 0 self._perf_fps = 0 self._perf_update_count = 0 self._perf_update_total_time = 0 self._perf_update_time = 0 self._perf_draw_count = 0 self._perf_draw_total_time = 0 self._perf_draw_time = 0 # exports variables pyxel._app = self pyxel.width = width pyxel.height = height pyxel.mouse_x = 0 pyxel.mouse_y = 0 pyxel.frame_count = 0 # initialize window if not glfw.init(): exit() monitor = glfw.get_primary_monitor() display_width, display_height = glfw.get_video_mode(monitor)[0] if scale == 0: scale = max( min( (display_width // width) - APP_SCREEN_SCALE_CUTDOWN, (display_height // height) - APP_SCREEN_SCALE_CUTDOWN, ), APP_SCREEN_SCALE_MINIMUM, ) window_width = width * scale + border_width window_height = height * scale + border_width self._window = glfw.create_window(window_width, window_height, caption, None, None) if not self._window: glfw.terminate() exit() glfw.set_window_pos( self._window, (display_width - window_width) // 2, (display_height - window_height) // 2, ) glfw.make_context_current(self._window) glfw.set_window_size_limits(self._window, width, height, glfw.DONT_CARE, glfw.DONT_CARE) self._hidpi_scale = (glfw.get_framebuffer_size(self._window)[0] / glfw.get_window_size(self._window)[0]) self._update_viewport() glfw.set_key_callback(self._window, self._key_callback) glfw.set_mouse_button_callback(self._window, self._mouse_button_callback) glfw.set_window_icon(self._window, 1, [utilities.get_icon_image()]) glfw.set_input_mode(self._window, glfw.CURSOR, glfw.CURSOR_HIDDEN) # initialize renderer self._renderer = Renderer(width, height) # initialize audio player self._audio_player = AudioPlayer() # export module functions pyxel.btn = self.btn pyxel.btnp = self.btnp pyxel.btnr = self.btnr pyxel.mouse = self.mouse pyxel.run = self.run pyxel.run_with_profiler = self.run_with_profiler pyxel.quit = self.quit pyxel.save = self.save pyxel.load = self.load pyxel.image = self._renderer.image pyxel.tilemap = self._renderer.tilemap pyxel.clip = self._renderer.draw_command.clip pyxel.pal = self._renderer.draw_command.pal pyxel.cls = self._renderer.draw_command.cls pyxel.pix = self._renderer.draw_command.pix pyxel.line = self._renderer.draw_command.line pyxel.rect = self._renderer.draw_command.rect pyxel.rectb = self._renderer.draw_command.rectb pyxel.circ = self._renderer.draw_command.circ pyxel.circb = self._renderer.draw_command.circb pyxel.blt = self._renderer.draw_command.blt pyxel.bltm = self._renderer.draw_command.bltm pyxel.text = self._renderer.draw_command.text pyxel.sound = self._audio_player.sound pyxel.music = self._audio_player.music pyxel.play = self._audio_player.play pyxel.playm = self._audio_player.playm pyxel.stop = self._audio_player.stop # initialize mouse cursor pyxel.image(3, system=True).set(MOUSE_CURSOR_IMAGE_X, MOUSE_CURSOR_IMAGE_Y, MOUSE_CURSOR_DATA)
def eye( timebase, is_alive_flag, ipc_pub_url, ipc_sub_url, ipc_push_url, user_dir, version, eye_id, overwrite_cap_settings=None, hide_ui=False, debug=False, pub_socket_hwm=None, parent_application="capture", ): """reads eye video and detects the pupil. Creates a window, gl context. Grabs images from a capture. Streams Pupil coordinates. Reacts to notifications: ``eye_process.should_stop``: Stops the eye process ``recording.started``: Starts recording eye video ``recording.stopped``: Stops recording eye video ``frame_publishing.started``: Starts frame publishing ``frame_publishing.stopped``: Stops frame publishing ``start_eye_plugin``: Start plugins in eye process Emits notifications: ``eye_process.started``: Eye process started ``eye_process.stopped``: Eye process stopped Emits data: ``pupil.<eye id>``: Pupil data for eye with id ``<eye id>`` ``frame.eye.<eye id>``: Eye frames with id ``<eye id>`` """ # We deferr the imports becasue of multiprocessing. # Otherwise the world process each process also loads the other imports. import zmq import zmq_tools zmq_ctx = zmq.Context() ipc_socket = zmq_tools.Msg_Dispatcher(zmq_ctx, ipc_push_url) pupil_socket = zmq_tools.Msg_Streamer(zmq_ctx, ipc_pub_url, pub_socket_hwm) notify_sub = zmq_tools.Msg_Receiver(zmq_ctx, ipc_sub_url, topics=("notify",)) # logging setup import logging logging.getLogger("OpenGL").setLevel(logging.ERROR) logger = logging.getLogger() logger.handlers = [] logger.setLevel(logging.NOTSET) logger.addHandler(zmq_tools.ZMQ_handler(zmq_ctx, ipc_push_url)) # create logger for the context of this function logger = logging.getLogger(__name__) if is_alive_flag.value: # indicates eye process that this is a duplicated startup logger.warning("Aborting redundant eye process startup") return with Is_Alive_Manager(is_alive_flag, ipc_socket, eye_id, logger): # general imports import traceback import numpy as np import cv2 from OpenGL.GL import GL_COLOR_BUFFER_BIT # display import glfw from gl_utils import GLFWErrorReporting GLFWErrorReporting.set_default() from pyglui import ui, graph, cygl from pyglui.cygl.utils import Named_Texture import gl_utils from gl_utils import basic_gl_setup, adjust_gl_view, clear_gl_screen from gl_utils import make_coord_system_pixel_based from gl_utils import make_coord_system_norm_based from gl_utils import is_window_visible, glViewport # monitoring import psutil # Plug-ins from plugin import Plugin_List # helpers/utils from uvc import get_time_monotonic from file_methods import Persistent_Dict from version_utils import parse_version from methods import normalize, denormalize, timer from av_writer import JPEG_Writer, MPEG_Writer, NonMonotonicTimestampError from ndsi import H264Writer from video_capture import source_classes, manager_classes from roi import Roi from background_helper import IPC_Logging_Task_Proxy from pupil_detector_plugins import available_detector_plugins, EVENT_KEY IPC_Logging_Task_Proxy.push_url = ipc_push_url def interrupt_handler(sig, frame): import traceback trace = traceback.format_stack(f=frame) logger.debug(f"Caught signal {sig} in:\n" + "".join(trace)) # NOTE: Interrupt is handled in world/service/player which are responsible for # shutting down the eye process properly signal.signal(signal.SIGINT, interrupt_handler) # UI Platform tweaks if platform.system() == "Linux": scroll_factor = 10.0 window_position_default = (600, 300 * eye_id + 30) elif platform.system() == "Windows": scroll_factor = 10.0 window_position_default = (600, 90 + 300 * eye_id) else: scroll_factor = 1.0 window_position_default = (600, 300 * eye_id) icon_bar_width = 50 window_size = None content_scale = 1.0 # g_pool holds variables for this process g_pool = SimpleNamespace() # make some constants avaiable g_pool.debug = debug g_pool.user_dir = user_dir g_pool.version = version g_pool.app = parent_application g_pool.eye_id = eye_id g_pool.process = f"eye{eye_id}" g_pool.timebase = timebase g_pool.camera_render_size = None g_pool.zmq_ctx = zmq_ctx g_pool.ipc_pub = ipc_socket g_pool.ipc_pub_url = ipc_pub_url g_pool.ipc_sub_url = ipc_sub_url g_pool.ipc_push_url = ipc_push_url def get_timestamp(): return get_time_monotonic() - g_pool.timebase.value g_pool.get_timestamp = get_timestamp g_pool.get_now = get_time_monotonic def load_runtime_pupil_detection_plugins(): from plugin import import_runtime_plugins from pupil_detector_plugins.detector_base_plugin import PupilDetectorPlugin plugins_path = os.path.join(g_pool.user_dir, "plugins") for plugin in import_runtime_plugins(plugins_path): if not isinstance(plugin, type): continue if not issubclass(plugin, PupilDetectorPlugin): continue if plugin is PupilDetectorPlugin: continue yield plugin available_detectors = available_detector_plugins() runtime_detectors = list(load_runtime_pupil_detection_plugins()) plugins = ( manager_classes + source_classes + available_detectors + runtime_detectors + [Roi] ) g_pool.plugin_by_name = {p.__name__: p for p in plugins} preferred_names = [ f"Pupil Cam3 ID{eye_id}", f"Pupil Cam2 ID{eye_id}", f"Pupil Cam1 ID{eye_id}", ] if eye_id == 0: preferred_names += ["HD-6000"] default_capture_name = "UVC_Source" default_capture_settings = { "preferred_names": preferred_names, "frame_size": (192, 192), "frame_rate": 120, } default_plugins = [ # TODO: extend with plugins (default_capture_name, default_capture_settings), ("UVC_Manager", {}), *[(p.__name__, {}) for p in available_detectors], ("NDSI_Manager", {}), ("HMD_Streaming_Manager", {}), ("File_Manager", {}), ("Roi", {}), ] def consume_events_and_render_buffer(): glfw.make_context_current(main_window) clear_gl_screen() if all(c > 0 for c in g_pool.camera_render_size): glViewport(0, 0, *g_pool.camera_render_size) for p in g_pool.plugins: p.gl_display() glViewport(0, 0, *window_size) # render graphs fps_graph.draw() cpu_graph.draw() # render GUI try: clipboard = glfw.get_clipboard_string(main_window).decode() except (AttributeError, glfw.GLFWError): # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, g_pool.camera_render_size) if g_pool.flip: pos = 1 - pos[0], 1 - pos[1] # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for plugin in g_pool.plugins: if plugin.on_click(pos, button, action): break for key, scancode, action, mods in user_input.keys: for plugin in g_pool.plugins: if plugin.on_key(key, scancode, action, mods): break for char_ in user_input.chars: for plugin in g_pool.plugins: if plugin.on_char(char_): break # update screen glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): nonlocal window_size nonlocal content_scale is_minimized = bool(glfw.get_window_attrib(window, glfw.ICONIFIED)) if is_minimized: return # Always clear buffers on resize to make sure that there are no overlapping # artifacts from previous frames. gl_utils.glClear(GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) active_window = glfw.get_current_context() glfw.make_context_current(window) content_scale = gl_utils.get_content_scale(window) framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h g_pool.camera_render_size = w - int(icon_bar_width * g_pool.gui.scale), h g_pool.gui.update_window(w, h) g_pool.gui.collect_menus() for g in g_pool.graphs: g.scale = content_scale g.adjust_window_size(w, h) adjust_gl_view(w, h) glfw.make_context_current(active_window) # Minimum window size required, otherwise parts of the UI can cause openGL # issues with permanent effects. Depends on the content scale, which can # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) glfw.set_window_size_limits( window, min_size, min_size, glfw.DONT_CARE, glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing consume_events_and_render_buffer() def on_window_key(window, key, scancode, action, mods): g_pool.gui.update_key(key, scancode, action, mods) def on_window_char(window, char): g_pool.gui.update_char(char) def on_iconify(window, iconified): g_pool.iconified = iconified def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) pos = x, y pos = normalize(pos, g_pool.camera_render_size) if g_pool.flip: pos = 1 - pos[0], 1 - pos[1] # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for p in g_pool.plugins: p.on_pos(pos) def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) def on_drop(window, paths): for plugin in g_pool.plugins: if plugin.on_drop(paths): break # load session persistent settings session_settings = Persistent_Dict( os.path.join(g_pool.user_dir, "user_settings_eye{}".format(eye_id)) ) if parse_version(session_settings.get("version", "0.0")) != g_pool.version: logger.info( "Session setting are from a different version of this app. I will not use those." ) session_settings.clear() camera_is_physically_flipped = eye_id == 0 g_pool.iconified = False g_pool.capture = None g_pool.flip = session_settings.get("flip", camera_is_physically_flipped) g_pool.display_mode = session_settings.get("display_mode", "camera_image") g_pool.display_mode_info_text = { "camera_image": "Raw eye camera image. This uses the least amount of CPU power", "roi": "Click and drag on the blue circles to adjust the region of interest. The region should be as small as possible, but large enough to capture all pupil movements.", "algorithm": "Algorithm display mode overlays a visualization of the pupil detection parameters on top of the eye video. Adjust parameters within the Pupil Detection menu below.", } def set_display_mode_info(val): g_pool.display_mode = val g_pool.display_mode_info.text = g_pool.display_mode_info_text[val] def toggle_general_settings(collapsed): # this is the menu toggle logic. # Only one menu can be open. # If no menu is open the menubar should collapse. g_pool.menubar.collapsed = collapsed for m in g_pool.menubar.elements: m.collapsed = True general_settings.collapsed = collapsed # Initialize glfw glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: glfw.window_hint(glfw.VISIBLE, 0) # hide window title = "Pupil Capture - eye {}".format(eye_id) # Pupil Cam1 uses 4:3 resolutions. Pupil Cam2 and Cam3 use 1:1 resolutions. # As all Pupil Core and VR/AR add-ons are shipped with Pupil Cam2 and Cam3 # cameras, we adjust the default eye window size to a 1:1 content aspect ratio. # The size of 500 was chosen s.t. the menu still fits. default_window_size = 500 + icon_bar_width, 500 width, height = session_settings.get("window_size", default_window_size) main_window = glfw.create_window(width, height, title, None, None) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( window=main_window, default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) glfw.make_context_current(main_window) cygl.utils.init() # gl_state settings basic_gl_setup() g_pool.image_tex = Named_Texture() g_pool.image_tex.update_from_ndarray(np.ones((1, 1), dtype=np.uint8) + 125) # setup GUI g_pool.gui = ui.UI() g_pool.menubar = ui.Scrolling_Menu( "Settings", pos=(-500, 0), size=(-icon_bar_width, 0), header_pos="left" ) g_pool.iconbar = ui.Scrolling_Menu( "Icons", pos=(-icon_bar_width, 0), size=(0, 0), header_pos="hidden" ) g_pool.gui.append(g_pool.menubar) g_pool.gui.append(g_pool.iconbar) general_settings = ui.Growing_Menu("General", header_pos="headline") def set_window_size(): # Get current capture frame size f_width, f_height = g_pool.capture.frame_size # Eye camera resolutions are too small to be used as default window sizes. # We use double their size instead. frame_scale_factor = 2 f_width *= frame_scale_factor f_height *= frame_scale_factor # Get current display scale factor content_scale = gl_utils.get_content_scale(main_window) framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor f_width *= display_scale_factor f_height *= display_scale_factor # Increas the width to account for the added scaled icon bar width f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append(ui.Switch("flip", g_pool, label="Flip image display")) general_settings.append( ui.Selector( "display_mode", g_pool, setter=set_display_mode_info, selection=["camera_image", "roi", "algorithm"], labels=["Camera Image", "ROI", "Algorithm"], label="Mode", ) ) g_pool.display_mode_info = ui.Info_Text( g_pool.display_mode_info_text[g_pool.display_mode] ) general_settings.append(g_pool.display_mode_info) g_pool.menubar.append(general_settings) icon = ui.Icon( "collapsed", general_settings, label=chr(0xE8B8), on_val=False, off_val=True, setter=toggle_general_settings, label_font="pupil_icons", ) icon.tooltip = "General Settings" g_pool.iconbar.append(icon) plugins_to_load = session_settings.get("loaded_plugins", default_plugins) if overwrite_cap_settings: # Ensure that overwrite_cap_settings takes preference over source plugins # with incorrect settings that were loaded from session settings. plugins_to_load.append(overwrite_cap_settings) # Add runtime plugins to the list of plugins to load with default arguments, # if not already restored from session settings plugins_to_load_names = set(name for name, _ in plugins_to_load) for runtime_detector in runtime_detectors: runtime_name = runtime_detector.__name__ if runtime_name not in plugins_to_load_names: plugins_to_load.append((runtime_name, {})) g_pool.plugins = Plugin_List(g_pool, plugins_to_load) if not g_pool.capture: # Make sure we always have a capture running. Important if there was no # capture stored in session settings. g_pool.plugins.add( g_pool.plugin_by_name[default_capture_name], default_capture_settings ) toggle_general_settings(True) g_pool.writer = None g_pool.rec_path = None # Register callbacks main_window glfw.set_framebuffer_size_callback(main_window, on_resize) glfw.set_window_iconify_callback(main_window, on_iconify) glfw.set_key_callback(main_window, on_window_key) glfw.set_char_callback(main_window, on_window_char) glfw.set_mouse_button_callback(main_window, on_window_mouse_button) glfw.set_cursor_pos_callback(main_window, on_pos) glfw.set_scroll_callback(main_window, on_scroll) glfw.set_drop_callback(main_window, on_drop) # load last gui configuration g_pool.gui.configuration = session_settings.get("ui_config", {}) # If previously selected plugin was not loaded this time, we will have an # expanded menubar without any menu selected. We need to ensure the menubar is # collapsed in this case. if all(submenu.collapsed for submenu in g_pool.menubar.elements): g_pool.menubar.collapsed = True # set up performance graphs pid = os.getpid() ps = psutil.Process(pid) ts = g_pool.get_timestamp() cpu_graph = graph.Bar_Graph() cpu_graph.pos = (20, 50) cpu_graph.update_fn = ps.cpu_percent cpu_graph.update_rate = 5 cpu_graph.label = "CPU %0.1f" fps_graph = graph.Bar_Graph() fps_graph.pos = (140, 50) fps_graph.update_rate = 5 fps_graph.label = "%0.0f FPS" g_pool.graphs = [cpu_graph, fps_graph] # set the last saved window size on_resize(main_window, *glfw.get_framebuffer_size(main_window)) should_publish_frames = False frame_publish_format = "jpeg" frame_publish_format_recent_warning = False # create a timer to control window update frequency window_update_timer = timer(1 / 60) def window_should_update(): return next(window_update_timer) logger.warning("Process started.") frame = None if platform.system() == "Darwin": # On macOS, calls to glfw.swap_buffers() deliberately take longer in case of # occluded windows, based on the swap interval value. This causes an FPS drop # and leads to problems when recording. To side-step this behaviour, the swap # interval is set to zero. # # Read more about window occlusion on macOS here: # https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/WorkWhenVisible.html glfw.swap_interval(0) # Event loop window_should_close = False while not window_should_close: if notify_sub.new_data: t, notification = notify_sub.recv() subject = notification["subject"] if subject.startswith("eye_process.should_stop"): if notification["eye_id"] == eye_id: break elif subject == "recording.started": if notification["record_eye"] and g_pool.capture.online: g_pool.rec_path = notification["rec_path"] raw_mode = notification["compression"] start_time_synced = notification["start_time_synced"] logger.info(f"Will save eye video to: {g_pool.rec_path}") video_path = os.path.join( g_pool.rec_path, "eye{}.mp4".format(eye_id) ) if raw_mode and frame and g_pool.capture.jpeg_support: g_pool.writer = JPEG_Writer(video_path, start_time_synced) elif hasattr(g_pool.capture._recent_frame, "h264_buffer"): g_pool.writer = H264Writer( video_path, g_pool.capture.frame_size[0], g_pool.capture.frame_size[1], g_pool.capture.frame_rate, ) else: g_pool.writer = MPEG_Writer(video_path, start_time_synced) elif subject == "recording.stopped": if g_pool.writer: logger.info("Done recording.") try: g_pool.writer.release() except RuntimeError: logger.error("No eye video recorded") else: # TODO: wrap recording logic into plugin g_pool.capture.intrinsics.save( g_pool.rec_path, custom_name=f"eye{eye_id}" ) finally: g_pool.writer = None elif subject.startswith("meta.should_doc"): ipc_socket.notify( { "subject": "meta.doc", "actor": "eye{}".format(eye_id), "doc": eye.__doc__, } ) elif subject.startswith("frame_publishing.started"): should_publish_frames = True frame_publish_format = notification.get("format", "jpeg") elif subject.startswith("frame_publishing.stopped"): should_publish_frames = False frame_publish_format = "jpeg" elif ( subject.startswith("start_eye_plugin") and notification["target"] == g_pool.process ): try: g_pool.plugins.add( g_pool.plugin_by_name[notification["name"]], notification.get("args", {}), ) except KeyError as err: logger.error(f"Attempt to load unknown plugin: {err}") elif ( subject.startswith("stop_eye_plugin") and notification["target"] == g_pool.process ): try: plugin_to_stop = g_pool.plugin_by_name[notification["name"]] except KeyError as err: logger.error(f"Attempt to load unknown plugin: {err}") else: plugin_to_stop.alive = False g_pool.plugins.clean() for plugin in g_pool.plugins: plugin.on_notify(notification) event = {} for plugin in g_pool.plugins: plugin.recent_events(event) frame = event.get("frame") if frame: if should_publish_frames: try: if frame_publish_format == "jpeg": data = frame.jpeg_buffer elif frame_publish_format == "yuv": data = frame.yuv_buffer elif frame_publish_format == "bgr": data = frame.bgr elif frame_publish_format == "gray": data = frame.gray assert data is not None except (AttributeError, AssertionError, NameError): if not frame_publish_format_recent_warning: frame_publish_format_recent_warning = True logger.warning( '{}s are not compatible with format "{}"'.format( type(frame), frame_publish_format ) ) else: frame_publish_format_recent_warning = False pupil_socket.send( { "topic": "frame.eye.{}".format(eye_id), "width": frame.width, "height": frame.height, "index": frame.index, "timestamp": frame.timestamp, "format": frame_publish_format, "__raw_data__": [data], } ) t = frame.timestamp dt, ts = t - ts, t try: fps_graph.add(1.0 / dt) except ZeroDivisionError: pass if g_pool.writer: try: g_pool.writer.write_video_frame(frame) except NonMonotonicTimestampError as e: logger.error( "Recorder received non-monotonic timestamp!" " Stopping the recording!" ) logger.debug(str(e)) ipc_socket.notify({"subject": "recording.should_stop"}) ipc_socket.notify( {"subject": "recording.should_stop", "remote_notify": "all"} ) for result in event.get(EVENT_KEY, ()): pupil_socket.send(result) # GL drawing if window_should_update(): cpu_graph.update() if is_window_visible(main_window): consume_events_and_render_buffer() glfw.poll_events() window_should_close = glfw.window_should_close(main_window) # END while running # in case eye recording was still runnnig: Save&close if g_pool.writer: logger.info("Done recording eye.") g_pool.writer.release() g_pool.writer = None session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() # save session persistent settings session_settings["flip"] = g_pool.flip session_settings["display_mode"] = g_pool.display_mode session_settings["ui_config"] = g_pool.gui.configuration session_settings["version"] = str(g_pool.version) if not hide_ui: glfw.restore_window(main_window) # need to do this for windows os session_settings["window_position"] = glfw.get_window_pos(main_window) session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): # Store unscaled window size as the operating system will scale the # windows appropriately during launch on Windows and Linux. f_width, f_height = ( f_width / content_scale, f_height / content_scale, ) session_settings["window_size"] = int(f_width), int(f_height) session_settings.close() for plugin in g_pool.plugins: plugin.alive = False g_pool.plugins.clean() glfw.destroy_window(main_window) g_pool.gui.terminate() glfw.terminate() logger.info("Process shutting down.")
def player(rec_dir, ipc_pub_url, ipc_sub_url, ipc_push_url, user_dir, app_version, debug): # general imports from time import sleep import logging from glob import glob from time import time, strftime, localtime # networking import zmq import zmq_tools import numpy as np # zmq ipc setup zmq_ctx = zmq.Context() ipc_pub = zmq_tools.Msg_Dispatcher(zmq_ctx, ipc_push_url) notify_sub = zmq_tools.Msg_Receiver(zmq_ctx, ipc_sub_url, topics=("notify", )) # log setup logging.getLogger("OpenGL").setLevel(logging.ERROR) logger = logging.getLogger() logger.handlers = [] logger.setLevel(logging.NOTSET) logger.addHandler(zmq_tools.ZMQ_handler(zmq_ctx, ipc_push_url)) # create logger for the context of this function logger = logging.getLogger(__name__) try: from background_helper import IPC_Logging_Task_Proxy IPC_Logging_Task_Proxy.push_url = ipc_push_url from tasklib.background.patches import IPCLoggingPatch IPCLoggingPatch.ipc_push_url = ipc_push_url # imports from file_methods import Persistent_Dict, next_export_sub_dir from OpenGL.GL import GL_COLOR_BUFFER_BIT # display import glfw from gl_utils import GLFWErrorReporting GLFWErrorReporting.set_default() # check versions for our own depedencies as they are fast-changing from pyglui import __version__ as pyglui_version from pyglui import ui, cygl from pyglui.cygl.utils import Named_Texture, RGBA import gl_utils # capture from video_capture import File_Source # helpers/utils from version_utils import parse_version from methods import normalize, denormalize, delta_t, get_system_info import player_methods as pm from pupil_recording import PupilRecording from csv_utils import write_key_value_file from hotkey import Hotkey # Plug-ins from plugin import Plugin, Plugin_List, import_runtime_plugins from plugin_manager import Plugin_Manager from vis_circle import Vis_Circle from vis_cross import Vis_Cross from vis_polyline import Vis_Polyline from vis_light_points import Vis_Light_Points from vis_watermark import Vis_Watermark from vis_fixation import Vis_Fixation from seek_control import Seek_Control from surface_tracker import Surface_Tracker_Offline # from marker_auto_trim_marks import Marker_Auto_Trim_Marks from fixation_detector import Offline_Fixation_Detector from log_display import Log_Display from annotations import Annotation_Player from raw_data_exporter import Raw_Data_Exporter from log_history import Log_History from pupil_producers import ( DisabledPupilProducer, Pupil_From_Recording, Offline_Pupil_Detection, ) from gaze_producer.gaze_from_recording import GazeFromRecording from gaze_producer.gaze_from_offline_calibration import ( GazeFromOfflineCalibration, ) from pupil_detector_plugins.detector_base_plugin import PupilDetectorPlugin from system_graphs import System_Graphs from system_timelines import System_Timelines from blink_detection import Offline_Blink_Detection from audio_playback import Audio_Playback from video_export.plugins.imotions_exporter import iMotions_Exporter from video_export.plugins.eye_video_exporter import Eye_Video_Exporter from video_export.plugins.world_video_exporter import World_Video_Exporter from head_pose_tracker.offline_head_pose_tracker import ( Offline_Head_Pose_Tracker, ) from video_capture import File_Source from video_overlay.plugins import Video_Overlay, Eye_Overlay from pupil_recording import ( assert_valid_recording_type, InvalidRecordingException, ) assert parse_version(pyglui_version) >= parse_version( "1.29"), "pyglui out of date, please upgrade to newest version" process_was_interrupted = False def interrupt_handler(sig, frame): import traceback trace = traceback.format_stack(f=frame) logger.debug(f"Caught signal {sig} in:\n" + "".join(trace)) nonlocal process_was_interrupted process_was_interrupted = True signal.signal(signal.SIGINT, interrupt_handler) runtime_plugins = import_runtime_plugins( os.path.join(user_dir, "plugins")) runtime_plugins = [ p for p in runtime_plugins if not issubclass(p, PupilDetectorPlugin) ] system_plugins = [ Log_Display, Seek_Control, Plugin_Manager, System_Graphs, System_Timelines, Audio_Playback, ] user_plugins = [ Vis_Circle, Vis_Fixation, Vis_Polyline, Vis_Light_Points, Vis_Cross, Vis_Watermark, Eye_Overlay, Video_Overlay, Offline_Fixation_Detector, Offline_Blink_Detection, Surface_Tracker_Offline, Raw_Data_Exporter, Annotation_Player, Log_History, DisabledPupilProducer, Pupil_From_Recording, Offline_Pupil_Detection, GazeFromRecording, GazeFromOfflineCalibration, World_Video_Exporter, iMotions_Exporter, Eye_Video_Exporter, Offline_Head_Pose_Tracker, ] + runtime_plugins plugins = system_plugins + user_plugins def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *g_pool.camera_render_size) g_pool.capture.gl_display() for p in g_pool.plugins: p.gl_display() gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() except (AttributeError, glfw.GLFWError): # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed glfw.set_clipboard_string(main_window, user_input.clipboard) for b in user_input.buttons: button, action, mods = b x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None) pos = normalize(pos, g_pool.camera_render_size) pos = denormalize(pos, g_pool.capture.frame_size) for plugin in g_pool.plugins: if plugin.on_click(pos, button, action): break for key, scancode, action, mods in user_input.keys: for plugin in g_pool.plugins: if plugin.on_key(key, scancode, action, mods): break for char_ in user_input.chars: for plugin in g_pool.plugins: if plugin.on_char(char_): break glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): nonlocal window_size nonlocal content_scale if w == 0 or h == 0: return # Always clear buffers on resize to make sure that there are no overlapping # artifacts from previous frames. gl_utils.glClear(GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) content_scale = gl_utils.get_content_scale(window) framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h g_pool.camera_render_size = w - int( icon_bar_width * g_pool.gui.scale), h g_pool.gui.update_window(*window_size) g_pool.gui.collect_menus() for p in g_pool.plugins: p.on_window_resize(window, *g_pool.camera_render_size) # Minimum window size required, otherwise parts of the UI can cause openGL # issues with permanent effects. Depends on the content scale, which can # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) glfw.set_window_size_limits( window, min_size, min_size, glfw.DONT_CARE, glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing consume_events_and_render_buffer() def on_window_key(window, key, scancode, action, mods): g_pool.gui.update_key(key, scancode, action, mods) def on_window_char(window, char): g_pool.gui.update_char(char) def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None) g_pool.gui.update_mouse(x, y) pos = x, y pos = normalize(pos, g_pool.camera_render_size) # Position in img pixels pos = denormalize(pos, g_pool.capture.frame_size) for p in g_pool.plugins: p.on_pos(pos) def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) def on_drop(window, paths): for path in paths: try: assert_valid_recording_type(path) _restart_with_recording(path) return except InvalidRecordingException as err: logger.debug(str(err)) for plugin in g_pool.plugins: if plugin.on_drop(paths): break def _restart_with_recording(rec_dir): logger.debug("Starting new session with '{}'".format(rec_dir)) ipc_pub.notify({ "subject": "player_drop_process.should_start", "rec_dir": rec_dir }) glfw.set_window_should_close(g_pool.main_window, True) tick = delta_t() def get_dt(): return next(tick) recording = PupilRecording(rec_dir) meta_info = recording.meta_info # log info about Pupil Platform and Platform in player.log logger.info("Application Version: {}".format(app_version)) logger.info("System Info: {}".format(get_system_info())) logger.debug(f"Debug flag: {debug}") icon_bar_width = 50 window_size = None content_scale = 1.0 # create container for globally scoped vars g_pool = SimpleNamespace() g_pool.app = "player" g_pool.process = "player" g_pool.zmq_ctx = zmq_ctx g_pool.ipc_pub = ipc_pub g_pool.ipc_pub_url = ipc_pub_url g_pool.ipc_sub_url = ipc_sub_url g_pool.ipc_push_url = ipc_push_url g_pool.plugin_by_name = {p.__name__: p for p in plugins} g_pool.camera_render_size = None video_path = recording.files().core().world().videos()[0].resolve() File_Source( g_pool, timing="external", source_path=video_path, buffered_decoding=True, fill_gaps=True, ) # load session persistent settings session_settings = Persistent_Dict( os.path.join(user_dir, "user_settings_player")) if parse_version(session_settings.get("version", "0.0")) != app_version: logger.info( "Session setting are a different version of this app. I will not use those." ) session_settings.clear() width, height = g_pool.capture.frame_size width += icon_bar_width width, height = session_settings.get("window_size", (width, height)) window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}" glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) main_window = glfw.create_window(width, height, window_name, None, None) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( window=main_window, default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) glfw.make_context_current(main_window) cygl.utils.init() g_pool.main_window = main_window g_pool.version = app_version g_pool.timestamps = g_pool.capture.timestamps g_pool.get_timestamp = lambda: 0.0 g_pool.user_dir = user_dir g_pool.rec_dir = rec_dir g_pool.meta_info = meta_info g_pool.min_data_confidence = session_settings.get( "min_data_confidence", MIN_DATA_CONFIDENCE_DEFAULT) g_pool.min_calibration_confidence = session_settings.get( "min_calibration_confidence", MIN_CALIBRATION_CONFIDENCE_DEFAULT) # populated by producers g_pool.pupil_positions = pm.PupilDataBisector() g_pool.gaze_positions = pm.Bisector() g_pool.fixations = pm.Affiliator() g_pool.eye_movements = pm.Affiliator() def set_data_confidence(new_confidence): g_pool.min_data_confidence = new_confidence notification = {"subject": "min_data_confidence_changed"} notification["_notify_time_"] = time() + 0.8 g_pool.ipc_pub.notify(notification) def do_export(_): left_idx = g_pool.seek_control.trim_left right_idx = g_pool.seek_control.trim_right export_range = left_idx, right_idx + 1 # exclusive range.stop export_ts_window = pm.exact_window(g_pool.timestamps, (left_idx, right_idx)) export_dir = os.path.join(g_pool.rec_dir, "exports") export_dir = next_export_sub_dir(export_dir) os.makedirs(export_dir) logger.info('Created export dir at "{}"'.format(export_dir)) export_info = { "Player Software Version": str(g_pool.version), "Data Format Version": meta_info.min_player_version, "Export Date": strftime("%d.%m.%Y", localtime()), "Export Time": strftime("%H:%M:%S", localtime()), "Frame Index Range:": g_pool.seek_control.get_frame_index_trim_range_string(), "Relative Time Range": g_pool.seek_control.get_rel_time_trim_range_string(), "Absolute Time Range": g_pool.seek_control.get_abs_time_trim_range_string(), } with open(os.path.join(export_dir, "export_info.csv"), "w") as csv: write_key_value_file(csv, export_info) notification = { "subject": "should_export", "range": export_range, "ts_window": export_ts_window, "export_dir": export_dir, } g_pool.ipc_pub.notify(notification) def reset_restart(): logger.warning("Resetting all settings and restarting Player.") glfw.set_window_should_close(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify({ "subject": "player_process.should_start", "rec_dir": rec_dir, "delay": 2.0, }) def toggle_general_settings(collapsed): # this is the menu toggle logic. # Only one menu can be open. # If no menu is open the menubar should collapse. g_pool.menubar.collapsed = collapsed for m in g_pool.menubar.elements: m.collapsed = True general_settings.collapsed = collapsed g_pool.gui = ui.UI() g_pool.menubar = ui.Scrolling_Menu("Settings", pos=(-500, 0), size=(-icon_bar_width, 0), header_pos="left") g_pool.iconbar = ui.Scrolling_Menu("Icons", pos=(-icon_bar_width, 0), size=(0, 0), header_pos="hidden") g_pool.timelines = ui.Container((0, 0), (0, 0), (0, 0)) g_pool.timelines.horizontal_constraint = g_pool.menubar g_pool.user_timelines = ui.Timeline_Menu("User Timelines", pos=(0.0, -150.0), size=(0.0, 0.0), header_pos="headline") g_pool.user_timelines.color = RGBA(a=0.0) g_pool.user_timelines.collapsed = True # add container that constaints itself to the seekbar height vert_constr = ui.Container((0, 0), (0, -50.0), (0, 0)) vert_constr.append(g_pool.user_timelines) g_pool.timelines.append(vert_constr) def set_window_size(): # Get current capture frame size f_width, f_height = g_pool.capture.frame_size # Get current display scale factor content_scale = gl_utils.get_content_scale(main_window) framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor f_width *= display_scale_factor f_height *= display_scale_factor # Increas the width to account for the added scaled icon bar width f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings = ui.Growing_Menu("General", header_pos="headline") general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append( ui.Info_Text( f"Minimum Player Version: {meta_info.min_player_version}")) general_settings.append( ui.Info_Text(f"Player Version: {g_pool.version}")) general_settings.append( ui.Info_Text( f"Recording Software: {meta_info.recording_software_name}")) general_settings.append( ui.Info_Text( f"Recording Software Version: {meta_info.recording_software_version}" )) general_settings.append( ui.Info_Text( "High level data, e.g. fixations, or visualizations only consider gaze data that has an equal or higher confidence than the minimum data confidence." )) general_settings.append( ui.Slider( "min_data_confidence", g_pool, setter=set_data_confidence, step=0.05, min=0.0, max=1.0, label="Minimum data confidence", )) general_settings.append( ui.Button("Restart with default settings", reset_restart)) g_pool.menubar.append(general_settings) icon = ui.Icon( "collapsed", general_settings, label=chr(0xE8B8), on_val=False, off_val=True, setter=toggle_general_settings, label_font="pupil_icons", ) icon.tooltip = "General Settings" g_pool.iconbar.append(icon) user_plugin_separator = ui.Separator() user_plugin_separator.order = 0.35 g_pool.iconbar.append(user_plugin_separator) g_pool.quickbar = ui.Stretching_Menu("Quick Bar", (0, 100), (100, -100)) g_pool.export_button = ui.Thumb( "export", label=chr(0xE2C5), getter=lambda: False, setter=do_export, hotkey=Hotkey.EXPORT_START_PLAYER_HOTKEY(), label_font="pupil_icons", ) g_pool.quickbar.extend([g_pool.export_button]) g_pool.gui.append(g_pool.menubar) g_pool.gui.append(g_pool.timelines) g_pool.gui.append(g_pool.iconbar) g_pool.gui.append(g_pool.quickbar) # we always load these plugins _pupil_producer_plugins = [ # In priority order (first is default) ("Pupil_From_Recording", {}), ("Offline_Pupil_Detection", {}), ("DisabledPupilProducer", {}), ] _pupil_producer_plugins = list(reversed(_pupil_producer_plugins)) _gaze_producer_plugins = [ # In priority order (first is default) ("GazeFromRecording", {}), ("GazeFromOfflineCalibration", {}), ] _gaze_producer_plugins = list(reversed(_gaze_producer_plugins)) default_plugins = [ ("Plugin_Manager", {}), ("Seek_Control", {}), ("Log_Display", {}), ("Raw_Data_Exporter", {}), ("Vis_Polyline", {}), ("Vis_Circle", {}), ("System_Graphs", {}), ("System_Timelines", {}), ("World_Video_Exporter", {}), *_pupil_producer_plugins, *_gaze_producer_plugins, ("Audio_Playback", {}), ] _plugins_to_load = session_settings.get("loaded_plugins", None) if _plugins_to_load is None: # If no plugins are available from a previous session, # then use the default plugin list _plugins_to_load = default_plugins else: # If there are plugins available from a previous session, # then prepend plugins that are required, but might have not been available before _plugins_to_load = [ *_pupil_producer_plugins, *_gaze_producer_plugins, *_plugins_to_load, ] g_pool.plugins = Plugin_List(g_pool, _plugins_to_load) # Manually add g_pool.capture to the plugin list g_pool.plugins._plugins.append(g_pool.capture) g_pool.plugins._plugins.sort(key=lambda p: p.order) g_pool.capture.init_ui() general_settings.insert( -1, ui.Text_Input( "rel_time_trim_section", getter=g_pool.seek_control.get_rel_time_trim_range_string, setter=g_pool.seek_control.set_rel_time_trim_range_string, label="Relative time range to export", ), ) general_settings.insert( -1, ui.Text_Input( "frame_idx_trim_section", getter=g_pool.seek_control.get_frame_index_trim_range_string, setter=g_pool.seek_control.set_frame_index_trim_range_string, label="Frame index range to export", ), ) # Register callbacks main_window glfw.set_framebuffer_size_callback(main_window, on_resize) glfw.set_key_callback(main_window, on_window_key) glfw.set_char_callback(main_window, on_window_char) glfw.set_mouse_button_callback(main_window, on_window_mouse_button) glfw.set_cursor_pos_callback(main_window, on_pos) glfw.set_scroll_callback(main_window, on_scroll) glfw.set_drop_callback(main_window, on_drop) toggle_general_settings(True) g_pool.gui.configuration = session_settings.get("ui_config", {}) # If previously selected plugin was not loaded this time, we will have an # expanded menubar without any menu selected. We need to ensure the menubar is # collapsed in this case. if all(submenu.collapsed for submenu in g_pool.menubar.elements): g_pool.menubar.collapsed = True # gl_state settings gl_utils.basic_gl_setup() g_pool.image_tex = Named_Texture() # trigger on_resize on_resize(main_window, *glfw.get_framebuffer_size(main_window)) def handle_notifications(n): subject = n["subject"] if subject == "start_plugin": g_pool.plugins.add(g_pool.plugin_by_name[n["name"]], args=n.get("args", {})) elif subject.startswith("meta.should_doc"): ipc_pub.notify({ "subject": "meta.doc", "actor": g_pool.app, "doc": player.__doc__ }) for p in g_pool.plugins: if (p.on_notify.__doc__ and p.__class__.on_notify != Plugin.on_notify): ipc_pub.notify({ "subject": "meta.doc", "actor": p.class_name, "doc": p.on_notify.__doc__, }) while not glfw.window_should_close( main_window) and not process_was_interrupted: # fetch newest notifications new_notifications = [] while notify_sub.new_data: t, n = notify_sub.recv() new_notifications.append(n) # notify each plugin if there are new notifications: for n in new_notifications: handle_notifications(n) for p in g_pool.plugins: p.on_notify(n) events = {} # report time between now and the last loop interation events["dt"] = get_dt() # pupil and gaze positions are added by their respective producer plugins events["pupil"] = [] events["gaze"] = [] # allow each Plugin to do its work. for p in g_pool.plugins: p.recent_events(events) # check if a plugin need to be destroyed g_pool.plugins.clean() glfw.make_context_current(main_window) glfw.poll_events() # render visual feedback from loaded plugins if gl_utils.is_window_visible(main_window): gl_utils.glViewport(0, 0, *g_pool.camera_render_size) g_pool.capture.gl_display() for p in g_pool.plugins: p.gl_display() gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() except (AttributeError, glfw.GLFWError): # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed glfw.set_clipboard_string(main_window, user_input.clipboard) for b in user_input.buttons: button, action, mods = b x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None) pos = normalize(pos, g_pool.camera_render_size) pos = denormalize(pos, g_pool.capture.frame_size) for plugin in g_pool.plugins: if plugin.on_click(pos, button, action): break for key, scancode, action, mods in user_input.keys: for plugin in g_pool.plugins: if plugin.on_key(key, scancode, action, mods): break for char_ in user_input.chars: for plugin in g_pool.plugins: if plugin.on_char(char_): break # present frames at appropriate speed g_pool.seek_control.wait(events["frame"].timestamp) glfw.swap_buffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["min_data_confidence"] = g_pool.min_data_confidence session_settings[ "min_calibration_confidence"] = g_pool.min_calibration_confidence session_settings["ui_config"] = g_pool.gui.configuration session_settings["window_position"] = glfw.get_window_pos(main_window) session_settings["version"] = str(g_pool.version) session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): f_width, f_height = ( f_width / content_scale, f_height / content_scale, ) session_settings["window_size"] = int(f_width), int(f_height) session_settings.close() # de-init all running plugins for p in g_pool.plugins: p.alive = False g_pool.plugins.clean() g_pool.gui.terminate() glfw.destroy_window(main_window) except Exception: import traceback trace = traceback.format_exc() logger.error("Process Player crashed with trace:\n{}".format(trace)) finally: logger.info("Process shutting down.") ipc_pub.notify({"subject": "player_process.stopped"}) sleep(1.0)
def main(): if not glfw.init(): raise RuntimeError('Failed to initialize GLFW') version = glfw.get_version_string().decode('ASCII') print('GLFW', version) monitors = glfw.get_monitors() for i, monitor in enumerate(monitors): name = glfw.get_monitor_name(monitor) primary = (glfw.get_monitor_pos(monitor) == glfw.get_monitor_pos(glfw.get_primary_monitor())) print('Monitor #{}: {}{}'.format(i, name.decode('utf8'), ' (primary)' if primary else '')) width_mm, height_mm = glfw.get_monitor_physical_size(monitor) diag_mm = math.sqrt(width_mm*width_mm + height_mm*height_mm) print('Diagonal: {:.1f}"'.format(diag_mm / 25.4)) mode = glfw.get_video_mode(monitor) print('Video mode: {}x{} {}Hz {}'.format(mode.size.width, mode.size.height, mode.refresh_rate, mode.bits)) xscale, yscale = glfw.get_monitor_content_scale(monitor) print('Scale: {}|{}'.format(xscale, yscale)) print('Virtual position:', glfw.get_monitor_pos(monitor)) print('Work ares:', glfw.get_monitor_workarea(monitor)) for mode in glfw.get_video_modes(monitor): print('Supported: {}x{} {}Hz {}'.format(mode.size.width, mode.size.height, mode.refresh_rate, mode.bits)) print(mode) print() glfw.window_hint(glfw.RESIZABLE, True) glfw.window_hint(glfw.STENCIL_BITS, 8) glfw.window_hint(glfw.CLIENT_API, glfw.OPENGL_API) glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 6) glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) monitor = glfw.get_primary_monitor() mode = glfw.get_video_mode(monitor) window = glfw.create_window(640, 480, 'Title', None, None) # window = glfw.create_window(mode.size.width, mode.size.height, 'Title', monitor, None) if window is None: glfw.terminate() raise RuntimeError('Failed to create a window') # glfw.set_window_monitor(window, monitor, 0, 0, mode.size.width, mode.size.height, mode.refresh_rate) width, height = glfw.get_window_size(window) print('Window size: {}x{}'.format(width, height)) print('Frame size:', glfw.get_window_frame_size(window)) width, height = glfw.get_framebuffer_size(window) print('Framebuffer size: {}x{}'.format(width, height)) print('Client API:', glfw.get_window_attrib(window, glfw.CLIENT_API)) version_major = glfw.get_window_attrib(window, glfw.CONTEXT_VERSION_MAJOR) version_minor = glfw.get_window_attrib(window, glfw.CONTEXT_VERSION_MINOR) revision = glfw.get_window_attrib(window, glfw.CONTEXT_REVISION) print('Version: {}.{} rev{}'.format(version_major, version_minor, revision)) glfw.make_context_current(window) renderer = Renderer(window) while not glfw.window_should_close(window): GL.glClear(GL.GL_COLOR_BUFFER_BIT) renderer.render() glfw.swap_buffers(window) glfw.poll_events() glfw.terminate()
def on_scroll(self, win, _deltax, deltay): """ Scroll controls the camera distance to trackball center """ self.zoom(deltay, glfw.get_window_size(win)[1])
def initialize(window): global cursorOnCowBoundingBox, floorTexID, cameraIndex, camModel, cow2wld, cowModel cursorOnCowBoundingBox=False; # Set up OpenGL state glShadeModel(GL_SMOOTH); # Set Smooth Shading glEnable(GL_DEPTH_TEST); # Enables Depth Testing glDepthFunc(GL_LEQUAL); # The Type Of Depth Test To Do # Use perspective correct interpolation if available glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); # Initialize the matrix stacks width, height = glfw.get_window_size(window) reshape(window, width, height); # Define lighting for the scene lightDirection = [1.0, 1.0, 1.0, 0]; ambientIntensity = [0.1, 0.1, 0.1, 1.0]; lightIntensity = [0.9, 0.9, 0.9, 1.0]; glLightfv(GL_LIGHT0, GL_AMBIENT, ambientIntensity); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightIntensity); glLightfv(GL_LIGHT0, GL_POSITION, lightDirection); glEnable(GL_LIGHT0); # initialize floor im = open('bricks.bmp') try: ix, iy, image = im.size[0], im.size[1], im.tobytes("raw", "RGB", 0, -1) except SystemError: ix, iy, image = im.size[0], im.size[1], im.tobytes("raw", "RGBX", 0, -1) # Make texture which is accessible through floorTexID. floorTexID=glGenTextures( 1) glBindTexture(GL_TEXTURE_2D, floorTexID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, ix, 0, GL_RGB, GL_UNSIGNED_BYTE, image); # initialize cow cowModel=OBJ.OBJrenderer("cow.obj") # initialize cow2wld matrix glPushMatrix(); # Push the current matrix of GL into stack. glLoadIdentity(); # Set the GL matrix Identity matrix. glTranslated(0,-cowModel.bbmin[1],-8); # Set the location of cow. glRotated(-90, 0, 1, 0); # Set the direction of cow. These information are stored in the matrix of GL. cow2wld=glGetDoublev(GL_MODELVIEW_MATRIX).T # convert column-major to row-major glPopMatrix(); # Pop the matrix on stack to GL. # intialize camera model. camModel=OBJ.OBJrenderer("camera.obj") # initialize camera frame transforms. cameraCount=len(cameras) for i in range(cameraCount): # 'c' points the coordinate of i-th camera. c = cameras[i]; glPushMatrix(); # Push the current matrix of GL into stack. glLoadIdentity(); # Set the GL matrix Identity matrix. gluLookAt(c[0],c[1],c[2], c[3],c[4],c[5], c[6],c[7],c[8]); # Setting the coordinate of camera. wld2cam.append(glGetDoublev(GL_MODELVIEW_MATRIX).T) glPopMatrix(); # Transfer the matrix that was pushed the stack to GL. cam2wld.append(np.linalg.inv(wld2cam[i])) cameraIndex = 0;
def get_size(self): """获取窗口尺寸""" if self.window is None: return None return glfw.get_window_size(self.window)
def start(self): logger.info('initializing glfw@%s', glfw.get_version()) glfw.set_error_callback(_glfw_error_callback) if not glfw.init(): raise Exception('glfw failed to initialize') window = None if self.visible: glfw.window_hint(glfw.SAMPLES, 4) else: glfw.window_hint(glfw.VISIBLE, 0); # try stereo if refresh rate is at least 100Hz stereo_available = False _, _, refresh_rate = glfw.get_video_mode(glfw.get_primary_monitor()) if refresh_rate >= 100: glfw.window_hint(glfw.STEREO, 1) window = glfw.create_window( self.init_width, self.init_height, "Simulate", None, None) if window: stereo_available = True # no stereo: try mono if not window: glfw.window_hint(glfw.STEREO, 0) window = glfw.create_window( self.init_width, self.init_height, "Simulate", None, None) if not window: glfw.terminate() return self.running = True # Make the window's context current glfw.make_context_current(window) self._init_framebuffer_object() width, height = glfw.get_framebuffer_size(window) width1, height = glfw.get_window_size(window) self._scale = width * 1.0 / width1 self.window = window mjlib.mjv_makeObjects(byref(self.objects), 1000) mjlib.mjv_defaultCamera(byref(self.cam)) mjlib.mjv_defaultOption(byref(self.vopt)) mjlib.mjr_defaultOption(byref(self.ropt)) mjlib.mjr_defaultContext(byref(self.con)) if self.model: mjlib.mjr_makeContext(self.model.ptr, byref(self.con), 150) self.autoscale() else: mjlib.mjr_makeContext(None, byref(self.con), 150) glfw.set_cursor_pos_callback(window, self.handle_mouse_move) glfw.set_mouse_button_callback(window, self.handle_mouse_button) glfw.set_scroll_callback(window, self.handle_scroll)