Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # tk_3d_voxel_animation.py
- import tkinter as tk
- import math
- def create_cube():
- voxels = []
- for x in range(-1, 2):
- for y in range(-1, 2):
- for z in range(-1, 2):
- voxels.append((x, y, z))
- return voxels
- def rotate_point(x, y, z):
- x0 = math.radians(angle_x + move_x)
- y0 = math.radians(angle_y + move_y)
- z0 = math.radians(angle_z + move_z)
- # Rotate around Z-axis
- new_x = x * math.cos(z0) - y * math.sin(z0)
- new_y = x * math.sin(z0) + y * math.cos(z0)
- # Rotate around Y-axis
- new_x, new_z = new_x * math.cos(y0) - z * math.sin(y0), new_x * math.sin(y0) + z * math.cos(y0)
- # Rotate around X-axis
- new_y, new_z = new_y * math.cos(x0) - new_z * math.sin(x0), new_y * math.sin(x0) + new_z * math.cos(x0)
- return new_x, new_y, new_z
- def project(x, y, z):
- factor = 200 / (4 - z)
- return cx + x * factor, cy - y * factor
- def draw_voxel(x, y, z):
- size = 20 / (4 - z)
- x0, y0 = project(x, y, z)
- canvas.create_rectangle(x0-size, y0-size, x0+size, y0+size, fill="white", outline="")
- def draw_grid_line(angle):
- rad = math.radians(angle)
- x_offset = 300 * math.cos(rad)
- y_offset = 300 * math.sin(rad)
- canvas.create_line(cx, cy, cx + x_offset, cy - y_offset, fill="red")
- def update_status():
- status_var.set(f"@ Angle: {angle % 360:.2f}°, Cube Rotation Angles -> Angle X: {move_x % 360:.2f}°, Angle Y: {move_y % 360:.2f}°, Angle Z: {move_z % 360:.2f}°")
- def on_x_slider_cube(value):
- global angle_x
- angle_x = float(value)
- def on_y_slider_cube(value):
- global angle_y
- angle_y = float(value)
- def on_z_slider_cube(value):
- global angle_z
- angle_z = float(value)
- def on_x_slider_move(value):
- global move_x0
- move_x0 = float(value)
- def on_y_slider_move(value):
- global move_y0
- move_y0 = float(value)
- def on_z_slider_move(value):
- global move_z0
- move_z0 = float(value)
- def rotate_voxel_cube():
- global move_x, move_y, move_z
- move_x += (move_x0) % 360
- move_y += (move_y0) % 360
- move_z += (move_z0) % 360
- def print_current_angles():
- print(status_var.get())
- def reset():
- global angle_x, angle_y, angle_z, move_x, move_y, move_z, move_x0, move_y0, move_z0, angle
- angle_x = 0
- angle_y = 0
- angle_z = 0
- move_x, move_y, move_z = 0, 0, 0
- move_x0, move_y0, move_z0 = 0, 0, 0
- angle = 0
- x_slider_move.set(0)
- y_slider_move.set(0)
- z_slider_move.set(0)
- x_slider.set(0)
- y_slider.set(0)
- z_slider.set(0)
- def reset_move():
- global angle_x, angle_y, angle_z, move_x, move_y, move_z, move_x0, move_y0, move_z0, angle
- move_x, move_y, move_z = 0, 0, 0
- move_x0, move_y0, move_z0 = 0, 0, 0
- x_slider_move.set(0)
- y_slider_move.set(0)
- z_slider_move.set(0)
- def f_angle():
- global angle
- angle = (angle - 30) % 360
- def b_angle():
- global angle
- angle = (angle + 30) % 360
- ww = 600
- hh = 600
- cx = 600 // 2
- cy = 600 // 2
- root = tk.Tk()
- root.title("3D Voxel Animation")
- root.geometry(f"{1200}x{hh}+0+0")
- canvas = tk.Canvas(root, width=ww, height=hh, bg="black")
- canvas.pack(side=tk.RIGHT)
- control_frame = tk.Frame(root)
- control_frame.pack(side=tk.LEFT, fill=tk.Y)
- # Status Display
- status_var = tk.StringVar()
- status_label = tk.Label(control_frame, textvariable=status_var)
- status_label.pack()
- # Button Frame
- button_frame = tk.Frame(control_frame)
- button_frame.pack(side=tk.BOTTOM, fill=tk.X)
- speed = 1
- x_slider_move = tk.Scale(control_frame, from_=-speed, to=speed, orient=tk.VERTICAL, label="X", resolution=0.005)
- x_slider_move.pack(side=tk.LEFT, fill=tk.Y)
- y_slider_move = tk.Scale(control_frame, from_=-speed, to=speed, orient=tk.VERTICAL, label="Y", resolution=0.005)
- y_slider_move.pack(side=tk.LEFT, fill=tk.Y)
- z_slider_move = tk.Scale(control_frame, from_=-speed, to=speed, orient=tk.VERTICAL, label="Z", resolution=0.005)
- z_slider_move.pack(side=tk.LEFT, fill=tk.Y)
- x_slider_move.bind("<Motion>", lambda e: on_x_slider_move(x_slider_move.get()))
- y_slider_move.bind("<Motion>", lambda e: on_y_slider_move(y_slider_move.get()))
- z_slider_move.bind("<Motion>", lambda e: on_z_slider_move(z_slider_move.get()))
- # Cube Position Sliders
- x_slider = tk.Scale(control_frame, from_=0, to=360, orient=tk.VERTICAL, label="Cube X", resolution=5)
- x_slider.pack(side=tk.LEFT, fill=tk.Y)
- y_slider = tk.Scale(control_frame, from_=0, to=360, orient=tk.VERTICAL, label="Cube Y", resolution=5)
- y_slider.pack(side=tk.LEFT, fill=tk.Y)
- z_slider = tk.Scale(control_frame, from_=0, to=360, orient=tk.VERTICAL, label="Cube Z", resolution=5)
- z_slider.pack(side=tk.LEFT, fill=tk.Y)
- x_slider.bind("<Motion>", lambda e: on_x_slider_cube(x_slider.get()))
- y_slider.bind("<Motion>", lambda e: on_y_slider_cube(y_slider.get()))
- z_slider.bind("<Motion>", lambda e: on_z_slider_cube(z_slider.get()))
- angle_y_button = tk.Button(button_frame, text="Rotate Voxel Cube", command=lambda: rotate_voxel_cube())
- angle_y_button.pack(side=tk.LEFT)
- print_button = tk.Button(button_frame, text="Print Data", command=print_current_angles)
- print_button.pack(side=tk.LEFT)
- f_angle_button = tk.Button(button_frame, text="+30 Degrees", command=f_angle)
- f_angle_button.pack(side=tk.LEFT)
- b_angle_button = tk.Button(button_frame, text="-30 Degrees", command=b_angle)
- b_angle_button.pack(side=tk.LEFT)
- reset_button = tk.Button(button_frame, text="RESET ALL", command=reset)
- reset_button.pack(side=tk.LEFT)
- reset_button = tk.Button(button_frame, text="RESET MOVE", command=reset_move)
- reset_button.pack(side=tk.LEFT)
- reset()
- voxels = create_cube()
- while True:
- canvas.delete("all")
- rotate_voxel_cube()
- draw_grid_line(angle)
- for voxel in voxels:
- x, y, z = rotate_point(*voxel)
- draw_voxel(x, y, z)
- update_status()
- canvas.update()
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement