Python Pygame绕轴旋转立方体
我一直在玩旋转立方体的例子。 我已经生成了2个立方体,它们应该绕Y轴旋转。然而,它似乎没有像预期的那样工作,我也不知道它的问题是什么 下面是一个工作代码示例:Python Pygame绕轴旋转立方体,python,pygame,geometry,Python,Pygame,Geometry,我一直在玩旋转立方体的例子。 我已经生成了2个立方体,它们应该绕Y轴旋转。然而,它似乎没有像预期的那样工作,我也不知道它的问题是什么 下面是一个工作代码示例: import sys import math import pygame from pygame.math import Vector3 from enum import Enum class Color(Enum): BLACK = (0, 0, 0) SILVER = (192,192,192) class
import sys
import math
import pygame
from pygame.math import Vector3
from enum import Enum
class Color(Enum):
BLACK = (0, 0, 0)
SILVER = (192,192,192)
class Cube():
def __init__(self, vectors, screen_width, screen_height, initial_angle=25):
self._vectors = vectors
self._angle = initial_angle
self._screen_width = screen_width
self._screen_height = screen_height
# Define the vectors that compose each of the 6 faces
self._faces = [(0,1,2,3),
(1,5,6,2),
(5,4,7,6),
(4,0,3,7),
(0,4,5,1),
(3,2,6,7)]
self._setup_initial_positions(initial_angle)
def _setup_initial_positions(self, angle):
tmp = []
for vector in self._vectors:
rotated_vector = vector.rotate_x(angle).rotate_y(angle)#.rotateZ(self.angle)
tmp.append(rotated_vector)
self._vectors = tmp
def transform_vectors(self, new_angle):
# It will hold transformed vectors.
transformed_vectors = []
for vector in self._vectors:
# Rotate the point around X axis, then around Y axis, and finally around Z axis.
mod_vector = vector.rotate_y(new_angle)
# Transform the point from 3D to 2D
mod_vector = self._project(mod_vector, self._screen_width, self._screen_height, 256, 4)
# Put the point in the list of transformed vectors
transformed_vectors.append(mod_vector)
return transformed_vectors
def _project(self, vector, win_width, win_height, fov, viewer_distance):
factor = fov / (viewer_distance + vector.z)
x = vector.x * factor + win_width / 2
y = -vector.y * factor + win_height / 2
return Vector3(x, y, vector.z)
def calculate_average_z(self, vectors):
avg_z = []
for i, face in enumerate(self._faces):
# for each point of a face calculate the average z value
z = (vectors[face[0]].z +
vectors[face[1]].z +
vectors[face[2]].z +
vectors[face[3]].z) / 4.0
avg_z.append([i, z])
return avg_z
def get_face(self, index):
return self._faces[index]
def create_polygon(self, face, transformed_vectors):
return [(transformed_vectors[face[0]].x, transformed_vectors[face[0]].y),
(transformed_vectors[face[1]].x, transformed_vectors[face[1]].y),
(transformed_vectors[face[2]].x, transformed_vectors[face[2]].y),
(transformed_vectors[face[3]].x, transformed_vectors[face[3]].y),
(transformed_vectors[face[0]].x, transformed_vectors[face[0]].y)]
class Simulation:
def __init__(self, win_width=640, win_height=480):
pygame.init()
self.screen = pygame.display.set_mode((win_width, win_height))
self.clock = pygame.time.Clock()
cube = Cube([
Vector3(0, 0.5, -0.5),
Vector3(0.5, 0.5, -0.5),
Vector3(0.5, 0, -0.5),
Vector3(0, 0, -0.5),
Vector3(0, 0.5, 0),
Vector3(0.5, 0.5, 0),
Vector3(0.5, 0, 0),
Vector3(0, 0, 0)
], win_width, win_height)
cube2 = Cube([
Vector3(0.5, 0.5, -0.5),
Vector3(1, 0.5, -0.5),
Vector3(1, 0, -0.5),
Vector3(0.5, 0, -0.5),
Vector3(0.5, 0.5, 0),
Vector3(1, 0.5, 0),
Vector3(1, 0, 0),
Vector3(0.5, 0, 0)
], win_width, win_height)
self._angle = 30
self._cubes = [cube, cube2]
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.clock.tick(50)
self.screen.fill(Color.BLACK.value)
for cube in self._cubes:
transformed_vectors = cube.transform_vectors(self._angle)
avg_z = cube.calculate_average_z(transformed_vectors)
# Draw the faces using the Painter's algorithm:
# Distant faces are drawn before the closer ones.
for avg_z in sorted(avg_z, key=lambda x: x[1], reverse=True):
face_index = avg_z[0]
face = cube._faces[face_index]
pointlist = cube.create_polygon(face, transformed_vectors)
pygame.draw.polygon(self.screen, Color.SILVER.value,pointlist)
pygame.draw.polygon(self.screen, Color.BLACK.value, pointlist, 3)
# break
self._angle += 1
pygame.display.flip()
if __name__ == "__main__":
Simulation().run()
在本例中,两个立方体都应围绕Y轴旋转。对于未来,我希望有一个解决方案,使它们可以绕任何轴旋转。仅按深度对每个立方体的面进行单独排序是不够的。必须按深度对整个场景中所有对象的面进行排序 创建一个元组列表,该列表由面的投影变换点和平均深度z值组成: 多边形=[] 对于自身中的多维数据集。\u多维数据集: 变换向量=立方体。变换向量自身。\角度 avg_z=立方。计算平均值_z变换向量 对于平均值中的z: 面_指数=z[0] 面=立方体。_面[面索引] 点列表=立方体。创建多边形面,变换的向量 polygons.appendpointlist,z[1] 按反向排序顺序绘制所有对象的面: 对于分类多边形中的多边形,key=lambda x:x[1],reverse=True: pygame.draw.polygonself.screen,Color.SILVER.value,poly[0] pygame.draw.polygonself.screen,Color.BLACK.value,poly[0],3 最简单的例子: 输入数学 导入pygame def投影矢量,w,h,fov,距离: 因子=math.atanfov/2*math.pi/180/距离+向量.z x=矢量。x*系数*w+w/2 y=-vector.y*因子*w+h/2 返回pygame.math.Vector3x,y,vector.z def rotate_垂直顶点、角度、轴: 返回[v.rotateangle,顶点中v的轴] def scale_垂直顶点,s: 返回[pygame.math.Vector3v[0]*s[0],v[1]*s[1],v[2]*s[2]表示顶点中的v] def translate_vertices顶点,t: 返回[v+pygame.math.Vector3t,用于顶点中的v] def投影垂直顶点,w,h,fov,距离: 返回[projectv,w,h,fov,顶点中v的距离] 类别网格: 定义初始自身、顶点、面: self._顶点=[pygame.math.Vector3v代表顶点中的v] self.\uu faces=面 def旋转自身、角度、轴: self.\uuu顶点=旋转\u顶点self.\uu顶点、角度、轴 def scaleself,s: self.\u顶点=缩放\u顶点self.\u顶点,s def translateself,t: self.\u顶点=平移\u顶点self.\u顶点,t def计算平均值,顶点: 返回[i,sum[顶点[j].z表示f中的j]/lenf表示f中的i,f.\uu面] def get_faceself,索引: 返回自我。\u面[索引] def get_Verticself: 返回自我 def创建_多边形自身、面、顶点: 返回[*面,面[0]]中的[顶点[i].x,顶点[i].y代表i 课堂场景: 定义初始自我、视野、距离: self.meshes=mehses self.fov=fov self.distance=距离 self.euler_角度=[0,0,0] def transform_verticself,顶点,宽度,高度: 变换的顶点=顶点 轴列表=[1,0,0,0,1,0,0,0,0,1] 对于角度,反转列表中的轴ziplistself.euler_角度,轴列表: 变换顶点=旋转顶点变换顶点、角度、轴 变换顶点=投影顶点变换顶点、宽度、高度、self.fov、self.distance 返回变换的顶点 def drawself,表面: 多边形=[] 对于self.mesh中的网格: transformed_顶点=self.transform_verticesmesh.get_顶点,*surface.get_大小 avg_z=网格。计算_平均值_z变形的_顶点 对于平均值中的z: 对于sortedavg_z中的z,key=lambda x:x[1],reverse=True: 点列表=网格。创建多边形网格。获取面[0],变换顶点 polygons.appendpointlist,z[1] pygame.draw.polygonsurface,128、128、192,点列表 pygame.draw.polygonsurface,0,0,0,点列表,3 对于分类多边形中的多边形,key=lambda x:x[1],reverse=True: pygame.draw.polygonsurface,128,128,192,poly[0] pygame.draw.polygonsurface,0,0,0,poly[0],3 顶点=[-1,-1,1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,1,1,-1,1,-1,1,-1] 面=[0,1,2,3,1,5,6,2,5,4,7,6,4,0,3,7,3,2,6,7,1,0,4,5] 多维数据集原点=[-1,-1,0,0,-1,0,1,-1,0,0,1,1,0,0,1,0,1,0,-1,1,0,-1,0,-1,0,0] 网格=[] 对于多维数据集中的原点,请执行以下操作: 立方体=网格顶点、面 立方体.比例0.5,0.5,0.5 多维数据集 附加立方体网格 场景=场景场景场景,90,5 pygame.init window=pygame.display.set_mode400300 clock=pygame.time.clock 运行=真 运行时: 时钟滴答滴答 对于pygame.event.get中的事件: 如果event.type==pygame.QUIT: 运行=错误 window.fill255、255、255 场景.拉窗 场景.欧拉角[1]+=1 pygame.display.flip pyg 退出