p99*_*ill 2 python theory 3d pygame shapes
如何使用 pygame 创建和渲染 3D 形状而不使用任何其他模块。我想创建自己的简单 3D 引擎。我可以画一个 3D 盒子,只是不知道如何调整线条的长度和位置,以在旋转盒子时给出 3D 效果。
我很难理解physics旋转物体时的阴影、深度感知和照明
假设我有一个盒子:
class box1():
x=100
y=100
z=100
size = 150 #length for distance between each point
point1 = 0,0,0 # top left front
point2 = 0,0,0 # top right front
point3 = 0,0,0 # bottom left front
point4 = 0,0,0 # bottom right front
point5 = 0,0,0 # top left back
point6 = 0,0,0 # top right back
point7 = 0,0,0 # bottom left back
point8 = 0,0,0 # bottom right back
def set_points():
x=box1.x
y=box1.y
z=box1.z
size = box1.size
#this part sets all the points x,y,x co-cords at the correct locations
# _____ 4____6
# |\____\ 1____2
# | | | Middle [x,y,z]
# |_| ` | 7____8
# \|____| 3____4
#
# the +50 is just a test to show the 'offset' of the behind points
box1.point1 = [x-(size/2),y-(size/2),z-(size/2)] # top left front
box1.point2 = [x+(size/2),y-(size/2),z-(size/2)] # top right front
box1.point3 = [x-(size/2),y+(size/2),z-(size/2)] # bottom left front
box1.point4 = [x+(size/2),y+(size/2),z-(size/2)] # bottom right front
box1.point5 = [x-(size/2)+50,y-(size/2)+50,z+(size/2)] # top left back
box1.point6 = [x+(size/2)+50,y-(size/2)+50,z+(size/2)] # top right back
box1.point7 = [x-(size/2)+50,y+(size/2)+50,z+(size/2)] # bottom left back
box1.point8 = [x+(size/2)+50,y+(size/2)+50,z+(size/2)] # bottom right back
camara_pos = [20,20,20] # I don't know how to make the points based off this
camara_angle = [45,0,0] # or this
while True:
set_points()
g.DISPLAYSURF.fill((0,0,0))
for event in pygame.event.get():
if event.type == QUIT:
exit()
#draws all the lines connecting all the points .
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point1[0],box1.point1[1]),(box1.point2[0],box1.point2[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point3[0],box1.point3[1]),(box1.point4[0],box1.point4[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point2[0],box1.point2[1]),(box1.point4[0],box1.point4[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point1[0],box1.point1[1]),(box1.point3[0],box1.point3[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point5[0],box1.point5[1]),(box1.point6[0],box1.point6[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point7[0],box1.point7[1]),(box1.point8[0],box1.point8[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point6[0],box1.point6[1]),(box1.point8[0],box1.point8[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point5[0],box1.point5[1]),(box1.point7[0],box1.point7[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point1[0],box1.point1[1]),(box1.point5[0],box1.point5[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point2[0],box1.point2[1]),(box1.point6[0],box1.point6[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point3[0],box1.point3[1]),(box1.point7[0],box1.point7[1]))
pygame.draw.line(g.DISPLAYSURF, (128,128,128), (box1.point4[0],box1.point4[1]),(box1.point8[0],box1.point8[1]))
pygame.display.update()
Run Code Online (Sandbox Code Playgroud)

谁能解释一下这个理论吗?谁能告诉我一些代码来计算分数?
您需要了解的唯一魔法称为“旋转矩阵”。
\n\n如果在这样的矩阵和向量之间执行乘法,就会得到旋转的向量。
\n\n有了这些信息(即复制维基百科的 3D 旋转矩阵之后),我最终得到了这个好东西:
\n\nimport pygame\nfrom numpy import array\nfrom math import cos, sin\n\n\n######################\n# #\n# math section #\n# #\n######################\n\nX, Y, Z = 0, 1, 2\n\n\ndef rotation_matrix(\xce\xb1, \xce\xb2, \xce\xb3):\n """\n rotation matrix of \xce\xb1, \xce\xb2, \xce\xb3 radians around x, y, z axes (respectively)\n """\n s\xce\xb1, c\xce\xb1 = sin(\xce\xb1), cos(\xce\xb1)\n s\xce\xb2, c\xce\xb2 = sin(\xce\xb2), cos(\xce\xb2)\n s\xce\xb3, c\xce\xb3 = sin(\xce\xb3), cos(\xce\xb3)\n return (\n (c\xce\xb2*c\xce\xb3, -c\xce\xb2*s\xce\xb3, s\xce\xb2),\n (c\xce\xb1*s\xce\xb3 + s\xce\xb1*s\xce\xb2*c\xce\xb3, c\xce\xb1*c\xce\xb3 - s\xce\xb3*s\xce\xb1*s\xce\xb2, -c\xce\xb2*s\xce\xb1),\n (s\xce\xb3*s\xce\xb1 - c\xce\xb1*s\xce\xb2*c\xce\xb3, c\xce\xb1*s\xce\xb3*s\xce\xb2 + s\xce\xb1*c\xce\xb3, c\xce\xb1*c\xce\xb2)\n )\n\n\nclass Physical:\n def __init__(self, vertices, edges):\n """\n a 3D object that can rotate around the three axes\n :param vertices: a tuple of points (each has 3 coordinates)\n :param edges: a tuple of pairs (each pair is a set containing 2 vertices\' indexes)\n """\n self.__vertices = array(vertices)\n self.__edges = tuple(edges)\n self.__rotation = [0, 0, 0] # radians around each axis\n\n def rotate(self, axis, \xce\xb8):\n self.__rotation[axis] += \xce\xb8\n\n @property\n def lines(self):\n location = self.__vertices.dot(rotation_matrix(*self.__rotation)) # an index->location mapping\n return ((location[v1], location[v2]) for v1, v2 in self.__edges)\n\n\n######################\n# #\n# gui section #\n# #\n######################\n\n\nBLACK, RED = (0, 0, 0), (255, 128, 128)\n\n\nclass Paint:\n def __init__(self, shape, keys_handler):\n self.__shape = shape\n self.__keys_handler = keys_handler\n self.__size = 450, 450\n self.__clock = pygame.time.Clock()\n self.__screen = pygame.display.set_mode(self.__size)\n self.__mainloop()\n\n def __fit(self, vec):\n """\n ignore the z-element (creating a very cheap projection), and scale x, y to the coordinates of the screen\n """\n # notice that len(self.__size) is 2, hence zip(vec, self.__size) ignores the vector\'s last coordinate\n return [round(70 * coordinate + frame / 2) for coordinate, frame in zip(vec, self.__size)]\n\n def __handle_events(self):\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n exit()\n self.__keys_handler(pygame.key.get_pressed())\n\n def __draw_shape(self, thickness=4):\n for start, end in self.__shape.lines:\n pygame.draw.line(self.__screen, RED, self.__fit(start), self.__fit(end), thickness)\n\n def __mainloop(self):\n while True:\n self.__handle_events()\n self.__screen.fill(BLACK)\n self.__draw_shape()\n pygame.display.flip()\n self.__clock.tick(40)\n\n\n######################\n# #\n# main start #\n# #\n######################\n\n\ndef main():\n from pygame import K_q, K_w, K_a, K_s, K_z, K_x\n\n cube = Physical( # 0 1 2 3 4 5 6 7\n vertices=((1, 1, 1), (1, 1, -1), (1, -1, 1), (1, -1, -1), (-1, 1, 1), (-1, 1, -1), (-1, -1, 1), (-1, -1, -1)),\n edges=({0, 1}, {0, 2}, {2, 3}, {1, 3},\n {4, 5}, {4, 6}, {6, 7}, {5, 7},\n {0, 4}, {1, 5}, {2, 6}, {3, 7})\n )\n\n counter_clockwise = 0.05 # radians\n clockwise = -counter_clockwise\n\n params = {\n K_q: (X, clockwise),\n K_w: (X, counter_clockwise),\n K_a: (Y, clockwise),\n K_s: (Y, counter_clockwise),\n K_z: (Z, clockwise),\n K_x: (Z, counter_clockwise),\n }\n\n def keys_handler(keys):\n for key in params:\n if keys[key]:\n cube.rotate(*params[key])\n\n pygame.init()\n pygame.display.set_caption(\'Control - q,w : X a,s : Y z,x : Z\')\n Paint(cube, keys_handler)\n\nif __name__ == \'__main__\':\n main()\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,我确实使用 NumPy 模块进行矩阵乘法(并使用数学进行三角函数);我假设“没有其他模块”是指“没有任何 3D 库”。\n无论如何,您可以实现自己的矩阵乘法函数并使用泰勒级数计算 sin\\cos,但这是完全没有必要的。
\n