向后看时出现 3d 渲染错误

3d rendering error whilst looking backwards

前几天在python(乌龟)做了一个3d体素渲染引擎。一切似乎都进行得很顺利,直到你在一个物体前面 360 度转身。该对象将在 y 轴上镜像显示。我通过设置你的 y 旋转来解决它,但该修复只适用于一个视角。没有任何控制台错误,所以我无法确定渲染错误的位置。我希望我有更多信息来帮助定位问题。

from turtle import*
from time import*
from math import*
wn=Screen()
speed(0)
ht()
pu()
wn.tracer(0,0)
fov=200
xoff=0
yoff=0
zoff=0
camx=0
camy=0
camz=-105
xrot=0
yrot=0
zrot=0
jvel=0
onground=False
def goto3d(x,y,z):
  rotxx=x
  rotxy=y*cos(xrot)-z*sin(xrot)
  rotxz=y*sin(xrot)+z*cos(xrot)
  rotyx=rotxx*cos(yrot)+rotxz*sin(yrot)
  rotyy=rotxy
  rotyz=rotxz*cos(yrot)-rotxx*sin(yrot)
  rotzx=rotyx*cos(zrot)-rotyy*sin(zrot)
  rotzy=rotyx*sin(zrot)+rotyy*cos(zrot)
  rotzz=rotyz
  transx=rotzx-xoff
  transy=rotzy-yoff
  transz=rotzz-zoff
  newx=fov*transx/transz
  newy=fov*transy/transz
  if newx<=-200 or newy<=-200 or newx>=200 or newy>=200:
    pencolor('black')
  else:
    goto(newx,newy)
def cube(x,y,z):
  z-=100
  pu()
  goto3d((-1+x)-camx,(-1+y)-camy,(-1+z)-camz)
  pd()
  goto3d((-1+x)-camx,(1+y)-camy,(-1+z)-camz)
  goto3d((1+x)-camx,(1+y)-camy,(-1+z)-camz)
  goto3d((1+x)-camx,(-1+y)-camy,(-1+z)-camz)
  goto3d((-1+x)-camx,(-1+y)-camy,(-1+z)-camz)
  pu()
  goto3d((-1+x)-camx,(1+y)-camy,(-1+z)-camz)
  pd()
  goto3d((-1+x)-camx,(1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(1+y)-camy,(-1+z)-camz)
  pu()
  goto3d((-1+x)-camx,(-1+y)-camy,(-1+z)-camz)
  pd()
  goto3d((-1+x)-camx,(-1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(-1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(-1+y)-camy,(1+z)-camz)
  goto3d((1+x)-camx,(-1+y)-camy,(-1+z)-camz)
  pu()
  goto3d((-1+x)-camx,(1+y)-camy,(1+z)-camz)
  pd()
  goto3d((-1+x)-camx,(-1+y)-camy,(1+z)-camz)
  pu()
  goto3d((1+x)-camx,(1+y)-camy,(1+z)-camz)
  pd()
  goto3d((1+x)-camx,(-1+y)-camy,(1+z)-camz)
def black():
  pencolor('black')
  pu()
  goto(-400,-400)
  pd()
  begin_fill()
  goto(-200,200)
  goto(200,200)
  goto(200,-200)
  end_fill()
def w():
  global camz
  global camx
  camz+=.3*cos(yrot)
  camx+=-1*.3*sin(yrot)
def a():
  global camz
  global camx
  camz+=-1*.3*sin(yrot)
  camx+=-1*.3*cos(yrot)
def s():
  global camz
  global camx
  camz+=-1*.3*cos(yrot)
  camx+=.3*sin(yrot)
def d():
  global camz
  global camx
  camz+=.3*sin(yrot)
  camx+=.3*cos(yrot)
def left():
  global yrot
  yrot+=pi/50
def right():
  global yrot
  yrot-=pi/50
def jump():
  global jvel
  if onground==True:
    jvel=.3
wn.onkey(w,'w')
wn.onkey(a,'a')
wn.onkey(s,'s')
wn.onkey(d,'d')
wn.onkey(left,'Left')
wn.onkey(right,'Right')
wn.onkey(jump,'Space')
wn.listen()
def bush(x,y,z):
  pencolor('darkgreen')
  cube(0+x,0+y,0+z)
  cube(2+x,0+y,0+z)
  cube(2+x,2+y,0+z)
def tree(x,y,z):
  pencolor('brown')
  cube(0+x,0+y,0+z)
  cube(0+x,2+y,0+z)
  pencolor('green')
  cube(0+x,4+y,0+z)
  cube(0+x,6+y,0+z)
  cube(2+x,4+y,0+z)
  cube(-2+x,4+y,0+z)
  cube(0+x,4+y,2+z)
  cube(0+x,4+y,-2+z)
def render():
  bush(-5,0,10)
  tree(3,0,7)
while True:
  clear()
  black()
  render()
  update()
  jvel-=.01
  camy+=jvel
  if camy<=0:
    camy=0
    jvel=.01
    onground=True
  if camy>=.3:
    onground=False

您没有剔除相机后面的顶点。我在您的代码中看不到任何剔除的证据。如果渲染位于相机后面的点,它会在结果中上下颠倒。你实际上不是转了 360 度,而是转了 180 度。当体素直接在您身后时,如果您不剔除它们,它们将呈现倒置状态。您可以通过打印 yrot 变量来测试它。尝试修改行 if newx<=-200 or newy<=-200 or newx>=200 or newy>=200 以包含对 transz 的检查,即 if transz < 0.1 or newx<=-200 or newy<=-200 or newx>=200 or newy>=200。任何小的值都可以,但 0.1 应该在您当前的实现中运行良好。