Domanda

Help me understand why my light is at a fixed position and won't follow the eye/camera. The openGL FAQ seems to say you just set the light's position before doing any transforms for the objects in your world, and that you can set it only once... But the light still stays at a fixed position.

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]
È stato utile?

Soluzione

There seem to potentially be two problems with your code:

  1. Generally, you want to put your viewing transformation on the model-view matrix stack, as compared to the projection matrix stack. Line 126, where you set gluLookAt really should go after line 135, where you reset the model-view matrix by calling glLoadIdentity. The reason for this is that lighting normals are transformed by the part of the model-view matrix, and not including your viewing transform will likely yield undesirable results.

  2. Second, you're specifying the light's position (by calling glLight( GL_LIGHT0, GL_POSITION, ...);) before any other transformation (assuming that the python code at the top of the files executes first).

When you specify a light's position in this manner, it gets locked in eye coordinates (a light's position is transformed by the matrix at the top of the model-view matrix when you call glLight( ..., GL_POSITION, ... );) If you want the light to move with the eye point, specify it after your call to gluLookAt, which will transform the light's position to move along with the eye.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top