微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

picture of the output

new output

new output2

points = [(-1,-1,-1),(-1,1),1,(1,]#coords for points

faces = [(3,4,7),5,6,2),(2,3),(5,7,6),(3,2,(0,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 函数旋转 3D 点,然后将它们转换为显示的 2D 坐标。 '''

def createFace(points):
    a,green,coords)
    

createFace 连接二维坐标。

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

'''

解决方法

计算一个面的法向量 to 并剔除法向量指向远离视图的面。法向量可以用 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]]

使用叉积并剔除面:

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)

你必须确保所有面的缠绕顺序都是逆时针的。另见Face CullingBack-face culling

按如下方式更改顶点和索引:

points = [(-1,-1,-1),( 1,(1,1,(-1,1),1)]

faces = [(0,2,3),(5,4,7,6),(4,3,7),5,6,2),0),(3,7)]

但是,我建议实施深度测试。请参阅 Pygame rotating cubes around axisDoes PyGame do 3d?


完整示例:

import pygame
import math

points = [(-1,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,a[0]*b[1] - a[1]*b[0]]

def createOutline(points):
    a,blue,coords,3)

def createFace(points):
    a,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[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,255)
screencolour = (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()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。