def intersect_ray(self, ray_origin, ray_direction): """RayCollider.intersect_ray(ray_origin, ray_direction) -> None or (t, hit_info). hit_info value depends on the object hit: can be the aabb or triangle. """ result = None if raytri.hit_aabb(ray_origin, ray_direction, self.aabb): for triangle in self.triangles: r = raytri.intersect_triangle(ray_origin, ray_direction, *triangle) if r and (not result or r[0] < result[0]): t, u, v = r result = t, (u, v, triangle) return result
def main(): glfw.setErrorCallback(error_callback) glfw.init() glfw.windowHint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.windowHint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.windowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) glfw.windowHint(glfw.RESIZABLE, gl.FALSE) glfw.windowHint(glfw.OPENGL_FORWARD_COMPAT, 1) window = glfw.createWindow(WIDTH, HEIGHT, "LearnOpenGL") if window is None: # print('could not open window.') glfw.terminate() sys.exit() cursor = Vec2() window_size = Vec2(WIDTH, HEIGHT) ui = EventEmitter() def mouse_move_callback(window, x, y): nonlocal cursor # print('mouse move:', window, x, y) cursor = Vec2(x, window_size.y - y) ui.emit('mouse_move', window, cursor) def mouse_button_callback(window, button, action, mods): print('mouse button:', window, button, action, mods) ui.emit('mouse_button', window, button, action, mods) def window_size_callback(window, width, height): nonlocal window_size window_size.x = width window_size.y = height window.makeContextCurrent() # window.setInputMode(glfw.CURSOR, glfw.CURSOR_DISABLED) window.setKeyCallback(key_callback) window.setMouseButtonCallback(mouse_button_callback) window.setCursorPosCallback(mouse_move_callback) window.setWindowSizeCallback(window_size_callback) gl.init() err = gl.getError() if err: print("WINDOW OPEN ERROR:", err) # pre game-loop initialization scene = Scene() # construct the triangle triangle_points = Vector(Vec3) triangle_points.append(Vec3(-0.5, -0.5, 0.0)) triangle_points.append(Vec3( 0.5, -0.5, 0.0)) triangle_points.append(Vec3(-0.5, 0.5, 0.0)) triangle_indices = Vector(c_ubyte) triangle_indices.append(0) triangle_indices.append(1) triangle_indices.append(2) triangle_attribs = BufferAttribs(sizeof(Vec3)) triangle_attribs.add(BufferAttribs.POSITION_INDEX, 3, gl.FLOAT, gl.FALSE, 0) triangle_shader = ShaderProgram(VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) triangle_draw_call = DrawCall(gl.UNSIGNED_BYTE, gl.LINE_LOOP, 0, len(triangle_indices)) triangle_material = {} triangle_mesh = Mesh(triangle_shader, triangle_draw_call, triangle_material) triangle_model = Model(triangle_indices.get_data(), triangle_points.get_data(), triangle_attribs, [triangle_mesh], InstanceData, ItemInstance) triangle_instance = scene.add(triangle_model, InstanceData(model_matrix=Mat4.Identity(), base_color=Vec3(1.0, 0.0, 0.0))) # construct the reticle RETICLE_SIZE = 0.01 reticle_points = Vector(Vec3) reticle_points.append(Vec3(-RETICLE_SIZE * 0.5, -RETICLE_SIZE * 0.5, 0.0)) reticle_points.append(Vec3(-RETICLE_SIZE * 0.5, RETICLE_SIZE * 0.5, 0.0)) reticle_points.append(Vec3( RETICLE_SIZE * 0.5, RETICLE_SIZE * 0.5, 0.0)) reticle_points.append(Vec3( RETICLE_SIZE * 0.5, -RETICLE_SIZE * 0.5, 0.0)) reticle_indices = Vector(c_ubyte) reticle_indices.append(0) reticle_indices.append(1) reticle_indices.append(2) reticle_indices.append(3) reticle_attribs = BufferAttribs(sizeof(Vec3)) reticle_attribs.add(BufferAttribs.POSITION_INDEX, 3, gl.FLOAT, gl.FALSE, 0) reticle_shader = triangle_shader reticle_draw_call = DrawCall(gl.UNSIGNED_BYTE, gl.LINE_LOOP, 0, len(reticle_indices)) reticle_material = {} reticle_mesh = Mesh(reticle_shader, reticle_draw_call, reticle_material) reticle_model = Model(reticle_indices.get_data(), reticle_points.get_data(), reticle_attribs, [reticle_mesh], InstanceData, ItemInstance) # construct the AABB model aabb = AABB3() aabb.include_point(Vec3(0.0, 0.0, 0.0)) aabb.include_point(Vec3(0.2, 0.2, 0.2)) aabb_points = Vector(Vec3) aabb_points.append(Vec3(aabb.min.x, aabb.min.y, aabb.min.z)) aabb_points.append(Vec3(aabb.max.x, aabb.min.y, aabb.min.z)) aabb_points.append(Vec3(aabb.min.x, aabb.max.y, aabb.min.z)) aabb_points.append(Vec3(aabb.max.x, aabb.max.y, aabb.min.z)) aabb_points.append(Vec3(aabb.min.x, aabb.min.y, aabb.max.z)) aabb_points.append(Vec3(aabb.max.x, aabb.min.y, aabb.max.z)) aabb_points.append(Vec3(aabb.min.x, aabb.max.y, aabb.max.z)) aabb_points.append(Vec3(aabb.max.x, aabb.max.y, aabb.max.z)) # lines aabb_indices = Vector(c_ubyte) aabb_indices.append(0) aabb_indices.append(1) aabb_indices.append(2) aabb_indices.append(3) aabb_indices.append(4) aabb_indices.append(5) aabb_indices.append(6) aabb_indices.append(7) aabb_indices.append(0) aabb_indices.append(4) aabb_indices.append(1) aabb_indices.append(5) aabb_indices.append(2) aabb_indices.append(6) aabb_indices.append(3) aabb_indices.append(7) aabb_indices.append(0) aabb_indices.append(2) aabb_indices.append(1) aabb_indices.append(3) aabb_indices.append(4) aabb_indices.append(6) aabb_indices.append(5) aabb_indices.append(7) aabb_attribs = BufferAttribs(sizeof(Vec3)) aabb_attribs.add(BufferAttribs.POSITION_INDEX, 3, gl.FLOAT, gl.FALSE, 0) aabb_shader = triangle_shader aabb_draw_call = DrawCall(gl.UNSIGNED_BYTE, gl.LINES, 0, len(aabb_indices)) aabb_material = {} aabb_mesh = Mesh(aabb_shader, aabb_draw_call, aabb_material) aabb_model = Model(aabb_indices.get_data(), aabb_points.get_data(), aabb_attribs, [aabb_mesh], InstanceData, ItemInstance) # reticle_instances = ModelInstances(reticle_model, InstanceData, ItemInstance) reticle_instance = scene.add(reticle_model, InstanceData(model_matrix=Mat4.Identity())) # aabb_instances = ModelInstances(aabb_model, InstanceData, ItemInstance) aabb_instance = scene.add(aabb_model, InstanceData(model_matrix=Mat4.Identity())) #reticle_instance.set_enabled(False) ray_scene = RayScene() # ui.on('mouse_move' lambda window, cursor: scene.mouse_move(camera, viewport, cursor)) camera = Camera(scene=scene) framebuffer_width, framebuffer_height = window.getFramebufferSize() # camera.projection_matrix = Mat4.Identity() camera.projection_matrix = Mat4.Perspective(45.0, framebuffer_width/framebuffer_height, 0.1, 100.0) camera.view_matrix = Mat4.Identity() t0 = time.perf_counter() frames = 0 while not window.shouldClose(): glfw.pollEvents() gl.enable(gl.DEPTH_TEST) gl.depthFunc(gl.LEQUAL) gl.enable(gl.CULL_FACE) gl.cullFace(gl.BACK) t = time.perf_counter() err = gl.getError() if err: print("ERROR:", err) # render the frame framebuffer_width, framebuffer_height = window.getFramebufferSize() # camera.view_matrix = Mat4.LookAt(Vec3(math.cos(time.clock() * 0.1), 1.0, math.sin(time.clock() * 0.1)) *15.0, Vec3(0.0, 0.0, 0.0), Vec3(0.0, 1.0, 0.0)) camera.view_matrix = Mat4.LookAt( Vec3(math.cos(time.clock() * 0.1), 1.0, math.sin(time.clock() * 0.1)) *2.0, Vec3(0.0, 0.0, 0.0), Vec3(0.0, 1.0, 0.0) ) viewport = (0, 0, framebuffer_width, framebuffer_height) camera.render_to_viewport(viewport) # not sure if this is correct when the viewport size doesn't match the framebuffer size. ray_origin, ray_direction = camera.get_ray(cursor, viewport) # print(ray) result = raytri.intersect_triangle(ray_origin, ray_direction, *triangle_points) if result: t, u, v = result hit_pos = triangle_points[0] * (1.0 - u - v) + triangle_points[1] * u + triangle_points[2] * v reticle_instance.set_enabled(True) reticle_instance.model_matrix = Mat4.Translation(hit_pos) reticle_instance.base_color = Vec3(1.0, 1.0, 1.0) triangle_instance.base_color = Vec3(1.0, 0.0, 0.0) else: reticle_instance.set_enabled(False) triangle_instance.base_color = Vec3(1.0, 1.0, 1.0) reticle_instance.base_color = Vec3(0.0, 0.0, 0.0) result = raytri.hit_aabb(ray_origin, ray_direction, aabb) if result: aabb_instance.base_color = Vec3(1.0, 0.0, 0.0) else: aabb_instance.base_color = Vec3(1.0, 1.0, 1.0) # print((ray_origin, ray_direction), result) # update buffers scene.update_instances() window.swapBuffers() frames += 1 if not frames % 100: print("FRAME RATE:", float(frames)/(time.perf_counter() - t0))