Свет openGL не будет двигаться с камерой

Помогите мне понять, почему мой свет находится в фиксированном положении и не следит за глазами / камерой. FAQ по openGL, кажется, говорит, что вы просто устанавливаете положение источника света перед выполнением каких-либо преобразований для объектов в вашем мире, и что вы можете установить его только один раз... Но источник света все еще остается в фиксированном положении.

import pyglet

from pyglet.gl import *
from pyglet.window import key
from pyglet.graphics import draw
from vector_math import *

win = pyglet.window.Window()
keys = key.KeyStateHandler()
win.push_handlers(keys)

rtri = 0.0
eye_vec = [0, 0, 2]
center_vec = [0, 0, 0]
up_vec = [0, 1, 0]
center_dist = 3.0

glClearColor(0.0, 0.0, 0.0, 0.0)    # This Will Clear The Background Color To Black
glClearDepth(1.0)                   # Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS)                # The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST)             # Enables Depth Testing
glEnable(GL_LINE_STIPPLE)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glShadeModel(GL_SMOOTH)             # Enables Smooth Color Shading

glViewport(0,0,win.width,win.height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()                    # Reset The Projection Matrix
# Calculate The Aspect Ratio Of The Window
gluPerspective(45.0, float(win.width) / float(win.height), 0.01, 100.0)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glPushMatrix()

glTranslatef(0.0, 0.0, 0.5)
glLightfv(GL_LIGHT0, GL_POSITION, (GLfloat * 4)(0.0, 0.0, 0.0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (GLfloat * 3)(40.0, 40.0, 40.0))
glLightfv(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat * 1) (.35))

glEnable(GL_LIGHT0)

glPopMatrix()

def move_eye_in(going_in):
    global center_dist
    global eye_vec
    center_dist += (-0.3 if going_in else 0.3)
    eye_vec = vec_scalar_mul(vec_normalize(eye_vec), center_dist)

def rotate_eye(is_left):
    global eye_vec

    print 'center_vec', center_vec
    print 'eye_vec', eye_vec

    center_minus_eye = vec_sub(center_vec, eye_vec)
    print 'center_minus_eye', center_minus_eye

    print 'up_vec', up_vec
    look_vec = vec_scalar_mul(vec_normalize(vec_cross(up_vec, center_minus_eye)), 0.5)
    print 'look_vec', look_vec

    eye_plus_look_vec = vec_add(eye_vec, look_vec) if is_left else vec_sub(eye_vec, look_vec)
    print 'eye_plus_look_vec', eye_plus_look_vec

    eye_vec = vec_scalar_mul(vec_normalize(eye_plus_look_vec), center_dist)

def move_eye(x, y, z):
    eye_vec[0] += x
    eye_vec[1] += y
    eye_vec[2] += z

def draw_pyramid(dim):
    glBegin(GL_TRIANGLES)

    glColor3f(1.0, 1.0, 0.0);   # yellow
    glVertex3f(0.0, dim, 0.0);  # Top Of Triangle (Right)
    glVertex3f(-dim, -dim, dim); # Left Of Triangle (Right)
    glVertex3f(dim, -dim, dim);

    glColor3f(1.0, 0.0, 0.0);   # red
    glVertex3f(0.0, dim, 0.0);  # Top Of Triangle (Right)
    glVertex3f(dim, -dim, dim); # Left Of Triangle (Right)
    glVertex3f(dim, -dim, -dim);

    glColor3f(0.0, 1.0, 0.0);   # green
    glVertex3f(0.0, dim, 0.0);      # Top Of Triangle (Back)
    glVertex3f(dim, -dim, -dim);    # Left Of Triangle (Back)
    glVertex3f(-dim, -dim, -dim)

    glColor3f(0.0, 0.0, 1.0);   # blue
    glVertex3f(0.0, dim, 0.0);      # Top Of Triangle (Left)
    glVertex3f(-dim, -dim, -dim);   # Left Of Triangle (Left)
    glVertex3f(-dim, -dim, dim);

    glEnd()

def makeUnitLineGrid(dim):
    line_coords = []
    for a in range(dim + 1):
        for b in range(dim + 1):
            line_coords.extend([
                # vert lines
                # a, 0,   b,
                # a, dim, b,
                # horiz lines
                0,   a, b,
                dim, a, b,
                # depth lines
                a, b, 0,
                a, b, dim])
    return line_coords

line_coords = makeUnitLineGrid(20)

@win.event
def on_draw():

    handle_down_keys()

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(90.0, float(win.width) / float(win.height), 0.001, 100.0)

    # glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    global rtri
    rtri += 1

    gluLookAt(
            eye_vec[0], eye_vec[1], eye_vec[2],
            center_vec[0], center_vec[1], center_vec[2],
            up_vec[0], up_vec[1], up_vec[2])

    glPushMatrix()

    # glTranslatef(0, 0, -0.5)
    # glRotatef(rtri, 0.0, 0.0, 1.0)
    # glRotatef(-90, 1.0, 0.0, 0.0)
    glScalef(1/5.0, 1/5.0, 1/5.0)
    draw_pyramid(3.0)

    glPopMatrix()

    glPushMatrix()

    glTranslatef(3, 0, 0)
    glRotatef(90, 0.0, 1.0, 0.0)
    glScalef(1/5.0, 1/5.0, 1/5.0)
    draw_pyramid(3.0)

    glPopMatrix()

    glPushMatrix()

    glLineStipple(1, 0xFFF)
    glTranslatef(-2.5, -2.5, -2.5)
    glScalef(1.5, 1.5, 1.5)
    glColor4f(1.0, 1.0, 0.0, 0.1);   # yellow

    glEnable(GL_LIGHTING)
    draw(len(line_coords) / 3, GL_LINES,
        ('v3f', line_coords),
        # ('c3B', colors),
    )
    glDisable(GL_LIGHTING)

    glPopMatrix()


def handle_down_keys():

    if keys[key.PAGEUP]:
        move_eye_in(True)
    elif keys[key.PAGEDOWN]:
        move_eye_in(False)
    elif keys[key.LEFT]:
        rotate_eye(True)
    elif keys[key.RIGHT]:
        rotate_eye(False)
    elif keys[key.UP]:
        move_eye(0, 0.5, 0)
    elif keys[key.DOWN]:
        move_eye(0, -0.5, 0)


pyglet.app.run()

vector_math.py

import math

def vec_add(a, b):
    return [a[0] + b[0], a[1] + b[1], a[2] + b[2]]

def vec_sub(a, b):
    return [a[0] - b[0], a[1] - b[1], a[2] - b[2]]

def vec_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 vec_normalize(a):
    mag = math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])
    return [a[0] / mag, a[1] / mag, a[2] / mag]

def vec_scalar_mul(a, n):
    return [a[0] * n, a[1] * n, a[2] * n]

1 ответ

Решение

Похоже, что в вашем коде есть две проблемы:

  1. Как правило, вы хотите поместить преобразование просмотра в стек матрицы представления модели по сравнению со стеком матрицы проекции. Линия 126, где вы установите gluLookAt действительно должно идти после строки 135, где вы сбрасываете матрицу вида модели, вызывая glLoadIdentity, Причиной этого является то, что нормали освещения преобразуются частью матрицы вида модели, и если вы не включите преобразование просмотра, это может привести к нежелательным результатам.

  2. Во-вторых, вы указываете положение источника света (вызывая glLight( GL_LIGHT0, GL_POSITION, ...);) перед любым другим преобразованием (при условии, что код python в верхней части файлов выполняется первым).

Когда вы указываете положение источника света таким образом, он фиксируется в координатах глаза (положение источника преобразуется матрицей в верхней части матрицы вида модели при вызове glLight( ..., GL_POSITION, ... );) Если вы хотите, чтобы источник света двигался вместе с точкой зрения, укажите ее после вызова gluLookAt, который изменит положение света, чтобы двигаться вместе с глазом.

Другие вопросы по тегам