我只有一点使用海龟的经验。
形状无意中看起来像一种视错觉,这不是我想要的效果。我不知道最好的方法是什么。我想用阴影添加一些深度,但我不知道这是否可能。任何建议将不胜感激。
import turtle
import math
# Setup
screen = turtle.Screen()
screen.bgcolor("light blue") # Set background
screen.title("Spinning Diamond")
t = turtle.Turtle()
t.speed(0)
t.hideturtle()
# vertices
vertices = [
[0, 0, 150], # Top vertex
[math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, 50],
[math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, 50],
[math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, 50],
[math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, 50],
[math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, 50],
[math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, -50],
[math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, -50],
[math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, -50],
[math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, -50],
[math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, -50],
[0, 0, -150] # Bottom vertex
]
faces = [
[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1],
[6, 7, 11], [7, 8, 11], [8, 9, 11], [9, 10, 11], [10, 6, 11],
[1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 5, 10, 9], [5, 1, 6, 10]
]
# Define colors
colors = [
"red", "green", "blue", "yellow", "cyan",
"magenta", "orange", "purple", "lime", "pink",
"brown", "gray", "violet", "navy", "gold"
]
# Rotate around X-axis
def rotateX(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
y = point[1] * cosA - point[2] * sinA
z = point[1] * sinA + point[2] * cosA
return [point[0], y, z]
# Rotate around Y-axis
def rotateY(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
x = point[0] * cosA + point[2] * sinA
z = -point[0] * sinA + point[2] * cosA
return [x, point[1], z]
# Rotate around Z-axis
def rotateZ(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
x = point[0] * cosA - point[1] * sinA
y = point[0] * sinA + point[1] * cosA
return [x, y, point[2]]
def project(point):
distance = 300
factor = distance / (distance - point[2])
x = point[0] * factor
y = point[1] * factor
return [x, y]
# Draw Shape
def draw_polyhedron():
t.clear()
# Rotation
rotated_vertices = [rotateX(rotateY(rotateZ(v, angleZ), angleY), angleX) for v in vertices]
projected_vertices = [project(v) for v in rotated_vertices]
# Calculate the avg Z value
face_depths = []
for i, face in enumerate(faces):
z_sum = sum(rotated_vertices[vertex][2] for vertex in face)
face_depths.append((z_sum / len(face), i))
# Sort depth
face_depths.sort(reverse=True)
# Draw faces
for depth, i in face_depths:
face = faces[i]
t.penup()
t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
t.pendown()
t.begin_fill()
t.color(colors[i % len(colors)])
for vertex in face:
t.goto(projected_vertices[vertex][0], projected_vertices[vertex][1])
t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
t.end_fill()
screen.update()
# rotation angles
angleX = 0
angleY = 0
angleZ = 0
# Animation loop
def animate():
global angleX, angleY, angleZ
angleX += 2
angleY += 3
angleZ += 1
draw_polyhedron()
screen.ontimer(animate, 50)
# Initialize animation
screen.tracer(0)
animate()
screen.mainloop()
你可以通过在代码中实现简单的光照模型来为五角星形反棱镜添加深度。下面是如何操作:
- 了解光照模型: 我们将使用一种名为环境光和漫反射照明的基本光照模型。这涉及到根据表面朝向假想光源的方向来计算表面的亮度。
- 计算表面法线: 对于每个面,我们需要计算表面法线向量。该向量垂直于表面,指示表面的“朝向”。
- 计算漫反射光: 我们将使用光向量和表面法线之间的点积来计算每个面的光照量。点积表示两个向量之间的对齐程度。如果法线直接指向光线,则表面会更亮。
- 应用阴影: 为了简单起见,我们将假设一个恒定的环境光照水平,并且不考虑阴影。
下面是更新后的代码:
import turtle
import math
# Setup
screen = turtle.Screen()
screen.bgcolor("light blue")
screen.title("Spinning Diamond")
t = turtle.Turtle()
t.speed(0)
t.hideturtle()
# vertices
vertices = [
[0, 0, 150],
[math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, 50],
[math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, 50],
[math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, 50],
[math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, 50],
[math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, 50],
[math.cos(2 * math.pi / 5) * 100, math.sin(2 * math.pi / 5) * 100, -50],
[math.cos(4 * math.pi / 5) * 100, math.sin(4 * math.pi / 5) * 100, -50],
[math.cos(6 * math.pi / 5) * 100, math.sin(6 * math.pi / 5) * 100, -50],
[math.cos(8 * math.pi / 5) * 100, math.sin(8 * math.pi / 5) * 100, -50],
[math.cos(10 * math.pi / 5) * 100, math.sin(10 * math.pi / 5) * 100, -50],
[0, 0, -150]
]
faces = [
[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1],
[6, 7, 11], [7, 8, 11], [8, 9, 11], [9, 10, 11], [10, 6, 11],
[1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 5, 10, 9], [5, 1, 6, 10]
]
# 定义颜色
colors = [
"red", "green", "blue", "yellow", "cyan",
"magenta", "orange", "purple", "lime", "pink",
"brown", "gray", "violet", "navy", "gold"
]
# 光照方向
light_dir = [1, 1, 1] # 假设光源在该方向上
# 旋转矩阵
def rotateX(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
y = point[1] * cosA - point[2] * sinA
z = point[1] * sinA + point[2] * cosA
return [point[0], y, z]
def rotateY(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
x = point[0] * cosA + point[2] * sinA
z = -point[0] * sinA + point[2] * cosA
return [x, point[1], z]
def rotateZ(point, angle):
rad = math.radians(angle)
cosA = math.cos(rad)
sinA = math.sin(rad)
x = point[0] * cosA - point[1] * sinA
y = point[0] * sinA + point[1] * cosA
return [x, y, point[2]]
# 投影函数
def project(point):
distance = 300
factor = distance / (distance - point[2])
x = point[0] * factor
y = point[1] * factor
return [x, y]
# 计算法向量
def calculate_normal(face, vertices):
p1 = vertices[face[0]]
p2 = vertices[face[1]]
p3 = vertices[face[2]]
v1 = [p2[i] - p1[i] for i in range(3)]
v2 = [p3[i] - p1[i] for i in range(3)]
normal = [
v1[1] * v2[2] - v1[2] * v2[1],
v1[2] * v2[0] - v1[0] * v2[2],
v1[0] * v2[1] - v1[1] * v2[0]
]
return normalize(normal)
# 归一化向量
def normalize(v):
norm = math.sqrt(sum(i * i for i in v))
return [i / norm for i in v]
# 计算点积
def dot_product(v1, v2):
return sum(v1[i] * v2[i] for i in range(3))
# 绘制形状
def draw_polyhedron():
t.clear()
# 旋转
rotated_vertices = [rotateX(rotateY(rotateZ(v, angleZ), angleY), angleX) for v in vertices]
projected_vertices = [project(v) for v in rotated_vertices]
# 计算平均 Z 值
face_depths = []
for i, face in enumerate(faces):
z_sum = sum(rotated_vertices[vertex][2] for vertex in face)
face_depths.append((z_sum / len(face), i))
# 按深度排序
face_depths.sort(reverse=True)
# 绘制面
for depth, i in face_depths:
face = faces[i]
normal = calculate_normal(face, rotated_vertices) # 计算法向量
light_intensity = max(0, dot_product(normal, light_dir)) # 计算光照强度
t.penup()
t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
t.pendown()
t.begin_fill()
base_color = colors[i % len(colors)]
r, g, b = turtle.colormode(255)[base_color]
shaded_color = (int(r * light_intensity), int(g * light_intensity), int(b * light_intensity))
t.color(shaded_color)
for vertex in face:
t.goto(projected_vertices[vertex][0], projected_vertices[vertex][1])
t.goto(projected_vertices[face[0]][0], projected_vertices[face[0]][1])
t.end_fill()
screen.update()
# 旋转角度
angleX = 0
angleY = 0
angleZ = 0
# 动画循环
def animate():
global angleX, angleY, angleZ
angleX += 2
angleY += 3
angleZ += 1
draw_polyhedron()
screen.ontimer(animate, 50)
# 初始化动画
screen.tracer(0)
animate()
screen.mainloop()
在这个改进版本中,我们添加了计算法向量和基于光照方向和表面法线之间角度的漫反射分量的函数。这将创建更逼真的 3D 效果,从而增强深度。
标签:python,shapes,python-turtle From: 78774647