向后看时出现 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
应该在您当前的实现中运行良好。
前几天在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
应该在您当前的实现中运行良好。