[英]How do I hide the faces of the cube that aren't facing forwards when I rotate the cube?
The code creates 3D coordinates for the cube and then displays them on the 2D screen but you can still see the back faces of the cube.该代码为立方体创建 3D 坐标,然后将它们显示在 2D 屏幕上,但您仍然可以看到立方体的背面。 I just want to tell the code not to draw the points that are behind the faces in the 3D coordinates.
我只想告诉代码不要在 3D 坐标中绘制面后面的点。
points = [(-1,-1,-1),(-1,-1,1),(-1,1,1),(-1,1,-1),
(1,-1,-1),(1,-1,1),(1,1,1),(1,1,-1), ]#coords for points
faces = [(3,0,4,7),(1,5,6,2),(2,1,0,3),(5,4,7,6),(3,2,6,7),(0,1,5,4)]
These are the coordinates of the points and which points should be joined to which这些是点的坐标,哪些点应该连接到哪些点
def flattenPoint(point):
(x, y, z) = (point[0], point[1], point[2])
xnew = x#x axis rotation
ynew = y * math.cos(rotatedanglex) - z * math.sin(rotatedanglex)
znew = y * math.sin(rotatedanglex) + z * math.cos(rotatedanglex)
xnew = znew * math.sin(rotatedangley) + xnew * math.cos(rotatedangley)
ynew = ynew #y axis rotation
znew = ynew * math.cos(rotatedangley) - xnew * math.sin(rotatedangley)
projectedY = int(height / 2 + ((ynew * distance) / (znew + distance)) * scale)
projectedX = int(width / 2 + ((xnew * distance) / (znew + distance)) * scale)
return (projectedX, projectedY, znew)
def createOutline(points):
a, b, c, d = points[0], points[1], points[2], points[3]
coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1]))
pygame.draw.polygon(screen, blue, coords, 1)
''' The FlattenPoint function rotates the 3D points and then turns them into 2D coordinates that are displayed. ''' FlattenPoint function 旋转 3D 点,然后将它们转换为显示的 2D 坐标。 '''
'''
def createFace(points):
a, b, c, d = points[0], points[1], points[2], points[3]
coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1]))
pygame.draw.polygon(screen, green, coords)
createFace joins up the 2D coordinates. createFace 连接了 2D 坐标。
def render(points, faces):
coords = []
for point in points:
coords.append(flattenPoint(point))
screen.fill(screencolour)
for face in faces:
createFace((coords[face[0]], coords[face[1]], coords[face[2]], coords[face[3]]))
for face in faces:#must draw outline after all the faces have been drawn
createOutline((coords[face[0]], coords[face[1]], coords[face[2]],coords[face[3]]))
''' '''
Compute the normal vector to of a face and cull the faces where the normal vector points away from the view.计算一个面的法线向量 to 并剔除法线向量指向远离视图的面。 The normal vector can be computed with the Cross product :
法线向量可以用叉积计算:
def cross(a, b):
return [a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]]
Use the cross product and cull the faces:使用叉积并剔除面:
def createFace(points):
a, b, c, d = points[0], points[1], points[2], points[3]
v1 = b[0]-a[0], b[1]-a[1], b[2]-a[2]
v2 = c[0]-a[0], c[1]-a[1], c[2]-a[2]
n = cross(v1, v2)
if n[2] < 0:
return
coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1]))
pygame.draw.polygon(screen, green, coords)
You have to ensure that the winding order of all the faces in counter clockwise.你必须确保所有面的缠绕顺序都是逆时针的。 See also Face Culling and Back-face culling
另见面剔除和背面剔除
Change the vertices and indices as follows:更改顶点和索引,如下所示:
points = [(-1,-1,-1),( 1,-1,-1), (1, 1,-1),(-1, 1,-1),
(-1,-1, 1),( 1,-1, 1), (1, 1, 1),(-1, 1, 1)]
faces = [(0,1,2,3),(5,4,7,6),(4,0,3,7),(1,5,6,2),(4,5,1,0),(3,2,6,7)]
However, I recommend to implement a depth test.但是,我建议实施深度测试。 See Pygame rotating cubes around axis and Does PyGame do 3d?
请参阅Pygame 围绕轴旋转立方体和PyGame 是否执行 3d? .
.
Complete example:完整示例:
import pygame
import math
points = [(-1,-1,-1),( 1,-1,-1), (1, 1,-1),(-1, 1,-1),
(-1,-1, 1),( 1,-1, 1), (1, 1, 1),(-1, 1, 1)]
faces = [(0,1,2,3),(5,4,7,6),(4,0,3,7),(1,5,6,2),(4,5,1,0),(3,2,6,7)]
def flattenPoint(point):
(x, y, z) = (point[0], point[1], point[2])
xnew = x#x axis rotation
ynew = y * math.cos(rotatedanglex) - z * math.sin(rotatedanglex)
znew = y * math.sin(rotatedanglex) + z * math.cos(rotatedanglex)
xnew = znew * math.sin(rotatedangley) + xnew * math.cos(rotatedangley)
ynew = ynew #y axis rotation
znew = ynew * math.cos(rotatedangley) - xnew * math.sin(rotatedangley)
projectedY = int(height / 2 + ((ynew * distance) / (znew + distance)) * scale)
projectedX = int(width / 2 + ((xnew * distance) / (znew + distance)) * scale)
return (projectedX, projectedY, znew)
def cross(a, b):
return [a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]]
def createOutline(points):
a, b, c, d = points[0], points[1], points[2], points[3]
v1 = b[0]-a[0], b[1]-a[1], b[2]-a[2]
v2 = c[0]-a[0], c[1]-a[1], c[2]-a[2]
n = cross(v1, v2)
if n[2] < 0:
return
coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1]))
pygame.draw.polygon(screen, blue, coords, 3)
def createFace(points):
a, b, c, d = points[0], points[1], points[2], points[3]
v1 = b[0]-a[0], b[1]-a[1], b[2]-a[2]
v2 = c[0]-a[0], c[1]-a[1], c[2]-a[2]
n = cross(v1, v2)
if n[2] < 0:
return
coords = ((b[0], b[1]), (a[0], a[1]), (d[0], d[1]),(c[0], c[1]))
pygame.draw.polygon(screen, green, coords)
def render(points, faces):
coords = []
for point in points:
coords.append(flattenPoint(point))
screen.fill(screencolour)
for face in faces:
createFace((coords[face[0]], coords[face[1]], coords[face[2]], coords[face[3]]))
for face in faces:#must draw outline after all the faces have been drawn
createOutline((coords[face[0]], coords[face[1]], coords[face[2]],coords[face[3]]))
pygame.init()
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
rotatedanglex = 0.0
rotatedangley = 0.0
width, height = screen.get_size()
distance = 200.0
scale = 75.0
green = (0, 255, 0)
blue = (0, 0, 255)
screencolour = (0, 0, 0)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill(0)
render(points, faces)
pygame.display.flip()
rotatedanglex += 0.01
rotatedangley += 0.02
pygame.quit()
exit()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.