360度キュービックVRの表示には通常QuickTime(QTVR)またはAdobe Flash Playerが使われます。私はQTVRの製作が趣味でして、World Wide Panoramaにも参加しています。
It would be very easy to implement 360 degree cubic panorama viewer using OpenGL. The source image has 6 cubic faces in one JPEG file.
OpenGLでキュービックパノラマを実現することは、割と簡単だと思われますので、やってみました。普通は次のような6面の画像を繋げたJPEGの画像を使いますが、簡単化のため6枚の別々の写真に分けました。
I manually cut the image into 6 pieces to simplify the OpenGL program.
Convert six JPEG files into six texture and attach to six cubic faces. It's very straight foward. The following code still have some bugs, but I can show you the basic idea. It's really a "inside rotating cube". まだバグなどがありますが、アイデアとしては次のようなものになります。
import sys
import math
import Image
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
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))
uuu = 0.1
fov = 120
xzt = yzt = 0
yyy = math.sin(yzt)
r = math.cos(yzt)
zzz = r * math.sin(xzt)
xxx = r * math.cos(xzt)
def polygon(a, b, c, d):
glBegin(GL_POLYGON)
glTexCoord2f(0.0, 0.0)
glVertex3fv(vertices[a])
glTexCoord2f(0.0, 1.0)
glVertex3fv(vertices[b])
glTexCoord2f(1.0, 1.0)
glVertex3fv(vertices[c])
glTexCoord2f(1.0, 0.0)
glVertex3fv(vertices[d])
glEnd()
def cube():
global texture
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture[4])
polygon(4,5,6,7)
glBindTexture(GL_TEXTURE_2D, texture[1])
polygon(1,5,4,0)
glBindTexture(GL_TEXTURE_2D, texture[2])
polygon(3,7,6,2)
glBindTexture(GL_TEXTURE_2D, texture[0])
polygon(0,4,7,3)
glBindTexture(GL_TEXTURE_2D, texture[5])
polygon(1,0,3,2)
glBindTexture(GL_TEXTURE_2D, texture[3])
polygon(2,6,5,1)
def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# set camera FOV=100 degree, aspect=1.0, near=1.0(0.0 will cause error), far=100.9
gluPerspective(fov, 1.0, 0.5, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# eye, at, up
gluLookAt(0.0, 0.0, 0.0, xxx,yyy,zzz, 0,1,0)
cube()
glFlush()
def mykey(key, x, y):
global xxx, yyy, zzz, fov, xzt, yzt
if key=='a': # -xzt
xzt = xzt - uuu
elif key=='d': # +xzt
xzt = xzt + uuu
elif key=='x': # -yzt
yzt = yzt - uuu
elif key=='w': # +yzt
yzt = yzt + uuu
elif key=='s': # default
xzt = yzt = 0.0
elif key=='-': # zoom out
fov = fov - 10
elif key=='+': # default
fov = fov + 10
yyy = math.sin(yzt)
rrr = math.cos(yzt)
zzz = rrr * math.sin(xzt)
xxx = rrr * math.cos(xzt)
print "xyzf:", xxx, yyy, zzz, fov
glutPostRedisplay()
def gentex(t, img):
# use the given texture
glBindTexture(GL_TEXTURE_2D, t)
print "texture", 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)
glutInit( sys.argv )
#glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH )
glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH )
glutInitWindowSize( 500, 500 )
glutInitWindowPosition(0,0)
glutCreateWindow( 'cube' )
glutDisplayFunc( display )
glutKeyboardFunc(mykey)
glEnable(GL_DEPTH_TEST) #hidden-surface removal
# glEnable(GL_CULL_FACE) #don't draw back side surface
# glCullFace(GL_BACK) #don't draw back side surface
### TEXTURE
glEnable(GL_TEXTURE_2D)
# generate continuous two texture
# different format from C, void glGenTexture(n, *name)
texture=glGenTextures(6)
gentex(texture[0], "./pcube/r1.bmp")
gentex(texture[1], "./pcube/r2.bmp")
gentex(texture[2], "./pcube/r3.bmp")
gentex(texture[3], "./pcube/r4.bmp")
gentex(texture[4], "./pcube/rb.bmp")
gentex(texture[5], "./pcube/rt.bmp")
glutMainLoop()
0 件のコメント:
コメントを投稿