gpt4 book ai didi

python - 近距离 3D 显示困惑

转载 作者:行者123 更新时间:2023-12-01 06:21:39 27 4
gpt4 key购买 nike

我复制了 YouTube 的一段代码,关于在 Python 中在屏幕上显示 3d 立方体,而不使用外部模块(如 PyOpenGL)。它工作得很好,但是当你进入两个立方体之间时,显示就会变得困惑。这是我的代码:

import pygame, sys, math, random

def rotate2d(pos, rad): x,y=pos; s,c = math.sin(rad),math.cos(rad); return x*c-y*s,y*c+x*s

class Cam:
def __init__(self, pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)

def events(self, event):
if event.type == pygame.MOUSEMOTION:
x, y = event.rel; x/=200; y/=200
self.rot[0]+=y; self.rot[1]+=x

def update(self, dt, key):
s = dt*10

if key[pygame.K_q]: self.pos[1]+=s
if key[pygame.K_e]: self.pos[1]-=s

x,y = s*math.sin(self.rot[1]),s*math.cos(self.rot[1])
if key[pygame.K_w]: self.pos[0]+=x; self.pos[2]+=y
if key[pygame.K_s]: self.pos[0]-=x; self.pos[2]-=y
if key[pygame.K_a]: self.pos[0]-=y; self.pos[2]+=x
if key[pygame.K_d]: self.pos[0]+=y; self.pos[2]-=x
if key[pygame.K_r]: self.pos[0]=0; self.pos[1]=0;\
self.pos[2]=-5; self.rot[0]=0; self.rot[1]=0


class Cube:
faces = (0,1,2,3),(4,5,6,7),(0,1,5,4),(2,3,7,6),(0,3,7,4),(1,2,6,5)
colors = (255,0,0),(255,128,0),(255,255,0),(255,255,255),(0,0,255),(0,255,0)
def __init__(self,pos=(0,0,0),color=None,v0=(-1,-1,-1),v1=(1,-1,-1),v2=(1,1,-1),v3=(-1,1,-1),v4=(-1,-1,1),v5=(1,-1,1),v6=(1,1,1),v7=(-1,1,1)):
if color != None:
if len(color) == 3 or len(color) == 4:
self.colors = tuple((color for i in range(6)))
if len(color) == 6:
self.colors = color
self.vertices = (v0,v1,v2,v3,v4,v5,v6,v7)
x,y,z = pos
self.verts = [(x+X/2,y+Y/2,z+Z/2) for X,Y,Z in self.vertices]


pygame.init()
w,h = 400,400; cx,cy = w//2, h//2
screen = pygame.display.set_mode((w,h))
clock = pygame.time.Clock()
cam = Cam((0,0,-5))
pygame.event.get(); pygame.mouse.get_rel()
pygame.mouse.set_visible(0); pygame.event.set_grab(1)
occupied = []

cube1 = Cube((0,0,0))
cube2 = Cube((0,0,2))
objects = [cube1, cube2]

while True:
dt = clock.tick()/1000

for event in pygame.event.get():
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: pygame.quit(); sys.exit()
cam.events(event)

screen.fill((0,0,0))

face_list = []; face_color = []; depth = []

for obj in objects:

vert_list = []; screen_coords = []
for x,y,z in obj.verts:
x-= cam.pos[0]; y-=cam.pos[1];z-=cam.pos[2]
x,z = rotate2d((x,z),cam.rot[1])
y,z = rotate2d((y,z),cam.rot[0])
vert_list += [(x,y,z)]

f = 200/z
x,y = x*f,y*f
screen_coords+=[(cx+int(x),cy+int(y))]

for f in range(len(obj.faces)):
face = obj.faces[f]

on_screen = False
for i in face:
x,y = screen_coords[i]
if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True; break

if on_screen:
coords = [screen_coords[i] for i in face]
face_list += [coords]
face_color += [obj.colors[f]]
depth += [sum(sum(vert_list[j][i]**2 for i in range(3)) for j in face) / len(face)]

order = sorted(range(len(face_list)),key=lambda i:depth[i],reverse=1)

for i in order:
try: pygame.draw.polygon(screen,face_color[i],face_list[i])
except: pass

key = pygame.key.get_pressed()
pygame.display.flip()
cam.update(dt,key)

当您尝试在两个多维数据集之间导航时,会发生以下情况: Example of error

有人可以建议对代码进行编辑,以防止当 cam.pos 靠近立方体时立方体变形吗?

最佳答案

当一个面(原始面,立方体的一侧)的一部分位于眼睛位置的后面而另一部分位于眼睛位置的前面时,应用程序无法正确绘制几何图形。如果变换后的 z 坐标 (vert_list += [(x,y,z)]) 对于某些顶点为正,对于形成图元(面)的其他一些顶点为负,则会发生这种情况。

如果您跳过所有面,其中至少一个 z 坐标为负(在眼睛后面),您可以轻松测试该行为:

while True:
# [...]

for obj in objects:
# [...]

for f in range(len(obj.faces)):
face = obj.faces[f]

#on_screen = False
#for i in face:
# x,y = screen_coords[i]
# if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True; break

# draw a face if any projected coordinate (x, y) is in the viewing volume
on_screen = False
for i in face:
x,y = screen_coords[i]
if x>0 and x<w and y>0 and y<h: on_screen = True; break
# skip a face if NOT ALL z coordinates are positive
if on_screen:
on_screen = all([vert_list[i][2]>0 for i in face])

if on_screen:
# [...]

<小时/>

可以通过在假设的近平面处裁剪几何体来解决该问题。请参阅Viewing frustum :

while True:
# [...]

for obj in objects:
# [...]

for f in range(len(obj.faces)):
face = obj.faces[f]

on_screen = False
for i in face:
x,y = screen_coords[i]
if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True; break

# clip geometry at near plane
if on_screen:
near = 0.01
for i in face:
if vert_list[i][2]<0:
x, y, z = vert_list[i]
nearscale = 200/near
x,y = x*nearscale,y*nearscale
screen_coords[i] = (cx+int(x),cy+int(y))

if on_screen:
coords = [screen_coords[i] for i in face]
face_list += [coords]
face_color += [obj.colors[f]]
depth += [sum(sum(vert_list[j][i]**2 for i in range(3)) for j in face) / len(face)]

关于python - 近距离 3D 显示困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60330496/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com