I have been using pickle to save to a file anything I've wanted to, such as class. It lets me later reload them when I start the application, allowing me to skip the initialization process.
However, when trying to save this map class (that I found on the pygame website: it renders height maps into terrains in pygame/opengl), I found that the terrains took quite a long time to load. I thought I could cheat and only initialize it the first time I ever started the game, and then dump it into a file (called map.pom
) to be used during subsequent game starts. This should let me jump into the game almost instantaneously.
But I'm having trouble, as it won't at all draw onto the screen anymore.
The following is my code:
Map class:
class glLibObjMap(glLibObj):
def __init__(self,mapdata,texturing=False,normals=None,heightscalar=1.0):
texturemap = []
normalmap = []
for z in xrange(len(mapdata)):
normalrow = []
texturerow = []
for x in xrange(len(mapdata[0])):
if normals == GLLIB_VERTEX_NORMALS:
Normals = []
t = 0
flip = True
leftpoint = rightpoint = uppoint = downpoint = False
normalpoint = (x, heightscalar*mapdata[z ][x ],z )
if x-1 >= 0: leftpoint = (x-1,heightscalar*mapdata[z ][x-1],z )#; print "leftpoint", leftpoint
if x+1 <= len(mapdata[0])-1: rightpoint = (x+1,heightscalar*mapdata[z ][x+1],z )#; print "rightpoint", rightpoint
if z+1 <= len(mapdata)-1: uppoint = (x, heightscalar*mapdata[z+1][x ],z+1)#; print "uppoint", uppoint
if z-1 >= 0: downpoint = (x, heightscalar*mapdata[z-1][x ],z-1)#; print "downpoint", downpoint
if rightpoint and uppoint: Normals.append(GetNormal(normalpoint,rightpoint,uppoint,flip))
if uppoint and leftpoint: Normals.append(GetNormal(normalpoint,uppoint,leftpoint,flip))
if leftpoint and downpoint: Normals.append(GetNormal(normalpoint,leftpoint,downpoint,flip))
if downpoint and rightpoint: Normals.append(GetNormal(normalpoint,downpoint,rightpoint,flip))
xcomp = []; ycomp = []; zcomp = []
for n in Normals:
xcomp.append(n[0]);ycomp.append(n[1]);zcomp.append(n[2])
normal = (sum(xcomp)/len(xcomp),sum(ycomp)/len(ycomp),sum(zcomp)/len(zcomp))
l = sqrt((normal[0]**2)+(normal[1]**2)+(normal[2]**2))
normal = [normal[0]/l,normal[1]/l,normal[2]/l]
normalrow.append(normal)
if texturing != False:
xtexcoord = float(x)/(len(mapdata[0])-1)
ytexcoord = float(z)/(len(mapdata)-1)
texturerow.append((xtexcoord,ytexcoord))
normalmap.append(normalrow)
texturemap.append(texturerow)
self.list = glGenLists(1)
glNewList(self.list, GL_COMPILE)
alreadytexturing = glGetBooleanv(GL_TEXTURE_2D)
if texturing:
glLibSelectTexture(texturing)
for z in xrange(len(mapdata)-1):
zrow1 = mapdata[z-1]
zrow2 = mapdata[z-1+1]
for x in xrange(len(zrow1)-1):
glBegin(GL_TRIANGLE_FAN)
# glBegin(GL_LINES)
if normals == GLLIB_FACE_NORMALS:
Normals = []
Normals.append(GetNormal((x, heightscalar*mapdata[z-1 ][x-1 ],z ),(x, heightscalar*mapdata[z-1+1][x-1 ],z+1),(x+1,heightscalar*mapdata[z-1 ][x-1+1],z )))
Normals.append(GetNormal((x, heightscalar*mapdata[z-1+1][x-1 ],z+1),(x+1,heightscalar*mapdata[z-1+1][x-1+1],z+1),(x, heightscalar*mapdata[z-1 ][x-1 ],z )))
Normals.append(GetNormal((x+1,heightscalar*mapdata[z-1 ][x-1+1],z ),(x, heightscalar*mapdata[z-1 ][x-1 ],z ),(x+1,heightscalar*mapdata[z-1+1][x-1+1],z+1)))
Normals.append(GetNormal((x+1,heightscalar*mapdata[z-1+1][x-1+1],z+1),(x+1,heightscalar*mapdata[z-1 ][x-1+1],z ),(x, heightscalar*mapdata[z-1+1][x-1 ],z+1)))
xcomp = []; ycomp = []; zcomp = []
for n in Normals:
xcomp.append(n[0]);ycomp.append(n[1]);zcomp.append(n[2])
normal = (sum(xcomp)/4.0,sum(ycomp)/4.0,sum(zcomp)/4.0)
l = sqrt((normal[0]**2)+(normal[1]**2)+(normal[2]**2))
normal = [normal[0]/l,normal[1]/l,normal[2]/l]
glNormal3f(*normal)
if normals == GLLIB_VERTEX_NORMALS: glNormal3f(*normalmap[z-1 ][x-1 ])
if texturing: glTexCoord2f(*texturemap[z ][x ])
glVertex3f(x, heightscalar*zrow1[x-1 ],z )
if normals == GLLIB_VERTEX_NORMALS: glNormal3f(*normalmap[z-1 ][x-1+1])
if texturing: glTexCoord2f(*texturemap[z ][x+1])
glVertex3f(x+1,heightscalar*zrow1[x-1+1],z )
if normals == GLLIB_VERTEX_NORMALS: glNormal3f(*normalmap[z-1+1][x-1+1])
if texturing: glTexCoord2f(*texturemap[z+1][x+1])
glVertex3f(x+1,heightscalar*zrow2[x-1+1],z+1)
if normals == GLLIB_VERTEX_NORMALS: glNormal3f(*normalmap[z-1+1][x-1 ])
if texturing: glTexCoord2f(*texturemap[z+1][x ])
glVertex3f(x, heightscalar*zrow2[x-1 ],z+1)
glEnd()
if alreadytexturing: glEnable(GL_TEXTURE_2D)
glEndList()
def draw(self,pos=[0,0,0],rotations=[],scalar=1.0):
glPushMatrix()
glTranslatef(*pos)
for rotation in rotations:
if rotation[0] != 0: glRotatef(rotation[0],1,0,0)
if rotation[1] != 0: glRotatef(rotation[1],0,1,0)
if rotation[2] != 0: glRotatef(rotation[2],0,0,1)
glScalef(scalar,scalar,scalar)
glCallList(self.list)
glPopMatrix()
def __del__(self):
del self.list
And my test program
from OpenGL import *
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
import os, sys
from OpenGLLibrary import *
import pickle
pygame.init()
Screen = (800,600)
Window = glLibWindow(Screen,caption="Map",multisample=True)
View3D = glLibView3D((0,0,Screen[0],Screen[1]),65)
View3D.set_view()
LightFocus = [0,0,0]
LightColor = (255,255,255)
ShadowColor = (153,153,153)
ShadowMapSize = 500
glLibTexturing(True)
glLibLighting(True)
Sun = glLibLight([0,20.0,10],color=LightColor,diffusecolor=ShadowColor)
Sun.enable()
Objects = [glLibObjFromFile("ExamplesData/Spikey.obj"),
glLibObjFromFile("ExamplesData/UberBall.obj"),
glLibObjCylinder(0.5,1.0,64),
glLibObjSphere(64)]
### WHAT ID LIKE TO DO ###
### THIS PART ONLY ON FIRST RUN ###
print 'Loading map...'
Mesh = []
heightmap = pygame.image.load(os.path.join("ExamplesData","heightmap.jpg"))
for x in xrange(heightmap.get_height()):
xrow = []
for y in xrange(heightmap.get_height()):
color = heightmap.get_at((x,y))
height = color[0]*0.02
xrow.append(height)
Mesh.append(xrow)
Map = glLibObjMap(Mesh,texturing=False,normals=GLLIB_VERTEX_NORMALS,heightscalar=10)
pickle.dump(Map, open("ExamplesData/map.pom", 'wb'))
print 'End.'
### THIS PART ON THE NEXT RUNS ###
Map = pickle.load(open("ExamplesData/map.pom", 'rb')) # on other runs
glLibShadowInit([[ShadowMapSize,5]])
# CAMERA ##
pos = [2,-20,2]
amountRotate = [0,0,0,0]
glTranslatef(pos[0],pos[1], pos[2])
print 'Loaded...'
def RenderFloor():
Map.draw([-100,0,30],[[0,150,0]])
objpos = [2,-100,2]
objectdrawing = 0
def RenderObj():
Objects[objectdrawing].draw([objpos[0],objpos[1],objpos[2]],scalar=1.0)
def GetInput():
global CameraRotation, LightPosition, objpos, objectdrawing
mpress = pygame.mouse.get_pressed()
mrel = pygame.mouse.get_rel()
key = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == QUIT or key[K_ESCAPE]:
pygame.quit(); sys.exit()
if event.type == KEYDOWN and event.key == K_RETURN:
objectdrawing += 1
if objectdrawing == 6:
objectdrawing = 0
if event.type == KEYDOWN and (event.key == K_w or event.key == K_UP):
pos[2] += 5
elif event.type == KEYDOWN and (event.key == K_a or event.key == K_LEFT):
pos[0] += 5
elif event.type == KEYDOWN and (event.key == K_s or event.key == K_DOWN):
pos[2] -= 5
elif event.type == KEYDOWN and (event.key == K_d or event.key == K_RIGHT):
pos[0] -= 5
elif event.type == KEYDOWN and event.key == K_1:
amountRotate[0] += 5
elif event.type == KEYDOWN and event.key == K_2:
amountRotate[0] -= 5
elif event.type == KEYDOWN and event.key == K_3:
amountRotate[1] += 5
elif event.type == KEYDOWN and event.key == K_4:
amountRotate[1] -= 5
elif event.type == KEYDOWN and event.key == K_5:
amountRotate[2] += 5
elif event.type == KEYDOWN and event.key == K_6:
amountRotate[2] -= 5
elif event.type == KEYDOWN and event.key == K_7:
amountRotate[3] += 5
elif event.type == KEYDOWN and event.key == K_8:
amountRotate[3] -= 5
if mpress[0]:
objpos[0] -= 0.1*mrel[0]
objpos[2] -= 0.1*mrel[1]
if mpress[2]:
formerpos = Sun.get_pos()
Sun.change_pos([formerpos[0]-0.1*mrel[0],formerpos[1],formerpos[2]-0.1*mrel[1]])
def Draw():
global LightFocus
#Clear
Window.clear()
#glLib step 1
LightPosition = Sun.get_pos()
LightFocus = [objpos[0],objpos[1],objpos[2]]
dist = sqrt(((LightFocus[0]-LightPosition[0])**2)+((LightFocus[1]-LightPosition[1])**2)+((LightFocus[2]-LightPosition[2])**2))
lightangle = degrees(2*asin((2.9*1.0)/dist))
near = dist - 2.9
far = dist + 2.9
glLibCreateShadowBefore(GLLIB_SHADOW_MAP1,LightPosition,LightFocus,lightviewangle=lightangle,near=near,far=far)
#Render all objects that should cast shadows
RenderObj()
#glLib step 2
glLibCreateShadowAfter(GLLIB_SHADOW_MAP1)
#Clear
Window.clear()
#Position the camera
View3D.set_view()
glTranslatef(pos[0],pos[1], pos[2])
glRotatef(amountRotate[0],amountRotate[1],amountRotate[2], amountRotate[3])
#Set the light
Sun.change_color((153,153,153))
Sun.change_diffuse_color((255,255,255))
Sun.draw()
Sun.draw_as_point()
#Render everything
RenderObj()
RenderFloor()
#glLib step 3
glLibRenderShadowCompareBefore(GLLIB_SHADOW_MAP1)
#Set light color to shadow color
Sun.change_diffuse_color(ShadowColor)
#Render all objects where shadows should be cast
RenderObj()
RenderFloor()
#glLib step 4
glLibRenderShadowCompareAfter()
#Flip
Window.flip()
def main():
while True:
GetInput()
Draw()
if __name__ == '__main__': main()