Пример #1
0
    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
Пример #2
0
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))