Как я могу рендерить только лица, которые находятся рядом с воздухом / ничем в pyglet python 3.7.2 opengl? - PullRequest
0 голосов
/ 04 января 2019

В последнее время я экспериментировал с pyglet python 3.7.2 opengl. Я пытаюсь сделать клон майнкрафт. Хотя при добавлении большого количества кубов у меня возникали некоторые проблемы с производительностью. Так что, чтобы это исправить, мне нужно только визуализировать необходимые лица / лица, которые увидит игрок. Я хочу, чтобы код проверял, есть ли воздух / ничего рядом с гранью куба, а затем только визуализировал лицо с воздухом / ничем рядом с ним.

Я пытался glEnable(GL_CULL_FACE), это работает до некоторой степени, но не так хорошо. Он не отображает внутреннюю часть куба, но все же отображает внешнюю часть кубов, которые игрок не должен видеть.

from pyglet.gl import *
from pyglet.window import key
import math

#Somehow should increase performance, I think, by disabling error check.
pyglet.options['debug_gl'] = False

#If you get an unindent error ctrl+x then ctrl+c the code.4
class Model:

    #This def runs at the start.
    def __init__(self):
        self.num_of_cubes = 0

        #Textures
        self.grass_top = self.get_tex('grass_top.png')
        self.grass_side = self.get_tex('grass_side.png')
        self.dirt = self.get_tex('dirt.png')

        #Texture groups
        #None yet

        self.tex_coords = ('t2f', (0,0, 1,0, 1,1, 0,1))

        print("Initializing Model.")

        x,y,z = 0,0,-1
        X,Y,Z = x+1,y+1,z+1

        '''If you put the batch inside add_cube() then it'll delete
        the batch and the cubes inside and only render the last cube.'''
        self.batch = pyglet.graphics.Batch()

        #Color of model (variable) (deprecated)
        #color = ('c3f',(1,1,1,)*4)

        #Cube generator
        for x in range(-16,16):
            for z in range(-16,16):
                self.add_cube(x,-2,-z,self.dirt,self.dirt,self.dirt)
                self.add_cube(x,-1,-z,self.grass_side,self.grass_top,self.dirt)
        print(self.num_of_cubes)

    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 add_cube(self,arg1,arg2,arg3,tex_side,tex_top,tex_bottom):
        self.num_of_cubes += 1

        #Location of cube
        x,y,z = arg1,arg2,arg3
        X,Y,Z = x+1,y+1,z+1

        #Cube sides
        self.batch.add(4,GL_QUADS,tex_side,('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z, )),self.tex_coords)   #Back
        self.batch.add(4,GL_QUADS,tex_side,('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z, )),self.tex_coords)   #Front
        self.batch.add(4,GL_QUADS,tex_side,('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z, )),self.tex_coords)   #Left
        self.batch.add(4,GL_QUADS,tex_side,('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z, )),self.tex_coords)   #Right
        self.batch.add(4,GL_QUADS,tex_top,('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z,  )),self.tex_coords)   #Top
        self.batch.add(4,GL_QUADS,tex_bottom,('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z, )),self.tex_coords) #Bottom

    def draw(self):
        #Draws everything in batch groups
        self.batch.draw()

class Player:
    #Movement config
    FLY_SPEED = 9
    WALK_SPEED = 4

    GRAVITY = 0.1 #The lower it is the stronger it is, I know, weird.
    JUMP_FORCE = (2*GRAVITY)**.5

    def __init__(self,pos=(0,0,0),rot=(0,0)):
        self.pos = list(pos)
        self.rot = list(rot)
        self.flying = 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):
        print("Jumped.")


    def update(self,dt,keys):
        #self.pos[0] is "X", [1] is "Y", [2] is "Z"
        '''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'''
        s = dt*self.FLY_SPEED if self.flying else dt*self.WALK_SPEED
        rotY = -self.rot[1]/180*math.pi
        dx,dz = s*math.sin(rotY),s*math.cos(rotY)
        if self.flying:
            if keys[key.SPACE]: self.pos[1]+=s
            if keys[key.LSHIFT]: self.pos[1]-=s
        elif keys[key.SPACE]: self.jump()
        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

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.fps_counter = pyglet.clock.ClockDisplay()
        self.model = Model()
        self.player = Player((0.5,1.5,1.5),(-30,0))
        self.on_fps = False

    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
        elif KEY == key.TAB: self.on_fps = not self.on_fps;

    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 self.on_fps == True:
            #Eveything after this is rendered 2d, I presume.
            self.set2d()
            self.fps_counter.draw()

if __name__ == "__main__":
    window = Window(width=400,height=300,caption="Pyglet Cube",resizable=True)
    glClearColor(0.5, 0.7, 1, 1);
    glEnable(GL_ALPHA_TEST)
    glEnable(GL_DEPTH_TEST) #Makes it so you can't see faces through other faces.
    glEnable(GL_CULL_FACE)  #Enables culling, doesn't render the faces you can't see. Increases performance.
    pyglet.app.run()
...