繁体   English   中英

当我旋转立方体时,如何隐藏立方体的不朝前的面?

[英]How do I hide the faces of the cube that aren't facing forwards when I rotate the cube?

该代码为立方体创建 3D 坐标,然后将它们显示在 2D 屏幕上,但您仍然可以看到立方体的背面。 我只想告诉代码不要在 3D 坐标中绘制面后面的点。

输出图片

新输出

新输出2

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)]

这些是点的坐标,哪些点应该连接到哪些点

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)

''' 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 连接了 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]]))

'''

计算一个面的法线向量 to 并剔除法线向量指向远离视图的面。 法线向量可以用叉积计算:

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 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)

你必须确保所有面的缠绕顺序都是逆时针的。 见面剔除和背面剔除

更改顶点和索引,如下所示:

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)]

但是,我建议实施深度测试。 请参阅Pygame 围绕轴旋转立方体PyGame 是否执行 3d? .


完整示例:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM