Pyglet textures are messed up - python

I have been following an Pyglet OpenGL tutorial on Youtube here and I followed it around a year or two ago. It worked quite well and I managed to make a Minecraft clone which included simple physics. Now, I've lost the code and I tried to recreate it. I followed the video, but it took too long so I just downloaded it from the link. Then, the only thing I replaced was the tex = pyglet.image.load(file).texture, because apparently I should use tex = pyglet.image.load(file).get_texture(). Then, when I ran it, the cube looked very distorted and the textures were all in the wrong place. Here are links to the cube pictures:
The code is here:
from pyglet.gl import *
from pyglet.window import key
import math
class Model:
def get_tex(self,file):
tex = pyglet.image.load(file).get_texture()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def __init__(self):
self.top = self.get_tex('grass_top.png')
self.side = self.get_tex('grass_side.png')
self.bottom = self.get_tex('dirt.png')
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f',(0,0, 1,0, 1,1, 0,1, ))
x,y,z = -1,-1,-1
X,Y,Z = x+2,y+2,z+2
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]-=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def update(self,dt,keys):
s = dt*10
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(90,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300, 200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model()
self.player = Player((0,0,5),(0,0))
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE: self.close()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
glPopMatrix()
if __name__ == '__main__':
window = Window(width=854,height=480,caption='Minecraft',resizable=True)
glClearColor(0.5,0.7,1,1)
glEnable(GL_DEPTH_TEST)
# glEnable(GL_CULL_FACE)
pyglet.app.run()
Note: I fiddled with the textures and when I replaced the batch adds with this:
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z)), tex_coords)
The cube was textured properly. Any ideas why?
Also, when I only drew one side, it was in the right place but the texture was bending over the face, as if it were two triangles.

You have to enable the Depth Test:
if __name__ == "__main__":
window = Window(width = 400, height = 300, caption = "Minecraft", resizable = True)
glClearColor(0.5, 0.7, 1, 1)
glEnable(GL_DEPTH_TEST) # <----
pyglet.app.run()
Note that the cube appears to be screwed up since the front of the cube doesn't cover the back. The depth test ensures that a geometry that has already been drawn is not covered by a new geometry that is behind it.

I found the answer. After testing the exact same code on a newer PC, it worked. Seems like I have an outdated GPU or graphics driver, just like Rabbid76 said.

Related

Annotate draggable Circle

I am looking to annotate a draggable circle with a number. The draggeable point is created from this class:
class DraggablePoint:
lock = None #only one can be animated at a time
def __init__(self, point):
self.point = point
self.press = None
self.background = None
def connect(self):
'connect to all the events we need'
self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.on_press)
self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event', self.on_release)
self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_press(self, event):
if event.inaxes != self.point.axes: return
if DraggablePoint.lock is not None: return
contains, attrd = self.point.contains(event)
if not contains: return
self.press = (self.point.center), event.xdata, event.ydata
DraggablePoint.lock = self
# draw everything but the selected point and store the pixel buffer
canvas = self.point.figure.canvas
axes = self.point.axes
self.point.set_animated(True)
canvas.draw()
self.background = canvas.copy_from_bbox(self.point.axes.bbox)
# now redraw just the rectangle
axes.draw_artist(self.point)
# and blit just the redrawn area
canvas.blit(axes.bbox)
def on_motion(self, event):
if DraggablePoint.lock is not self:
return
if event.inaxes != self.point.axes: return
self.point.center, xpress, ypress = self.press
dx = event.xdata - xpress
dy = event.ydata - ypress
self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy)
canvas = self.point.figure.canvas
axes = self.point.axes
# restore the background region
canvas.restore_region(self.background)
# redraw just the current rectangle
axes.draw_artist(self.point)
# blit just the redrawn area
canvas.blit(axes.bbox)
def on_release(self, event):
'on release we reset the press data'
if DraggablePoint.lock is not self:
return
self.press = None
DraggablePoint.lock = None
# turn off the rect animation property and reset the background
self.point.set_animated(False)
self.background = None
# redraw the full figure
self.point.figure.canvas.draw()
def disconnect(self):
'disconnect all the stored connection ids'
self.point.figure.canvas.mpl_disconnect(self.cidpress)
self.point.figure.canvas.mpl_disconnect(self.cidrelease)
self.point.figure.canvas.mpl_disconnect(self.cidmotion)
I am plotting with this (circles.append + the last loop is the interesting code for this problem):
drs = []
circles = []
for team, color, sec_color in zip([hometeam.loc[frame], awayteam.loc[frame]], team_colors, sec_colors):
x_columns = [c for c in team.keys() if
c[-2:].lower() == '_x' and c != 'ball_x'] # column header for player x positions
y_columns = [c for c in team.keys() if
c[-2:].lower() == '_y' and c != 'ball_y'] # column header for player y positions
for x, y in zip(team[x_columns], team[y_columns]):
#if ctr == 0:
circles.append(patches.Circle((x, y), 1.4, fc=color, edgecolor=sec_color, linewidth=1.2, zorder=2))
for circ in circles:
ax.add_patch(circ)
dr = DraggablePoint(circ)
dr.connect()
drs.append(dr)
plt.show()
I can plot text at the circles center, however once I drag a circle, the text stays at the original position. Is there a way to add text to the circles, which would move alongside the circles when dragged?
Sure. Add a label, record the relative position to the circle, and update its position on motion.
import matplotlib.pyplot as plt
class DraggablePoint:
...
class LabelledDraggablePoint(DraggablePoint):
def __init__(self, point, label):
super().__init__(point)
self.label = label
x1, y1 = self.label.get_position()
x2, y2 = self.point.center
self.label_offset = (x1 - x2, y1 - y2)
def on_motion(self, event):
super().on_motion(event)
self.label.set_position(self.point.center + self.label_offset)
if __name__ == '__main__':
fig, ax = plt.subplots()
point = plt.Circle((0.5, 0.5), 0.1)
ax.add_patch(point)
ax.set_aspect('equal')
label = ax.text(0.5, 0.5, 'Lorem ipsum', ha='center', va='center')
instance = LabelledDraggablePoint(point, label)
instance.connect()
plt.show()
On a different note: the blitting is nausea inducing. You will get much smoother animations without it. I would cut all of that out.

Pyglet 3-D's rendering is putting extra pixels in an image

I have Python 3.8.2, and I'm trying to create my own minecraft armor renderer, and I've run into a problem that I just can't wrap my head around (Render). Obviously I don't want the top of the shoulder to be floating above the shoulder, but it isn't anything to do with the texture (An Example Texture which I got directly by saving the pyglet texture).
How do I fix this and how can I avoid this in the future? If you need me to give more information or more specific information, I can update this and respond. (I'm new to pyglet, so criticism and advice welcome.)
My two armor layers: (Armor Layer 1, Armor Layer 2)
The code I'm worried about:
from pyglet.window import key
import math, os, shutil
from PIL import Image, ImageOps
class Model():
def get_tex(self,file):
tex = pyglet.image.load(file).get_texture()
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
return pyglet.graphics.TextureGroup(tex)
def __init__(self,pos = (0,0,-1),size = (16,16,16),bottom='ancient_debris_top.png',top='ancient_debris_top.png',back='ancient_debris_side.png',front='ancient_debris_side.png',left='ancient_debris_side.png',right='ancient_debris_side.png'):
self.top = self.get_tex(top)
self.bottom = self.get_tex(bottom)
self.back = self.get_tex(back)
self.front = self.get_tex(front)
self.left = self.get_tex(left)
self.right = self.get_tex(right)
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f',(0,0, 1,0, 1,1, 0,1, ))
x,y,z = pos[0]*4, pos[1]*4, pos[2]*4
X,Y,Z = x+size[0]/4,y+size[1]/4,z+size[2]/4
self.batch.add(4,GL_QUADS,self.left,('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.right,('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.bottom,('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.top,('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.back,('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.front,('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z, )),tex_coords)
def draw(self):
self.batch.draw()
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(70,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300,200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model(pos=(0,1,-1),size=(8,8,8),front='head/head_front.png',back='head/head_back.png',top='head/head_top.png',bottom='head/head_bottom.png',left='head/head_left.png',right='head/head_right.png')
self.model2 = Model(pos=(0,0.375,-0.875),size=(8,12,4),front='chest/chest_front.png',back='chest/chest_back.png',top='chest/chest_top.png',bottom='chest/chest_bottom.png',left='chest/chest_left.png',right='chest/chest_right.png')
self.model3 = Model(pos=(0.5,0.375,-0.875),size=(4,12,4),front='shoulder_right/shoulder_right_front.png',back='shoulder_right/shoulder_right_back.png',top='shoulder_right/shoulder_right_top.png',bottom='shoulder_right/shoulder_right_bottom.png',left='shoulder_right/shoulder_right_left.png',right='shoulder_right/shoulder_right_right.png')
self.model4 = Model(pos=(-0.25,0.375,-0.875),size=(4,12,4),front='shoulder_left/shoulder_left_front.png',back='shoulder_left/shoulder_left_back.png',top='shoulder_left/shoulder_left_top.png',bottom='shoulder_left/shoulder_left_bottom.png',left='shoulder_left/shoulder_left_left.png',right='shoulder_left/shoulder_left_right.png')
self.player = Player((0.5,1.5,1.5),(-30,0))
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE:
self.close()
rmallfolders()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
self.model2.draw()
self.model3.draw()
self.model4.draw()
glPopMatrix()
My entire code:
from pyglet.window import key
import math, os, shutil
from PIL import Image, ImageOps
class Model():
def get_tex(self,file):
tex = pyglet.image.load(file).get_texture()
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
return pyglet.graphics.TextureGroup(tex)
def __init__(self,pos = (0,0,-1),size = (16,16,16),bottom='ancient_debris_top.png',top='ancient_debris_top.png',back='ancient_debris_side.png',front='ancient_debris_side.png',left='ancient_debris_side.png',right='ancient_debris_side.png'):
self.top = self.get_tex(top)
self.bottom = self.get_tex(bottom)
self.back = self.get_tex(back)
self.front = self.get_tex(front)
self.left = self.get_tex(left)
self.right = self.get_tex(right)
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f',(0,0, 1,0, 1,1, 0,1, ))
x,y,z = pos[0]*4, pos[1]*4, pos[2]*4
X,Y,Z = x+size[0]/4,y+size[1]/4,z+size[2]/4
self.batch.add(4,GL_QUADS,self.left,('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.right,('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.bottom,('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.top,('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.back,('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z, )),tex_coords)
self.batch.add(4,GL_QUADS,self.front,('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z, )),tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]-=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def update(self,dt,keys):
s = dt*10
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(70,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300,200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model(pos=(0,1,-1),size=(8,8,8),front='head/head_front.png',back='head/head_back.png',top='head/head_top.png',bottom='head/head_bottom.png',left='head/head_left.png',right='head/head_right.png')
self.model2 = Model(pos=(0,0.375,-0.875),size=(8,12,4),front='chest/chest_front.png',back='chest/chest_back.png',top='chest/chest_top.png',bottom='chest/chest_bottom.png',left='chest/chest_left.png',right='chest/chest_right.png')
self.model3 = Model(pos=(0.5,0.375,-0.875),size=(4,12,4),front='shoulder_right/shoulder_right_front.png',back='shoulder_right/shoulder_right_back.png',top='shoulder_right/shoulder_right_top.png',bottom='shoulder_right/shoulder_right_bottom.png',left='shoulder_right/shoulder_right_left.png',right='shoulder_right/shoulder_right_right.png')
self.model4 = Model(pos=(-0.25,0.375,-0.875),size=(4,12,4),front='shoulder_left/shoulder_left_front.png',back='shoulder_left/shoulder_left_back.png',top='shoulder_left/shoulder_left_top.png',bottom='shoulder_left/shoulder_left_bottom.png',left='shoulder_left/shoulder_left_left.png',right='shoulder_left/shoulder_left_right.png')
self.player = Player((0.5,1.5,1.5),(-30,0))
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE:
self.close()
rmallfolders()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
self.model2.draw()
self.model3.draw()
self.model4.draw()
glPopMatrix()
def readfile1(filename):
rawimage=Image.open(filename)
#left, top, right, bottom
head_top = rawimage.crop((8,0,16,8)); head_left = rawimage.crop((0,8,8,16)); head_front = rawimage.crop((8,8,16,16)); head_right = rawimage.crop((16,8,24,16)); head_back = rawimage.crop((24,8,32,16)); head_bottom=Image.open("empty_bottom_head.png"); os.mkdir("head")
head_top.save('head/head_top.png'); head_left.save('head/head_left.png'); head_front.save('head/head_front.png'); head_right.save('head/head_right.png'); head_back.save('head/head_back.png'); head_bottom.save('head/head_bottom.png')
chest_top = Image.open("empty_bottom_head.png"); chest_front = rawimage.crop((20,20,28,32)); chest_left = rawimage.crop((16,20,20,32)); chest_right = rawimage.crop((28,20,32,32)); chest_back = rawimage.crop((32,20,40,32)); chest_bottom = Image.open("empty_bottom_head.png"); os.mkdir("chest")
chest_top.save('chest/chest_top.png'); chest_left.save('chest/chest_left.png'); chest_front.save('chest/chest_front.png'); chest_right.save('chest/chest_right.png'); chest_back.save('chest/chest_back.png'); chest_bottom.save('chest/chest_bottom.png')
shoulder_right_top = rawimage.crop((44,16,48,20)); shoulder_right_front = rawimage.crop((44,20,48,32)); shoulder_right_left = rawimage.crop((40,20,44,32)); shoulder_right_right = rawimage.crop((48,20,52,32)); shoulder_right_back = rawimage.crop((52,20,56,32)); shoulder_right_bottom = Image.open("empty_bottom_head.png"); os.mkdir("shoulder_right")
shoulder_right_top.save('shoulder_right/shoulder_right_top.png'); shoulder_right_left.save('shoulder_right/shoulder_right_left.png'); shoulder_right_front.save('shoulder_right/shoulder_right_front.png'); shoulder_right_right.save('shoulder_right/shoulder_right_right.png'); shoulder_right_back.save('shoulder_right/shoulder_right_back.png'); shoulder_right_bottom.save('shoulder_right/shoulder_right_bottom.png')
shoulder_left_top = ImageOps.mirror(shoulder_right_top); shoulder_left_bottom = ImageOps.mirror(shoulder_right_bottom); shoulder_left_right = ImageOps.mirror(shoulder_right_left); shoulder_left_left = ImageOps.mirror(shoulder_right_right); shoulder_left_front = ImageOps.mirror(shoulder_right_front); shoulder_left_back = ImageOps.mirror(shoulder_right_back); os.mkdir('shoulder_left')
shoulder_left_top.save('shoulder_left/shoulder_left_top.png'); shoulder_left_left.save('shoulder_left/shoulder_left_left.png'); shoulder_left_front.save('shoulder_left/shoulder_left_front.png'); shoulder_left_right.save('shoulder_left/shoulder_left_right.png'); shoulder_left_back.save('shoulder_left/shoulder_left_back.png'); shoulder_left_bottom.save('shoulder_left/shoulder_left_bottom.png')
def rmallfolders():
folders = ['head','chest','shoulder_right','shoulder_left']
for i in folders:
try:
shutil.rmtree(i)
except:
pass
if __name__ == '__main__':
rmallfolders()
readfile1('ruby_layer_1.png')
window = Window(width=854,height=480,caption='3-D Modeller',resizable=True)
glClearColor(0.5,0.7,1,1)
glEnable(GL_DEPTH_TEST)
#glEnable(GL_CULL_FACE)
pyglet.app.run()
Thanks so much!

Pyglet texture doesn't cover the square

Im programming a simple pyglet example in pyglet 1.3.0 but i have a problem. I have also tested other pyglet versions but the problem still there.
No error is displayed but the texture only appears in a part of the square. I'm using python 3.7.
Here is the code:
from pyglet.gl import *
from pyglet.window import key
import resources
import math
class Model:
def get_tex(self, file):
tex = pyglet.image.load(file).texture
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def __init__(self):
self.top = self.get_tex("grass_tex.jpg")
self.bottom = self.get_tex("grass_tex.jpg")
self.side = self.get_tex("terrain_tex.jpg")
self.batch = pyglet.graphics.Batch()
tex_coords = ("t2f", (0,0, 1,0, 1,1, 0,1, ))
#color = ("c3f", (1, 1, 1)*4)
x, y, z = 0, 0, -1
X, Y, Z = x+1, y+1, z+1
self.batch.add(4, GL_QUADS, self.top, ("v3f", (x,y,z, X,y,z, X,Y,z, x,Y,z, )), tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self):
self.pos = [0, 0, 0]
self.rot = [0, 0]
def update(self, dt, keys):
pass
class Window(pyglet.window.Window):
def Projection(self):
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
def Model(self):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def set2d(self):
self.Projection()
gluOrtho2D(0, self.width, 0, self.height)
self.Model()
def set3d(self):
self.Projection()
gluPerspective(70, self.width/self.height, 0.05, 1000)
self.Model()
def setLock(self, state):
self.lock = state
self.set_exclusive_mouse(state)
lock = False
mouse_lock = property(lambda self:self.lock, setLock)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.model = Model()
self.player = Player()
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
def on_key_press(self, KEY, MOD):
if KEY == key.ESCAPE:
self.close()
elif KEY == key.SPACE:
self.mouse_lock = not self.mouse_lock
def update(self, dt):
self.player.update(dt, self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.model.draw()
if __name__ == "__main__":
window = Window(width=400, height=300, caption="gamelearn2", resizable=False)
glClearColor(0.5, 0.7, 1, 1)
pyglet.app.run()
And this is the error:
When you use a perspective projection gluPerspective, then the (0, 0) is in the center of the viewport.
You have to draw the quad with the texture from (-1, -1) to (1, 1) and at a depth of 1 (z = -1).
x, y, z = -1, -1, -1
X, Y = 1, 1
self.batch.add(4, GL_QUADS, self.top, ("v3f", (x,y,z, X,y,z, X,Y,z, x,Y,z, )), tex_coords)
Furthermore use a field of view angle of 90°:
class Window(pyglet.window.Window):
# [...]
def set3d(self):
self.Projection()
gluPerspective(90, self.width/self.height, 0.05, 1000)
self.Model()

Python: How do I generate minecraft style terrain with pyglet?

I'm currently trying to make a Minecraft clone using pyglet and python for fun, and I found a nice tutorial which I used to create a player class with movement, and a 3D block that generates in the scene.
Now I want to create some sort of a terrain, I read about terrain generating and I stumbled upon a function called "noise function" which seems to fit nicely with one I'm trying to do. sadly I don't really know how to implement it. :(
At first I tried to generate a flat terrain by creating a function in the Model class which contains the code that creates a cube, and then I create a loop that generates all the numbers between 1 and 20 for example, and use them as values to the cube function. but it didn't work so i had to remove it :(
I do think that it might be too soon to implement a terrain with the noise function seeing the stage I'm currently in. so creating an endless flat terrain that do work will be good as well :D
If you want to check the program, You'll need to press 'E' when you run the code to enable a mouse lock, which will let you to move the mouse and the player in the scene.
Here is the code I have:
from pyglet.gl import *
from pyglet.window import key
import math
import random
from random import *
class Model:
def get_tex(self, file):
tex = pyglet.image.load(file).texture
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def __init__(self):
self.top = self.get_tex('grass_top.png')
self.side = self.get_tex('grass_side.png')
self.bottom = self.get_tex('dirt.png')
self.batch = pyglet.graphics.Batch()
tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1,))
x, y, z = randint(0, 5), randint(0, 5), -1
X, Y, Z = x+1, y+1, z+1
self.batch.add(4, GL_QUADS, self.side, ('v3f', (x, y, z, x, y, Z, x, Y, Z, x, Y, z,)), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f', (X, y, Z, X, y, z, X, Y, z, X, Y, Z,)), tex_coords)
self.batch.add(4, GL_QUADS, self.bottom, ('v3f', (x, y, z, X, y, z, X, y, Z, x, y, Z,)), tex_coords)
self.batch.add(4, GL_QUADS, self.top, ('v3f', (x, Y, Z, X, Y, Z, X, Y, z, x, Y, z, )), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f', (X, y, z, x, y, z, x, Y, z, X, Y, z, )), tex_coords)
self.batch.add(4, GL_QUADS, self.side, ('v3f', (x, y, Z, X, y, Z, X, Y, Z, x, Y, Z, )), tex_coords)
def draw(self):
self.batch.draw()
class Player:
def __init__(self, pos=(0, 0, 0), rot=(0, 0)):
self.pos = list(pos)
self.rot = list(rot)
def mouse_motion(self, dx, dy):
dx /= 8
dy /= 8
self.rot[0] += dy
self.rot[1] -= dx
if self.rot[0] > 90:
self.rot[0] = 90
elif self.rot[0] < -90:
self.rot[0] = -90
def update(self, dt, keys):
s = dt*10
rotation_y = -self.rot[1]/180*math.pi
dx, dz = s*math.sin(rotation_y), s*math.cos(rotation_y)
if keys[key.W]:
self.pos[0] += dx
self.pos[2] -= dz
if keys[key.S]:
self.pos[0] -= dx
self.pos[2] += dz
if keys[key.A]:
self.pos[0] -= dz
self.pos[2] -= dx
if keys[key.D]:
self.pos[0] += dz
self.pos[2] += dx
if keys[key.SPACE]:
self.pos[1] += s
if keys[key.LSHIFT]:
self.pos[1] -= s
class Window(pyglet.window.Window):
def push(self, pos, rot):
glPushMatrix()
glRotatef(-rot[0], 1, 0, 0)
glRotatef(-rot[1], 0, 1, 0)
glTranslatef(-pos[0], -pos[1], -pos[2],)
def Projection(self):
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
def Model(self):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def set2d(self):
self.Projection()
gluOrtho2D(0, self.width, 0, self.height)
self.Model()
def set3d(self):
self.Projection()
gluPerspective(70, self.width / self.height, 0.05, 1000)
self.Model()
def setLock(self, state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self: self.lock, setLock)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_minimum_size(300, 200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.model = Model()
self.player = Player((0.5, 1.5, 1.5), (-30, 0))
def on_mouse_motion(self, x, y, dx, dy):
if self.mouse_lock:
self.player.mouse_motion(dx, dy)
def on_key_press(self, KEY, MOD):
if KEY == key.ESCAPE:
self.close()
elif KEY == key.E:
self.mouse_lock = not self.mouse_lock
def update(self, dt):
self.player.update(dt, self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos, self.player.rot)
self.model.draw()
glPopMatrix()
if __name__ == '__main__':
window = Window(width=854, height=480, caption='Minecraft', resizable=True)
glClearColor(0.5, 0.7, 1, 1)
glEnable(GL_DEPTH_TEST)
# glEnable(GL_CULL_FACE)
pyglet.app.run()
My project use's some images to create the dirt texture. so here is a link to a website which has the images and the main program which you can see above you:
http://www.mediafire.com/file/7iolhmh1hqj9516/Basic+Pyglet+Cube.rar
I already tried to generate more then one block using a list and recalling a function
You could create a function to show a block at the given position and with the texture texture:
def show_block(self, position, texture):
top = texture[0]
side = texture[1]
bottom = texture[2]
x, y, z = position
X, Y, Z = x+1,y+1, z+1
tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1,))
self.batch.add(4, GL_QUADS, side, ('v3f', (x, y, z, x, y, Z, x, Y, Z, x, Y, z,)), tex_coords)
self.batch.add(4, GL_QUADS, side, ('v3f', (X, y, Z, X, y, z, X, Y, z, X, Y, Z,)), tex_coords)
self.batch.add(4, GL_QUADS, bottom, ('v3f', (x, y, z, X, y, z, X, y, Z, x, y, Z,)), tex_coords)
self.batch.add(4, GL_QUADS, top, ('v3f', (x, Y, Z, X, Y, Z, X, Y, z, x, Y, z, )), tex_coords)
self.batch.add(4, GL_QUADS, side, ('v3f', (X, y, z, x, y, z, x, Y, z, X, Y, z, )), tex_coords)
self.batch.add(4, GL_QUADS, side, ('v3f', (x, y, Z, X, y, Z, X, Y, Z, x, Y, Z, )), tex_coords)
Then you could use perlin to generate terrain:
class Perlin:
def __call__(self,x,y): return (self.noise(x*self.f,y*self.f)+1)/2
def __init__(self,seed=None):
self.f = 15/512; self.m = 65535; p = list(range(self.m))
if seed: random.seed(seed)
random.shuffle(p); self.p = p+p
def fade(self,t): return t*t*t*(t*(t*6-15)+10)
def lerp(self,t,a,b): return a+t*(b-a)
def grad(self,hash,x,y,z):
h = hash&15; u = y if h&8 else x
v = (x if h==12 or h==14 else z) if h&12 else y
return (u if h&1 else -u)+(v if h&2 else -v)
def noise(self,x,y,z=0):
p,fade,lerp,grad = self.p,self.fade,self.lerp,self.grad
xf,yf,zf = math.floor(x),math.floor(y),math.floor(z)
X,Y,Z = xf%self.m,yf%self.m,zf%self.m
x-=xf; y-=yf; z-=zf
u,v,w = fade(x),fade(y),fade(z)
A = p[X ]+Y; AA = p[A]+Z; AB = p[A+1]+Z
B = p[X+1]+Y; BA = p[B]+Z; BB = p[B+1]+Z
return lerp(w,lerp(v,lerp(u,grad(p[AA],x,y,z),grad(p[BA],x-1,y,z)),lerp(u,grad(p[AB],x,y-1,z),grad(p[BB],x-1,y-1,z))),
lerp(v,lerp(u,grad(p[AA+1],x,y,z-1),grad(p[BA+1],x-1,y,z-1)),lerp(u,grad(p[AB+1],x,y-1,z-1),grad(p[BB+1],x-1,y-1,z-1))))
After all these changes, your code should look somewhat like this:
from pyglet.gl import *
from pyglet.window import key,mouse
from collections import deque
import sys, os, time, math, random
class Perlin:
def __call__(self,x,y): return int(sum(self.noise(x*s,y*s)*h for s,h in self.perlins)*self.avg)
def __init__(self):
self.m = 65536; p = list(range(self.m)); random.shuffle(p); self.p = p+p
p = self.perlins = tuple((1/i,i) for i in (16,20,22,31,32,64,512) for j in range(2))
self.avg = 8*len(p)/sum(f+i for f,i in p)
def fade(self,t): return t*t*t*(t*(t*6-15)+10)
def lerp(self,t,a,b): return a+t*(b-a)
def grad(self,hash,x,y,z):
h = hash&15; u = y if h&8 else x
v = (x if h==12 or h==14 else z) if h&12 else y
return (u if h&1 else -u)+(v if h&2 else -v)
def noise(self,x,y,z=0):
p,fade,lerp,grad = self.p,self.fade,self.lerp,self.grad
xf,yf,zf = math.floor(x),math.floor(y),math.floor(z)
X,Y,Z = xf%self.m,yf%self.m,zf%self.m
x-=xf; y-=yf; z-=zf
u,v,w = fade(x),fade(y),fade(z)
A = p[X ]+Y; AA = p[A]+Z; AB = p[A+1]+Z
B = p[X+1]+Y; BA = p[B]+Z; BB = p[B+1]+Z
return lerp(w,lerp(v,lerp(u,grad(p[AA],x,y,z),grad(p[BA],x-1,y,z)),lerp(u,grad(p[AB],x,y-1,z),grad(p[BB],x-1,y-1,z))),
lerp(v,lerp(u,grad(p[AA+1],x,y,z-1),grad(p[BA+1],x-1,y,z-1)),lerp(u,grad(p[AB+1],x,y-1,z-1),grad(p[BB+1],x-1,y-1,z-1))))
class Model:
alpha_textures = 'leaves_oak','tall_grass'
def load_textures(self):
t = self.texture = {}; self.texture_dir = {}; dirs = ['textures']
while dirs:
dir = dirs.pop(0); textures = os.listdir(dir)
for file in textures:
if os.path.isdir(dir+'/'+file): dirs+=[dir+'/'+file]
else:
n = file.split('.')[0]; self.texture_dir[n] = dir; image = pyglet.image.load(dir+'/'+file)
transparent = n in self.alpha_textures
texture = image.texture if transparent else image.get_mipmapped_texture()
self.texture[n] = pyglet.graphics.TextureGroup(texture)
if not transparent: glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
self.block = {}; self.ids = []; done = []
items = sorted(self.texture_dir.items(),key=lambda i:i[0])
for name,dir in items:
n = name.split(' ')[0]
if n in done: continue
done+=[n]
if dir.startswith('textures/blocks'):
self.ids+=[n]
if dir=='textures/blocks': self.block[n] = t[n],t[n],t[n],t[n],t[n],t[n]
elif dir=='textures/blocks/tbs': self.block[n] = t[n+' s'],t[n+' s'],t[n+' b'],t[n+' t'],t[n+' s'],t[n+' s']
elif dir=='textures/blocks/ts': self.block[n] = t[n+' s'],t[n+' s'],t[n+' t'],t[n+' t'],t[n+' s'],t[n+' s']
self.ids+=['water']
flow,still = t['water_flow'],t['water_still']
self.block['water'] = flow,flow,still,still,flow,flow
def draw(self):
glEnable(GL_ALPHA_TEST); self.opaque.draw(); glDisable(GL_ALPHA_TEST)
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); self.transparent.draw()
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); self.transparent.draw()
def update(self,dt):
self.cubes.water.update(dt)
def __init__(self):
self.opaque = pyglet.graphics.Batch()
self.transparent = pyglet.graphics.Batch()
self.load_textures()
self.cubes = CubeHandler(self)
perlin = Perlin()
for x in range(64):
for z in range(64):
y = perlin(x,z)
self.cubes.add((x,-y,-z),'grass')
for i in range(1,3): self.cubes.add((x,-i-y,-z),'dirt')
for cube in self.cubes.cubes.values(): self.cubes.update_cube(cube)
class Water:
def __init__(self,transparent):
self.transparent = transparent
self.time = {'still':TimeLoop(32),'flow':TimeLoop(32)}
self.coords = {'still':[],'flow':[]}; self.still_faces = {}; self.flow_faces = {}
for i in range(32-1,-1,-1):
y0 = i/16; y1 = (i+1)/16; self.coords['still'] += [[0,y0, 1,y0, 1,y1, 0,y1]]
y0 = i/32; y1 = (i+1)/32; self.coords['flow'] += [[0,y0, 1,y0, 1,y1, 0,y1]]
a,b = self.time['still'],self.time['flow']; self.t = b,b,a,a,b,b
a,b = self.coords['still'],self.coords['flow']; self.c = b,b,a,a,b,b
def update(self,dt):
if self.time['still'].update(dt*0.5):
for face,i in self.still_faces.items(): face.tex_coords = self.c[i][self.t[i].int]
if self.time['flow'].update(dt):
for face,i in self.flow_faces.items(): face.tex_coords = self.c[i][self.t[i].int]
def show(self,v,t,i):
face = self.transparent.add(4,GL_QUADS,t,('v3f',v),('t2f',self.c[i][0]))
faces = self.still_faces if i==2 or i==3 else self.flow_faces
faces[face] = i; return face
class CubeHandler:
def __init__(self,model):
self.model = model
self.opaque,self.transparent = model.opaque,model.transparent
self.block,self.alpha_textures = model.block,model.alpha_textures
self.water = Water(self.transparent)
self.cubes = {}
def hit_test(self,p,vec,dist=256):
if normalize(p) in self.cubes: return None,None
m = 8; x,y,z = p; dx,dy,dz = vec
dx/=m; dy/=m; dz/=m; prev = None
for i in range(dist*m):
key = normalize((x,y,z))
if key in self.cubes: return key,prev
prev = key
x,y,z = x+dx,y+dy,z+dz
return None,None
def show(self,v,t,i): return self.opaque.add(4,GL_QUADS,t,('v3f',v),('t2f',(0,0, 1,0, 1,1, 0,1)))
def update_cube(self,cube):
if not any(cube.shown.values()): return
show = self.water.show if cube.name=='water' else self.show
v = cube_vertices(cube.p)
f = 'left','right','bottom','top','back','front'
for i in (0,1,2,3,4,5):
if cube.shown[f[i]] and not cube.faces[f[i]]: cube.faces[f[i]] = show(v[i],cube.t[i],i)
def set_adj(self,cube,adj,state):
x,y,z = cube.p; X,Y,Z = adj; d = X-x,Y-y,Z-z; f = 'left','right','bottom','top','back','front'
for i in (0,1,2):
if d[i]:
j = i+i; a,b = [f[j+1],f[j]][::d[i]]; cube.shown[a] = state
if not state and cube.faces[a]: cube.faces[a].delete(); face = cube.faces[a]; cube.faces[a] = None; self.remove_water(face)
def add(self,p,t,now=False):
if p in self.cubes: return
cube = self.cubes[p] = Cube(t,p,self.block[t],'alpha' if t in self.alpha_textures else 'blend' if t=='water' else 'solid')
for adj in adjacent(*cube.p):
if adj not in self.cubes: self.set_adj(cube,adj,True)
else:
a,b = cube.type,self.cubes[adj].type
if a==b and (a=='solid' or b=='blend'): self.set_adj(self.cubes[adj],cube.p,False)
elif a!='blend' and b!='solid': self.set_adj(self.cubes[adj],cube.p,False); self.set_adj(cube,adj,True)
if now: self.update_cube(cube)
def remove_water(self,face):
if face in self.water.still_faces: del self.water.still_faces[face]
elif face in self.water.flow_faces: del self.water.flow_faces[face]
def remove(self,p):
if p not in self.cubes: return
cube = self.cubes.pop(p)
for side,face in cube.faces.items():
if face: face.delete()
self.remove_water(face)
for adj in adjacent(*cube.p):
if adj in self.cubes:
self.set_adj(self.cubes[adj],cube.p,True)
self.update_cube(self.cubes[adj])
class Cube:
def __init__(self,name,p,t,typ):
self.name,self.p,self.t,self.type = name,p,t,typ
self.shown = {'left':False,'right':False,'bottom':False,'top':False,'back':False,'front':False}
self.faces = {'left':None,'right':None,'bottom':None,'top':None,'back':None,'front':None}
class TimeLoop:
def __init__(self,duration): self.unit = 0; self.int = 0; self.duration = duration; self.prev = 0
def update(self,dt):
self.unit+=dt; self.unit-=int(self.unit); self.int = int(self.unit*self.duration)
if self.prev!=self.int: self.prev = self.int; return True
def cube_vertices(pos,n=0.5):
x,y,z = pos; v = tuple((x+X,y+Y,z+Z) for X in (-n,n) for Y in (-n,n) for Z in (-n,n))
return tuple(tuple(k for j in i for k in v[j]) for i in ((0,1,3,2),(5,4,6,7),(0,4,5,1),(3,7,6,2),(4,0,2,6),(1,5,7,3)))
def flatten(lst): return sum(map(list,lst),[])
def normalize(pos): x,y,z = pos; return round(x),round(y),round(z)
def adjacent(x,y,z):
for p in ((x-1,y,z),(x+1,y,z),(x,y-1,z),(x,y+1,z),(x,y,z-1),(x,y,z+1)): yield p
class Player:
WALKING_SPEED = 5
FLYING_SPEED = 15
GRAVITY = 20
JUMP_SPEED = (2*GRAVITY)**.5
TERMINAL_VELOCITY = 50
def push(self): glPushMatrix(); glRotatef(-self.rot[0],1,0,0); glRotatef(self.rot[1],0,1,0); glTranslatef(-self.pos[0],-self.pos[1],-self.pos[2])
def __init__(self,cubes,pos=(0,0,0),rot=(0,0)):
self.cubes = cubes
self.pos,self.rot = list(pos),list(rot)
self.flying = True
self.noclip = True
self.dy = 0
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]+=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def jump(self):
if not self.dy: self.dy = self.JUMP_SPEED
def get_sight_vector(self):
rotX,rotY = self.rot[0]/180*math.pi,self.rot[1]/180*math.pi
dx,dz = math.sin(rotY),-math.cos(rotY)
dy,m = math.sin(rotX),math.cos(rotX)
return dx*m,dy,dz*m
def update(self,dt,keys):
DX,DY,DZ = 0,0,0; s = dt*self.FLYING_SPEED if self.flying else dt*self.WALKING_SPEED
rotY = self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if self.flying:
if keys[key.LSHIFT]: DY-=s
if keys[key.SPACE]: DY+=s
elif keys[key.SPACE]: self.jump()
if keys[key.W]: DX+=dx; DZ-=dz
if keys[key.S]: DX-=dx; DZ+=dz
if keys[key.A]: DX-=dz; DZ-=dx
if keys[key.D]: DX+=dz; DZ+=dx
if dt<0.2:
dt/=10; DX/=10; DY/=10; DZ/=10
for i in range(10): self.move(dt,DX,DY,DZ)
def move(self,dt,dx,dy,dz):
if not self.flying:
self.dy -= dt*self.GRAVITY
self.dy = max(self.dy,-self.TERMINAL_VELOCITY)
dy += self.dy*dt
x,y,z = self.pos
self.pos = self.collide((x+dx,y+dy,z+dz))
def collide(self,pos):
if self.noclip and self.flying: return pos
pad = 0.25; p = list(pos); np = normalize(pos)
for face in ((-1,0,0),(1,0,0),(0,-1,0),(0,1,0),(0,0,-1),(0,0,1)):
for i in (0,1,2):
if not face[i]: continue
d = (p[i]-np[i])*face[i]
if d<pad: continue
for dy in (0,1):
op = list(np); op[1]-=dy; op[i]+=face[i]; op = tuple(op)
if op in self.cubes:
p[i]-=(d-pad)*face[i]
if face[1]: self.dy = 0
break
return tuple(p)
class Window(pyglet.window.Window):
def set2d(self): glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,self.width,0,self.height)
def set3d(self): glLoadIdentity(); gluPerspective(65,self.width/self.height,0.1,320); glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def on_resize(self,w,h): glViewport(0,0,w,h); self.load_vertex_lists(w,h)
def setLock(self,state): self.set_exclusive_mouse(state); self.mouseLock = state
mouseLock = False; mouse_lock = property(lambda self:self.mouseLock,setLock)
def __init__(self,*args):
super().__init__(*args)
pyglet.clock.schedule(self.update)
self.keys = pyglet.window.key.KeyStateHandler()
self.push_handlers(self.keys)
self.model = Model()
self.player = Player(self.model.cubes.cubes)
self.mouse_lock = True
self.fps = pyglet.clock.ClockDisplay()
self.reticle = None
self.block = 0
def load_vertex_lists(self,w,h):
x,y = w/2,h/2; m = 10
if self.reticle: self.reticle.delete()
self.reticle = pyglet.graphics.vertex_list(4,('v2f',(x-m,y, x+m,y, x,y-m, x,y+m)),('c3f',(0,0,0, 0,0,0, 0,0,0, 0,0,0)))
self.water = pyglet.graphics.vertex_list(4,('v2f',(0,0, w,0, w,h, 0,h)),('c4f',[0.15,0.3,1,0.5]*4))
def update(self,dt):
self.player.update(dt,self.keys)
self.model.update(dt)
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_mouse_press(self,x,y,button,MOD):
if button == mouse.LEFT:
block = self.model.cubes.hit_test(self.player.pos,self.player.get_sight_vector())[0]
if block: self.model.cubes.remove(block)
elif button == mouse.RIGHT:
block = self.model.cubes.hit_test(self.player.pos,self.player.get_sight_vector())[1]
if block: self.model.cubes.add(block,self.model.ids[self.block],True)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE: self.dispatch_event('on_close')
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
elif KEY == key.F: self.player.flying = not self.player.flying; self.player.dy = 0; self.player.noclip = True
elif KEY == key.C: self.player.noclip = not self.player.noclip
elif KEY == key.UP: self.block = (self.block-1)%len(self.model.ids)
elif KEY == key.DOWN: self.block = (self.block+1)%len(self.model.ids)
def on_draw(self):
self.clear()
self.set3d()
self.player.push()
self.model.draw()
block = self.model.cubes.hit_test(self.player.pos,self.player.get_sight_vector())[0]
if block:
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glColor3d(0,0,0)
pyglet.graphics.draw(24,GL_QUADS,('v3f/static',flatten(cube_vertices(block,0.52))))
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glColor3d(1,1,1)
glPopMatrix()
self.set2d()
cubes = self.model.cubes.cubes; p = normalize(self.player.pos)
if p in cubes and cubes[p].name=='water': self.water.draw(GL_POLYGON)
self.fps.draw()
self.reticle.draw(GL_LINES)
def main():
window = Window(800,600,'Minecraft',True)
glClearColor(0.5,0.7,1,1)
glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glAlphaFunc(GL_GEQUAL,1)
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
pyglet.app.run()
if __name__ == '__main__':
main()

draw horizontal bars on the same line

I have to draw a gantt resource type of chart.
Idea is to draw several horizontal bars on the same line (corresponding to a resource) each length represented by start date and and date
this is the expected result:
Altogether we have around 200 resources and max. 50 task for each to display, so performance is important.
Any idea?
In addition the tasks should be draggable by mouse.
An solution (Fat GUI (pyQt, wxwidget, tkinter, ...) or web based Flask, web2py, etc) is OK
Actually, I'm gonna cheat and post you something straight from the Matplotlib Documentation. This should get you started with draggable objects in mpl. you'll have to come up with your own dynamic object creation code...
full credit to the guys over at mpl:
# draggable rectangle with the animation blit techniques; see
# http://www.scipy.org/Cookbook/Matplotlib/Animations
import numpy as np
import matplotlib.pyplot as plt
class DraggableRectangle:
lock = None # only one can be animated at a time
def __init__(self, rect):
self.rect = rect
self.press = None
self.background = None
def connect(self):
'connect to all the events we need'
self.cidpress = self.rect.figure.canvas.mpl_connect(
'button_press_event', self.on_press)
self.cidrelease = self.rect.figure.canvas.mpl_connect(
'button_release_event', self.on_release)
self.cidmotion = self.rect.figure.canvas.mpl_connect(
'motion_notify_event', self.on_motion)
def on_press(self, event):
'on button press we will see if the mouse is over us and store some data'
if event.inaxes != self.rect.axes: return
if DraggableRectangle.lock is not None: return
contains, attrd = self.rect.contains(event)
if not contains: return
print('event contains', self.rect.xy)
x0, y0 = self.rect.xy
self.press = x0, y0, event.xdata, event.ydata
DraggableRectangle.lock = self
# draw everything but the selected rectangle and store the pixel buffer
canvas = self.rect.figure.canvas
axes = self.rect.axes
self.rect.set_animated(True)
canvas.draw()
self.background = canvas.copy_from_bbox(self.rect.axes.bbox)
# now redraw just the rectangle
axes.draw_artist(self.rect)
# and blit just the redrawn area
canvas.blit(axes.bbox)
def on_motion(self, event):
'on motion we will move the rect if the mouse is over us'
if DraggableRectangle.lock is not self:
return
if event.inaxes != self.rect.axes: return
x0, y0, xpress, ypress = self.press
dx = event.xdata - xpress
dy = event.ydata - ypress
self.rect.set_x(x0+dx)
self.rect.set_y(y0+dy)
canvas = self.rect.figure.canvas
axes = self.rect.axes
# restore the background region
canvas.restore_region(self.background)
# redraw just the current rectangle
axes.draw_artist(self.rect)
# blit just the redrawn area
canvas.blit(axes.bbox)
def on_release(self, event):
'on release we reset the press data'
if DraggableRectangle.lock is not self:
return
self.press = None
DraggableRectangle.lock = None
# turn off the rect animation property and reset the background
self.rect.set_animated(False)
self.background = None
# redraw the full figure
self.rect.figure.canvas.draw()
def disconnect(self):
'disconnect all the stored connection ids'
self.rect.figure.canvas.mpl_disconnect(self.cidpress)
self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
fig = plt.figure()
ax = fig.add_subplot(111)
rects = ax.bar(range(10), 20*np.random.rand(10))
drs = []
for rect in rects:
dr = DraggableRectangle(rect)
dr.connect()
drs.append(dr)
plt.show()

Categories

Resources