#! /usr/bin/env python
# -*- coding: utf8 -*-
"""Port of NeHe Lesson 26 by Ivan Izuver """
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
# from Image import *
from PIL.Image import *
import sys,gc
import random
ESCAPE = '\033'
# Number of the glut window.
window = 0
LightAmb=(0.7,0.7,0.7) #Окружающий свет
LightDif=(1.0,1.0,0.0) #Рассеянный свет
LightPos=(4.0,4.0,6.0,1.0) #Позиция источника освещения
#q=GLUquadricObj()
xrot=yrot=0.0 #Вращение по Х Y
xrotspeed=yrotspeed=0.0 #Скорость вращения по X Y
zoom=-3.0 #Глубина сцены в экране
height=0.5 #Высота мяча над полом
textures = {}
goblelength=2
ballr=0.05
x=0
y=0
z=0
vx=0.01
vy=0.01
vz=0.01
ax=0
ay=0
ag=-0.0098#重力加速度
az=0
time=0
def LoadTextures(fname):
if textures.get( fname ) is not None:
return textures.get( fname )
texture = textures[fname] = glGenTextures(1)
image = open(fname)
ix = image.size[0]
iy = image.size[1]
image = image.tobytes("raw", "RGBX", 0, -1)
# Create Texture
glBindTexture(GL_TEXTURE_2D, texture) # 2d texture (x and y size)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
return texture
# A general OpenGL initialization function. Sets all of the initial parameters.
def InitGL(Width, Height): # We call this right after our OpenGL window is created.
glClearColor(0.2, 0.5, 1.0, 1.0) # This Will Clear The Background Color To Black
glClearDepth(1.0) # Enables Clearing Of The Depth Buffer
glClearStencil(0)
glDepthFunc(GL_LEQUAL) # The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST) # Enables Depth Testing
glShadeModel(GL_SMOOTH) # Enables Smooth Color Shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glEnable(GL_TEXTURE_2D)
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb)
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif)
glLightfv(GL_LIGHT0, GL_POSITION, LightPos)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHTING)
glMatrixMode(GL_PROJECTION)
glLoadIdentity() # Reset The Projection Matrix
# Calculate The Aspect Ratio Of The Window
gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below)
def ReSizeGLScene(Width, Height):
if Height == 0: # Prevent A Divide By Zero If The Window Is Too Small
Height = 1
glViewport(0, 0, Width, Height) # Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
def DrawObject():
glColor3f(1.0, 1.0, 1.0);
glBindTexture( GL_TEXTURE_2D, LoadTextures('NeHe.bmp') )
Q=gluNewQuadric()
gluQuadricNormals(Q, GL_SMOOTH)
gluQuadricTexture(Q, GL_TRUE)
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
global ballr
gluSphere(Q, ballr*2, 32, 32)
glColor4f(1.0, 1.0, 1.0, 0.4)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE)
glEnable(GL_TEXTURE_GEN_S)
glEnable(GL_TEXTURE_GEN_T)
gluSphere(Q, ballr*2, 32, 32)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_BLEND)
gluDeleteQuadric( Q )
def DrawFloor():
glBindTexture( GL_TEXTURE_2D, LoadTextures('NeHe2.bmp') )
glBegin(GL_QUADS) # Begin draw
glNormal3f(0.0, 1.0, 0.0) # Upper normal
glTexCoord2f(0.0, 1.0) # bottom left side of texture
glVertex3f(-2.0, -2.0, 2.0) # bottom left angle of floor
glTexCoord2f(0.0, 0.0) # upper left side of texture
glVertex3f(-2.0, -2.0,-2.0)# upper left angle of floor
glTexCoord2f(1.0, 0.0) #upper right side of texture
glVertex3f( 2.0, -2.0,-2.0) # upper right angle of floor
glTexCoord2f(1.0, 1.0) # bottom right side of texture
glVertex3f( 2.0, -2.0, 2.0)# bottom right angle of floor
glEnd() # finish draw
####上
glBegin(GL_QUADS) # Begin draw
glNormal3f(0.0, 1.0, 0.0) # Upper normal
glTexCoord2f(0.0, 1.0) # bottom left side of texture
glVertex3f(-2.0, 2.0, 2.0) # bottom left angle of floor
glTexCoord2f(0.0, 0.0) # upper left side of texture
glVertex3f(-2.0, 2.0,-2.0)# upper left angle of floor
glTexCoord2f(1.0, 0.0) #upper right side of texture
glVertex3f( 2.0, 2.0,-2.0) # upper right angle of floor
glTexCoord2f(1.0, 1.0) # bottom right side of texture
glVertex3f( 2.0, 2.0, 2.0)# bottom right angle of floor
glEnd() # finish draw
####
glBegin(GL_QUADS) # Begin draw
glNormal3f(0.0, 1.0, 0.0) # Upper normal
glTexCoord2f(0.0, 1.0) # bottom left side of texture
glVertex3f(2.0, 2.0, 2.0) # bottom left angle of floor
glTexCoord2f(0.0, 0.0) # upper left side of texture
glVertex3f(2.0, 2.0,-2.0)# upper left angle of floor
glTexCoord2f(1.0, 0.0) #upper right side of texture
glVertex3f( 2.0, -2.0,-2.0) # upper right angle of floor
glTexCoord2f(1.0, 1.0) # bottom right side of texture
glVertex3f( 2.0, -2.0, 2.0)# bottom right angle of floor
glEnd() # finish draw
####
glBegin(GL_QUADS) # Begin draw
glNormal3f(0.0, 1.0, 0.0) # Upper normal
glTexCoord2f(0.0, 1.0) # bottom left side of texture
glVertex3f(-2.0, 2.0, 2.0) # bottom left angle of floor
glTexCoord2f(0.0, 0.0) # upper left side of texture
glVertex3f(-2.0, 2.0,-2.0)# upper left angle of floor
glTexCoord2f(1.0, 0.0) #upper right side of texture
glVertex3f( -2.0, -2.0,-2.0) # upper right angle of floor
glTexCoord2f(1.0, 1.0) # bottom right side of texture
glVertex3f( -2.0, -2.0, 2.0)# bottom right angle of floor
glEnd() # finish draw
####
glBegin(GL_QUADS) # Begin draw
glNormal3f(0.0, 1.0, 0.0) # Upper normal
glTexCoord2f(0.0, 1.0) # bottom left side of texture
glVertex3f(2.0, 2.0, -2.0) # bottom left angle of floor
glTexCoord2f(0.0, 0.0) # upper left side of texture
glVertex3f(2.0, -2.0,-2.0)# upper left angle of floor
glTexCoord2f(1.0, 0.0) #upper right side of texture
glVertex3f( -2.0, -2.0,-2.0) # upper right angle of floor
glTexCoord2f(1.0, 1.0) # bottom right side of texture
glVertex3f( -2.0, 2.0, -2.0)# bottom right angle of floor
glEnd() # finish draw
# The main drawing function.
def DrawGLScene():
pass
# Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)
eqr=(0.0,-1.0, 0.0, 0.0)
glLoadIdentity() # Reset 视角
glTranslatef(0.0, -0.0, -7)
glColorMask(0,0,0,0)
glEnable(GL_STENCIL_TEST)
glStencilFunc(GL_ALWAYS, 1, 1)
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)
glDisable(GL_DEPTH_TEST)
glEnable(GL_DEPTH_TEST)
glColorMask(1,1,1,1)
glStencilFunc(GL_EQUAL, 1, 1)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glEnable(GL_CLIP_PLANE0)
glClipPlane(GL_CLIP_PLANE0, eqr)
glPushMatrix()
glScalef(1.0, -1.0, 1.0)
glLightfv(GL_LIGHT0, GL_POSITION, LightPos)
glTranslatef(0.0, height, 0.0)
glPopMatrix()
glDisable(GL_CLIP_PLANE0)
glDisable(GL_STENCIL_TEST)
glLightfv(GL_LIGHT0, GL_POSITION, LightPos)
glEnable(GL_BLEND)
glDisable(GL_LIGHTING)
glColor4f(1.0, 1.0, 1.0, 0.8)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
DrawFloor()
glEnable(GL_LIGHTING)
glDisable(GL_BLEND)
glTranslatef(0.0, 0.0, 0.0)
# DrawObject()
global x,y,z
global vx, vy, vz
vx=vx+ax
vy=vy+ay+ag
vz=vz+az
x=x+vx
y=y+vy
z=z+vz
#反弹
if y<-(goblelength-ballr):
vy=-vy
y=-(goblelength-ballr)
elif y>(goblelength-ballr):
vy=-vy
y=(goblelength-ballr)
else:# y<-goblelength:
vy=vy
if x<-(goblelength-ballr) :
vx=-vx
x=-(goblelength-ballr)
elif x>(goblelength-ballr):
vx=-vx
x=(goblelength-ballr)
else:# y<-goblelength:
vx=vx
if z<-(goblelength-ballr):
vz=-vz
z=-(goblelength-ballr)
elif z>(goblelength-ballr):
z=(goblelength-ballr)
vz=-vz
else:# y<-goblelength:
vz=vz
# print('ay:',ay)
# print('vy',vy)
# print('y',y)
glTranslatef(x, y, z)
DrawObject()
glFlush()
# since this is double buffered, swap the buffers to display what just got drawn.
glutSwapBuffers()
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
def keyPressed(*args):
global window
# If escape is pressed, kill everything.
if args[0] == ESCAPE:
sys.exit()
def mouseButton( button, mode, mx, my ):
if button == GLUT_LEFT_BUTTON:
global x,y,z
z=2
y=-(my-240.0)/240.0
x=(mx-240.0)/240.0
print x
print y
print '##'
vx=random.randint(0,0.00001)
vy=random.randint(0,0.00001)
vz=random.randint(0,0.00001)
# if button == GLUT_RIGHT_BUTTON:
# print [mx,my]
def mouseMotionCB(mx, my):
if(mouseLeftDown):
cameraAngleY += (mx - mouseX)
cameraAngleX += (my - mouseY)
mouseX = mx
mouseY = my
if(mouseRightDown):
cameraDistance += (my - mouseY) * 0.2
mouseY = my
glutPostRedisplay()
def main():
global window
# pass arguments to init
glutInit(sys.argv)
# Select type of Display mode:
# Double buffer
# RGBA color
# Alpha components supported
# Depth buffer
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
# get a 640 x 480 window
glutInitWindowSize(480, 480)
# the window starts at the upper left corner of the screen
glutInitWindowPosition(0, 0)
# Okay, like the C version we retain the window id to use when closing, but for those of you new
# to Python (like myself), remember this assignment would make the variable local and not global
# if it weren't for the global declaration at the start of main.
window = glutCreateWindow("Realistic Reflection by RISC")
# Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
# set the function pointer and invoke a function to actually register the callback, otherwise it
# would be very much like the C version of the code.
glutDisplayFunc(DrawGLScene)
# Uncomment this line to get full screen.
#glutFullScreen()
# When we are doing nothing, redraw the scene.
glutIdleFunc(DrawGLScene)
# Register the function called when our window is resized.
glutReshapeFunc(ReSizeGLScene)
# Register the function called when the keyboard is pressed.
glutKeyboardFunc(keyPressed)
glutMouseFunc( mouseButton )
glutMotionFunc(mouseMotionCB);
# Initialize our window.
InitGL(480, 480)
# Start Event Processing Engine
glutMainLoop()
# Print message to console, and kick off the main to get it rolling.
if __name__ == "__main__":
print "Hit ESC key to quit."
main()
需要程序运行目录下有两张图片作为小球和墙布的纹理载入,文件名分别为:NeHe2.bmp和NeHe2.bmp
然后直接运行这个程序就好了,在窗口中点击鼠标会重新刷新出一个小球。