В вашем коде есть 2 проблемы.
gluLookAt
устанавливает матрицу просмотра.Но это еще не все.gluLookAt
умножает матрицу вида на текущую матрицу в стеке матриц, которую выбирает glMatrixMode
.
Таким образом, ваш код объединяет новую матрицу вида с существующей матрицей представления.Это приводит к тому, что объекты начинают быстро вращаться.
Установите Identity matrix перед вызовом gluLookAt
, чтобы решить эту проблему.Это приводит к тому, что матрица представления модели устанавливается с нуля, независимо от ее прежнего состояния.
glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
Это не решит вашу проблему полностью, потому что в момент, когда вы устанавливаете матрицу вида, текущая матрица в стеке матриц вида модели является объединением матрицы проекции и матрицы вида.Это приводит к тому, что glLoadIdentity
также пропускает матрицу проекции.
Такое поведение можно легко решить.Поместите матрицу вида в стек матрицы моделей (GL_MODELVIEW
) и матрицу проекции в стек матрицы проекций (GL_PROJECTION
):
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
Гораздо лучшим и полностью работающим решением является применение матрицы вращения вокруг осей x и y к матрице вида.Сначала примените матрицу вращения вокруг оси y (вектор вверх), затем текущую матрицу вида и, наконец, вращение по оси x:
view-matrix = rotate-X * view-matrix * rotate-Y
. Для этого текущая матрица вида должна быть прочитана как glGetFloatv(GL_MODELVIEW_MATRIX)
:
modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
glRotate(-change[1]*0.1, 1, 0, 0)
glMultMatrixf(modelview)
glRotate(change[0]*0.1, 0, 1, 0)
Обратите внимание, что это должно быть сделано вместо:
glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
Завершить функцию main
( renderEngine.py ), с предлагаемыми изменениями:
def main(world,x,y,z,width,height,renderDistance):
pygame.init()
pygame.display.set_mode((width,height), DOUBLEBUF | OPENGL)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthMask(GL_TRUE)
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CCW)
glShadeModel(GL_SMOOTH)
glDepthRange(0.0, 1.0)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
#pygame.mouse.set_visible(False)
facing = [0, 0, False]
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
pygame.mouse.set_visible(True)
pygame.quit()
return # TODO: Add pause
newMousePos = pygame.mouse.get_pos()
change = (newMousePos[0]-(width/2), newMousePos[1]-(height/2))
pygame.mouse.set_pos([width / 2, height / 2])
if facing[2]:
facing[0] -= change[0]
else:
facing[0] += change[0]
facing[1] += change[1]
while facing[0] > width:
facing[0] = 2*width-facing[0]
facing[2] = not facing[2]
while facing[0] < 0:
facing[0] = 0-facing[0]
facing[2] = not facing[2]
if facing[1] < 0:
facing[1] = 0
if facing[1] > height:
facing[1] = height
radius = (width**2+height**2)**.5+1
lookingZ = (-1*facing[0]**2-facing[1]**2+radius**2)**.5
if facing[2]:
lookingZ *= -1
#print(lookingZ, facing[0], facing[1], radius)
print(facing[0], facing[1], lookingZ)
#glLoadIdentity()
#gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
glRotate(-change[1]*0.1, 1, 0, 0)
glMultMatrixf(modelview)
glRotate(change[0]*0.1, 0, 1, 0)
xmin = round(x-renderDistance[0])
ymin = round(y-renderDistance[1])
zmin = round(z-renderDistance[2])
if xmin < 0:
xmin = 0
if ymin < 0:
ymin = 0
if zmin < 0:
zmin = 0
xmax = round(x+renderDistance[0])
ymax = round(y+renderDistance[1])
zmax = round(z+renderDistance[2])
dims = world.dims()
if xmax > dims[0]:
xmax = dims[0]
if ymax > dims[1]:
ymax = dims[1]
if zmax > dims[2]:
zmax = dims[2]
selection = world.select_data(xrange = (xmin, xmax), yrange = (ymin, ymax), zrange = (zmin, zmax))
blocks = selection.iterate(ignore=(None,))
glClearDepth(1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
for bl in blocks:
locations = bl[0]
block = bl[1]
cube(locations[0] - x, locations[1] - y, locations[2] - z, block)
#print(locations[0],locations[1],locations[2])
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glOrtho(0.0, width, 0.0, height, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
glDisable(GL_DEPTH_TEST)
crosshair(width/2, height/2, 20)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glCullFace(GL_BACK)
pygame.display.flip()
time.sleep(.01)