CCCPaste

# tk_Basic_Optimizations_Demo.py

# tk_Basic_Optimizations_Demo.py

import tkinter as tk

canvas_width = 600
canvas_height = 600
pan_offset_x = 0

scene_objects = [
    [50, 50, 50, 0, 0],
    [150, 70, 40, 1, 0],
    [250, 60, 60, 0, 1],
    [350, 80, 30, 1, 1],
    [450, 90, 55, 0, 2],
    [550, 100, 45, 1, 2],
    [100, 250, 70, 0, 0],
    [200, 270, 50, 1, 0],
    [300, 260, 80, 0, 1],
    [400, 280, 35, 1, 1],
    [500, 290, 65, 0, 2],
    [50, 450, 60, 0, 0],
    [150, 470, 45, 1, 0],
    [250, 460, 75, 0, 1],
    [350, 480, 38, 1, 1],
    [450, 490, 60, 0, 2],
    [550, 500, 50, 1, 2]
]

zsort_triangles = [
	[60, 50, 50, 2, 0],
	[80, 150, 50, 2, 0],
	[220, 120, 60, 2, 1],
	[400, 70, 70, 2, 2],
	[520, 150, 80, 2, 3],
	[100, 350, 90, 2, 4],
	[300, 450, 100, 2, 5],
	[580, 300, 70, 2, 6],
	[180, 270, 60, 2, 7],
	[480, 370, 80, 2, 8],
	[360, 240, 90, 2, 9],
	[60, 50, 15, 2, 0],
	[100, 70, 10, 2, 1],
	[140, 90, 12, 2, 2],
	[180, 110, 8, 2, 3],
	[220, 130, 14, 2, 4],
	[260, 150, 9, 2, 5],
	[300, 170, 13, 2, 6],
	[340, 190, 11, 2, 7],
	[380, 210, 10, 2, 8],
	[420, 230, 12, 2, 9],
	[460, 250, 14, 2, 10],
	[500, 270, 9, 2, 11],
	[540, 290, 13, 2, 12],
	[580, 310, 11, 2, 13],
	[100, 350, 10, 2, 14],
	[140, 370, 12, 2, 15],
	[180, 390, 8, 2, 16],
	[220, 410, 14, 2, 17],
	[260, 430, 9, 2, 18],
	[300, 450, 13, 2, 19]
]

occluder = [200, 200, 200, "gray"]
frustum = [120, 120, 480, 480]

def get_wrapped_x(x):
    return (x + pan_offset_x) % canvas_width

def get_bounding_box(x, y, size):
    return (x, y, x + size, y + size)

def is_inside_frustum(x, y, size):
    left, top, right, bottom = get_bounding_box(get_wrapped_x(x), y, size)
    return not (right < frustum[0] or left > frustum[2] or bottom < frustum[1] or top > frustum[3])

def is_occluded(x, y, size):
    left, top, right, bottom = get_bounding_box(get_wrapped_x(x), y, size)
    return (left >= occluder[0] and top >= occluder[1] and right <= occluder[0] + occluder[2] and bottom <= occluder[1] + occluder[2])

def draw_object(x, y, size, shape_type, dashed=False, stationary=False):
    x = x if stationary else get_wrapped_x(x)
    dash = (2, 2) if dashed else None
    outline = "black"

    if shape_type == 0:  # Rectangle
        fill = "blue"
        canvas.create_rectangle(x, y, x + size, y + size, fill=fill if not dashed else "", outline=outline, dash=dash)
    elif shape_type == 1:  # Oval
        fill = "red"
        canvas.create_oval(x, y, x + size, y + size, fill=fill if not dashed else "", outline=outline, dash=dash)
    elif shape_type == 2:  # Triangle
        fill = "green"
        points = [
            x + size / 2, y,
            x, y + size,
            x + size, y + size
        ]
        canvas.create_polygon(points, fill=fill, outline=outline,)

def draw_square(x, y, size, fill_color="blue"):
    canvas.create_rectangle(x, y, x + size, y + size, fill=fill_color, outline="black")

def render_scene():
    canvas.delete("all")
    canvas.create_text(300, 20, text="Basic Optimizations Demo", fill="black", font=("Arial", 12))
    draw_square(occluder[0], occluder[1], occluder[2], occluder[3])
    canvas.create_text(occluder[0], occluder[1], text="Occluder", fill="black", anchor="s")
    canvas.create_rectangle(frustum[0], frustum[1], frustum[2], frustum[3], outline="cyan", width=2)
    canvas.create_text(frustum[0], frustum[1], text="Frustum", fill="cyan", anchor="s")

    all_objects = scene_objects + zsort_triangles

    if enable_zsort.get():
        all_objects = sorted(all_objects, key=lambda o: o[2])  # ascending
    else:
        all_objects = sorted(all_objects, key=lambda o: -o[2])  # descending

    for obj in all_objects:
        x, y, size, shape_type, _ = obj
        stationary = (shape_type == 2)
        frustum_culled = enable_frustum.get() and not is_inside_frustum(x, y, size)
        occlusion_culled = enable_occlusion.get() and is_occluded(x, y, size)
        dashed = frustum_culled or occlusion_culled
        draw_object(x, y, size, shape_type, dashed=dashed, stationary=stationary)

def auto_pan():
    global pan_offset_x
    pan_offset_x -= 2
    render_scene()
    root.after(20, auto_pan)

root = tk.Tk()
root.title("Basic Optimizations Demo")
root.geometry("800x600+0+0")

canvas = tk.Canvas(root, width=canvas_width, height=canvas_height, bg="white")
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

control_frame = tk.Frame(root)
control_frame.pack(side=tk.RIGHT, fill=tk.Y)

enable_frustum = tk.BooleanVar()
enable_occlusion = tk.BooleanVar()
enable_zsort = tk.BooleanVar()

tk.Checkbutton(control_frame, text="Frustum Culling", variable=enable_frustum, command=render_scene).pack(anchor="w", padx=10, pady=5)
tk.Checkbutton(control_frame, text="Occlusion Culling", variable=enable_occlusion, command=render_scene).pack(anchor="w", padx=10, pady=5)
tk.Checkbutton(control_frame, text="Z-Index Sorting", variable=enable_zsort, command=render_scene).pack(anchor="w", padx=10, pady=5)

render_scene()
auto_pan()
root.mainloop()