2009/02/18

cubeGL V1.0 dirty code

The first version of CubicVR Viewer "cubeGL" is now working. It still a dirty code.

一応CubicVR Viewer "cubeGL"が動きましたので、まだ汚いコードですが、参考になればと思い掲載します。本当はもっときれいなコードにしてから掲載したかったのですが、コードをきれいにすると動かなくなります。これをもとに、一から書き直した方が早いかもしれませんね。改良点としては、
1. glutMotionFunc( )を使ってマウスでグリグリ回せるようにした。
2. glutIdleFunc()を使って、マウスを放しても慣性力で回り続けるようにした。

# cube-GL V1.0 - still dirty code, but has minimum functionality set
# A Python/Open-GL based cubic VR viewer
# By R.Kishimoto 2009.2.18

import sys
import math
import Image
import time
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

tex_size = 256
window_size = (500, 500)
input_file_name = "./pcube/sj256.jpg"
mx=my=0
gx=gy=0
mod = 0
now = past = 0
xspeed = yspeed = 0

def prep_tex (pfname):
global rc, image_x
im=Image.open(pfname)
size=im.size
image_x = size[0]
image_y = size[1]

if image_x*6 == image_y:
print "good y = 6x"
else:
print "error y != 6x"
sys.exit

rc = image_x / tex_size
rc_mod = image_x % tex_size
if rc_mod != 0:
rc = rc + 1

for face in range(6):
for y in range(rc):
for x in range(rc):
x1 = tex_size*x
x2 = x1 + tex_size
y1 = face * image_x + tex_size * y
y2 = y1 + tex_size

box = (x1, y1, x2, y2)
region = im.crop(box)
fname = '%s%d%d%d%s' % (pfname, face, y, x, ".jpg")
region.save(fname)
print (face, y, x, x1, y1, x2, y2, fname)

fov = 120
vertices = ((-1.0, 1.0, -1.0), (1.0, 1.0, -1.0), (1.0, -1.0, -1.0), (-1.0, -1.0, -1.0),
(-1.0, 1.0, 1.0), (1.0, 1.0, 1.0), (1.0, -1.0, 1.0), (-1.0, -1.0, 1.0))

def polygon(a, b, c, d):
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3fv(vertices[a])
glTexCoord2f(1.0, 0.0)
glVertex3fv(vertices[b])
glTexCoord2f(1.0, 1.0)
glVertex3fv(vertices[c])
glTexCoord2f(0.0, 1.0)
glVertex3fv(vertices[d])
glEnd()

def cube():
ti = 0
step = 2.0 * 256.0 / 1000.0
glEnable(GL_TEXTURE_2D)

for y in range(rc):
for x in range(rc):
x1 = -1 + step * x
x2 = x1 + step
y1 = 1 - step * y
y2 = y1 - step
#print "x1,x2,y1,y2,step,ti", x1, x2, y1, y2, step, ti
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(0,1,2,3)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(x1, y1, -1.0)
glTexCoord2f(1.0, 0.0)
glVertex3f(x2, y1, -1.0)
glTexCoord2f(1.0, 1.0)
glVertex3f(x2, y2, -1.0)
glTexCoord2f(0.0, 1.0)
glVertex3f(x1, y2, -1.0)
glEnd()
ti=ti+1

for y in range(rc):
for x in range(rc):
x1 = -1 + step * x
x2 = x1 + step
y1 = 1 - step * y
y2 = y1 - step
#print "x1,x2,y1,y2,step,rc", x1, x2, y1, y2, step, rc
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(1,5,6,2)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(1.0, y1, x1)
glTexCoord2f(1.0, 0.0)
glVertex3f(1.0, y1, x2)
glTexCoord2f(1.0, 1.0)
glVertex3f(1.0, y2, x2)
glTexCoord2f(0.0, 1.0)
glVertex3f(1.0, y2, x1)
glEnd()
ti=ti+1

for y in range(rc):
for x in range(rc):
x1 = 1 - step * x
x2 = x1 - step
y1 = 1 - step * y
y2 = y1 - step
#print "x1,x2,y1,y2,step,rc", x1, x2, y1, y2, step, rc
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(5,4,7,6)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(x1, y1, 1.0)
glTexCoord2f(1.0, 0.0)
glVertex3f(x2, y1, 1.0)
glTexCoord2f(1.0, 1.0)
glVertex3f(x2, y2, 1.0)
glTexCoord2f(0.0, 1.0)
glVertex3f(x1, y2, 1.0)
glEnd()
ti=ti+1

for y in range(rc):
for x in range(rc):
x1 = 1 - step * x
x2 = x1 - step
y1 = 1 - step * y
y2 = y1 - step
#print "x1,x2,y1,y2,step,rc", x1, x2, y1, y2, step, rc
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(4,0,3,7)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(-1.0, y1, x1)
glTexCoord2f(1.0, 0.0)
glVertex3f(-1.0, y1, x2)
glTexCoord2f(1.0, 1.0)
glVertex3f(-1.0, y2, x2)
glTexCoord2f(0.0, 1.0)
glVertex3f(-1.0, y2, x1)
glEnd()
ti=ti+1

for y in range(rc):
for x in range(rc):
x1 = -1 + step * x
x2 = x1 + step
y1 = 1 - step * y
y2 = y1 - step
#print "x1,x2,y1,y2,step,rc", x1, x2, y1, y2, step, rc
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(4,5,1,0)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(x1, 1.0, y1)
glTexCoord2f(1.0, 0.0)
glVertex3f(x2, 1.0, y1)
glTexCoord2f(1.0, 1.0)
glVertex3f(x2, 1.0, y2)
glTexCoord2f(0.0, 1.0)
glVertex3f(x1, 1.0, y2)
glEnd()
ti=ti+1

for y in range(rc):
for x in range(rc):
x1 = -1 + step * x
x2 = x1 + step
y1 = -1 + step * y
y2 = y1 + step
#print "x1,x2,y1,y2,step,rc", x1, x2, y1, y2, step, rc
glBindTexture(GL_TEXTURE_2D, texture[ti])
#polygon(3,2,6,7)
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3f(x1, -1.0, y1)
glTexCoord2f(1.0, 0.0)
glVertex3f(x2, -1.0, y1)
glTexCoord2f(1.0, 1.0)
glVertex3f(x2, -1.0, y2)
glTexCoord2f(0.0, 1.0)
glVertex3f(x1, -1.0, y2)
glEnd()
ti=ti+1

def drawText( value, x,y, windowHeight, windowWidth, step = 18 ):
"""Draw the given text at given 2D position in window
"""
glMatrixMode(GL_PROJECTION);
# For some reason the GL_PROJECTION_MATRIX is overflowing with a single push!
# glPushMatrix()
matrix = glGetDouble( GL_PROJECTION_MATRIX )

glLoadIdentity();
glOrtho(0.0, windowHeight or 32, 0.0, windowWidth or 32, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glClearColor(1.0, 1.0, 1.0, 0.0)

glBegin(GL_LINES)
glColor3f(1.0, 1.0, 1.0)
glVertex2i(x, y+20)
glVertex2i(x+60, y+20)
glVertex2i(x+60, y)
glVertex2i(x+60, y+20)
glVertex2i(x, y)
glVertex2i(x, y+20)
glEnd()

glRasterPos2i(x, y);
lines = 0
for character in value:
if character == '\n':
glRasterPos2i(x, y-(lines*18))
else:
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ord(character));
glPopMatrix();
glMatrixMode(GL_PROJECTION);
# For some reason the GL_PROJECTION_MATRIX is overflowing with a single push!
# glPopMatrix();
glLoadMatrixd( matrix ) # should have un-decorated alias for this...

glMatrixMode(GL_MODELVIEW);

def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glViewport(0, 0, window_size[0], window_size[1])

glMatrixMode(GL_PROJECTION)
glLoadIdentity()

# set camera FOV=100 degree, aspect=1.0, near=0.01(0.0 will cause error), far=100.0
gluPerspective(fov, 1.0, 0.01, 100.0)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# eye, at, up
gluLookAt(0.0, 0.0, 0.0, xxx, yyy, zzz, 0, 1, 0)

cube()

drawText( 'ksmt', 430, 1, window_size[0], window_size[1] )
drawText( 'Z-OUT', 360, 1, window_size[0], window_size[1] )
drawText( 'Z-IN', 290, 1, window_size[0], window_size[1] )
drawText( 'DOWN', 220, 1, window_size[0], window_size[1] )
drawText( 'UP', 150, 1, window_size[0], window_size[1] )
drawText( '-->', 80, 1, window_size[0], window_size[1] )
drawText( '<--', 10, 1, window_size[0], window_size[1] )

glFlush()

def deg2rad(deg):
rad = math.pi * deg / 360
return rad

uuu = 10.0
fov = 120
xzd = -180
xyd = 0
xzt = deg2rad(xzd)
xyt = deg2rad(xyd)

yyy = math.sin(xyt)
zzz = math.sin(xzt) * math.cos(xyt)
xxx = math.cos(xzt) * math.cos(xyt)

def mykey(key, x, y):
global xxx, yyy, zzz, fov, xzd, xyd
print "key, mod ", key, glutGetModifiers()

if key=='a': # -xzt
xzd = xzd - uuu
elif key=='d': # +xzt
xzd = xzd + uuu
elif key=='x': # -xyt
if (xyd - uuu) >= -180 :
xyd = xyd - uuu
elif key=='w': # +xyt
if (xyd + uuu) <= 180:
xyd = xyd + uuu
elif key=='s': # default
xzd = -180.0
xyd = 0.0
fov = 120

elif key=='e': # zoom out
if fov <= 160:
fov = fov + 10
elif key=='z': # zoom in
if fov > 10:
fov = fov - 10

elif key=='-': # zoom out
if fov <= 160:
fov = fov + 10
elif key=='+': # zoom in
if fov >=10:
fov = fov - 10

xzt = deg2rad(xzd)
xyt = deg2rad(xyd)

yyy = math.sin(xyt)
zzz = math.sin(xzt) * math.cos(xyt)
xxx = math.cos(xzt) * math.cos(xyt)

glutPostRedisplay()

def mymouse(button, state, x, y):
global xxx, yyy, zzz, fov, xzd, xyd, start_x, start_y, gx, gy, mod
sy = window_size[1] - y
mod = glutGetModifiers()
#print "click button, state, x, y, mod--------", button, state, x , sy, mod
if state == 0 & button == 0:
start_x = x
start_y = sy
if ((10 < x) & (x < 70) & (sy < 20)):
xzd = xzd - uuu
print "left ", x, sy
elif ((80 < x) & (x < 140) & (sy < 20)):
xzd = xzd + uuu
print "right ", x, sy
elif ((150 < x) & (x < 210) & (sy < 20)):
if (xyd - uuu) >= -180 :
xyd = xyd + uuu
print "up ", x, sy
elif ((220 < x) & (x < 280) & (sy < 20)):
if (xyd + uuu) <= 180:
xyd = xyd - uuu
print "down ", x, sy
elif ((290 < x) & (x < 350) & (sy < 20)):
if fov <= 160:
fov = fov - 10
print "out ", x, sy
elif ((360 < x) & (x < 420) & (sy < 20)):
if fov > 10:
fov = fov + 10
print "in ", x, sy

gx = x
gy = sy

xzt = deg2rad(xzd)
xyt = deg2rad(xyd)

yyy = math.sin(xyt)
zzz = math.sin(xzt) * math.cos(xyt)
xxx = math.cos(xzt) * math.cos(xyt)

prev_state = state

glutPostRedisplay()


def gentex(t, img):
# use the given texture
glBindTexture(GL_TEXTURE_2D, t)

# read texture data from .bmp file using Image library
image=Image.open(img)
if len(image.getbands())!=4:
image=image.convert("RGBA")
size=image.size

# generate texture from array image.tostring() inside current texture 'texture'
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size[0], size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, image.tostring())

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

def mymotion(x, y):
global xxx, yyy, zzz, fov, xzd, xyd, start_x, start_y, gx, gy, mod, now, past, xspeed, yspeed
y = window_size[1]-y
#print "motion xy, frist_flag, gx, gy, mod", x, y, gx, gy, mod

dx = x - gx
dy = y - gy
xzd = xzd + dx
if ((xyd + dy) >= -180) & ((xyd + dy) <= 180):
xyd = xyd + dy

now = time.time()
dtime = now - past
if dtime == 0:
xspeed = yspeed = 0
else:
xspeed = 0.9 * dx / dtime
yspeed = 0.9 * dy / dtime

speedlimit = 200.0
if xspeed > speedlimit :
xspeed = speedlimit
elif xspeed < ( -1 * speedlimit) :
xspeed = -1 * speedlimit

if yspeed > speedlimit:
yspeed = speedlimit
elif yspeed < (-1 * speedlimit) :
yspeed = -1 * speedlimit

#print "xspeed, yspeed", xspeed, yspeed
past = now

if mod==GLUT_ACTIVE_SHIFT: # zoom in
if fov > 10:
fov = fov - 1
elif mod==GLUT_ACTIVE_CTRL: # zoom out
if fov <= 160:
fov = fov + 1

xzt = deg2rad(xzd)
xyt = deg2rad(xyd)

yyy = math.sin(xyt)
zzz = math.sin(xzt) * math.cos(xyt)
xxx = math.cos(xzt) * math.cos(xyt)

glutPostRedisplay()
gx = x
gy = y

def myidle():
global now, past, xspeed, yspeed, xxx, yyy, zzz, fov, xzd, xyd
now = time.time()
dtime = now - past

dy = dtime * yspeed
if ((xyd + dy) >= -180) & ((xyd + dy) <= 180):
xyd = xyd + dy
xzd = xzd + (dtime * xspeed)

xzt = deg2rad(xzd)
xyt = deg2rad(xyd)

yyy = math.sin(xyt)
zzz = math.sin(xzt) * math.cos(xyt)
xxx = math.cos(xzt) * math.cos(xyt)

glutPostRedisplay()
past = now
xspeed = xspeed * 0.99
yspeed = yspeed * 0.99

def myspecial( key, x, y ):
mod = glutGetModifiers()
print "special key, x, y, mod ", key, x, y, mod

glutInit( sys.argv )
#glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH )
glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH )
glutInitWindowSize( window_size[0], window_size[1] )
glutInitWindowPosition(0,0)
glutCreateWindow( 'cube' )
glutDisplayFunc( display )
glutKeyboardFunc( mykey )
glutMouseFunc( mymouse )
glutMotionFunc( mymotion)
glutSpecialFunc( myspecial )
glutIdleFunc( myidle )
glEnable(GL_DEPTH_TEST)
#glEnable(GL_CULL_FACE)
#glCullFace(GL_BACK)
# prep_tex(input_file_name)

### TEXTURE
rc=4
tex_num=0
glEnable(GL_TEXTURE_2D)
texture=glGenTextures(rc*rc*6)
for face in range(6):
for y in range(rc):
for x in range(rc):
fname = '%s%d%d%d%s' % ("./pcube/sjtex", face, y, x, ".jpg")
gentex(texture[tex_num], fname)
#print 'reading texture %s %d' % (fname, tex_num)
tex_num = tex_num+1

#Menu
def selectMessage():
return 1
print "select message meny selected"

glutMainLoop()

#
# Six Cubic face global mapping
# 0-----1
# | |
# | F0 |
# 3-----2
# 1-----5
# | |
# | R1 |
# 2-----6
# 5-----4
# | |
# | B2 |
# 6-----7
# 4-----0
# | |
# | L3 |
# 7-----3
# 4-----5
# | |
# | U4 |
# 0-----1
# 3-----2
# | |
# | D5 |
# 7-----6
#
# 4-----5
# | |
# | U4 |
# 0-----1
# 4-----00-----11-----55-----4
# | || || || |
# | L3 || F0 || R1 || B2 |
# 7-----33-----22-----66-----7
# 3-----2
# | |
# | D5 |
# 7-----6
#
# local texture mapping
#
# 0.0----------------------------1.0
# |-----------image_x--------------|
# |--tex_size--|
# |<-- (tex_size/image_x) * 0
# |<-- (tex_size/image_x) * 1
# |<-- (tex_size/image_x) * 2

0 件のコメント: