5
\$\begingroup\$

I'm using OpenGL to draw about 20 circles. Each circle has 2 lines, ~10 segments, and all of them have different colors and lengths. Frames per Second are around 4.

How can I optimize this to run faster, with higher frame-rates? I am using Python 3 on Ubuntu.

class ScreenOpenGL(Screen):
def __init__(self,layers,layers_lock):
    """ Инициализирует экран и запускает его, потом всю программу """
    Screen.__init__(self,"OpenGL",layers,layers_lock)

    self.window = 0
    self.quad = None
    self.keypress = []

    print("Fuck")
    # self.infoScreen = ScreenCursesInfo()
    self.infoScreen = ScreenStandartInfo()
    GLUT.glutInit(sys.argv)
    GLUT.glutInitDisplayMode(GLUT.GLUT_RGBA | GLUT.GLUT_DOUBLE | GLUT.GLUT_ALPHA | GLUT.GLUT_DEPTH)
    GLUT.glutInitWindowSize(640, 480)
    GLUT.glutInitWindowPosition(400, 400)
    self.window = GLUT.glutCreateWindow(b"Project Evoluo alpha")
    GLUT.glutDisplayFunc(self._loop) # Функция, отвечающая за рисование
    GLUT.glutIdleFunc(self._loop) # При простое перерисовывать
    GLUT.glutReshapeFunc(self._resize) # изменяет размеры окна
    GLUT.glutKeyboardFunc(self._keyPressed) # Обрабатывает нажатия
    self._initGL(640, 480)
    field_params(640, 480)
    print("Fuck")

def run(self):
    # для threading
    GLUT.glutMainLoop()

def _initGL(self,Width,Height):
    GL.glShadeModel(GL.GL_SMOOTH); 
    GL.glClearColor(0.0, 0.0, 0.0, 0.0)    # This Will Clear The Background Color To Black
    GL.glClearDepth(1.0)                   # Enables Clearing Of The Depth Buffer
    GL.glDepthFunc(GL.GL_LESS)                # The Type Of Depth Test To Do
    GL.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST)
    GL.glEnable(GL.GL_BLEND);                         # Enable Blending
    GL.glLineWidth(1.);
    GL.glDisable(GL.GL_LINE_SMOOTH)
    GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

    self.width = Width
    self.height = Height
    self.quad = GLU.gluNewQuadric()
    GLU.gluQuadricNormals(self.quad, GLU.GLU_SMOOTH)
    GLU.gluQuadricTexture(self.quad, GL.GL_TRUE)

def _resize(self,Width,Height):
    if Height == 0:
        Height = 1
    self.width = Width
    self.height = Height
    field_params(Width,Height)

    GL.glViewport(0, 0, Width, Height)       # Reset The Current Viewport And Perspective Transformation
    GL.glMatrixMode(GL.GL_PROJECTION)
    GL.glLoadIdentity()

    GL.glOrtho(0.0,Width,0.0,Height,-1.0,1.0)

    GL.glMatrixMode(GL.GL_MODELVIEW)                   # Select The Modelview Matrix
    GL.glLoadIdentity()

def update(self):
    GLUT.glutSwapBuffers()

def clear(self):
    GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
    GL.glLoadIdentity()                    # Reset The View 

def write(self,pos,str):
    pass

def __del__(self):
    del(self.infoScreen)
    GLUT.glutDestroyWindow(self.window)
    self._end()
    # sys.exit()

def getch(self):
    if self.keypress != []:
        # print
        return self.keypress.pop(-1)[0]
    else:
        return None

def _keyPressed(self,*args):
    if args != None:
        self.keypress.append(args)
        print(self.keypress)

def _draw_prepare(self):
    del(self._layers)
    self._layers = []
    for layer in layers:
        if layer.__class__ == LayerObjects:
            self._layers.append([layer.type,copy.deepcopy(layer.get_objs()),copy.copy(layer._attacked)])

def draw_eyes(self,vis,r_max,dphi):
    for x in range(0,7):
        GLU.gluPartialDisk(self.quad,
            1,
            vis[x][0] * r_max,
            5,
            3,
            - ((x - 3) * 15 + 7.5 + dphi / pi * 180) + 90,
            15)

def draw_sensitivity(self,sens,r_max,dphi):
    for x in range(0,5):
        GLU.gluPartialDisk(self.quad,
            1,
            sens[x] * r_max,
            5,
            3,
            - (52.5 + (x+1) * 51 + dphi / pi * 180) + 90,
            51)   
    pass

def draw_obj(self,obj,_id,pos,circle,lines,attacked):
    # Кружок
    GL.glLoadIdentity()
    GL.glTranslatef(pos[0]-1,pos[1]-1,0)
    red,green,blue = obj.color # берём цвет
    GL.glColor3f(red,green,blue)
    GLU.gluDisk(self.quad,*circle)

    #Глазки
    GL.glColor3f(1-red,1-green,1-blue)
    try:
        eyes = obj.eyes
    except NameError:
        pass
    else:
        self.draw_eyes(obj.eyes.eyes,obj.radius * k_screen,obj.pos[1])
    # Прикосновения
    GL.glColor3f(1,0,0)
    try:
        sensitivity = obj.sensitivity
    except NameError:
        pass
    else:
        self.draw_sensitivity(obj.sensitivity._sens,obj.radius * k_screen,obj.pos[1])
    # Полосочки
    GL.glBegin(GL.GL_LINES)
    for color,x,y in lines:
        GL.glColor3f(*color)
        GL.glVertex3f(0,0,0)
        GL.glVertex3f(x,y,0)
    GL.glEnd()

def draw(self,layer):
    global width,height
    if layer[0] == "Layer Objects":
        attacked = layer[2]
        for obj in layer[1]:
            #Стрелочки-направления
            pos = [int(x) for x in obj.get_pos_screen()]
            positions = [pos,]
            radius_scr = obj.radius * k_screen
            att = Vector(radius_scr * (1 +obj._attack_range*obj._attack),
                    obj.pos[1],
                    isPolar = True
                    ) 
            speed = obj.speed[0] * k_screen * 5

            if pos[0] < radius_scr:
                positions.append([pos[0] + self.width,pos[1]])
            if pos[0] + radius_scr > self.width:
                positions.append([pos[0] - self.width,pos[1]])
            if pos[1] < radius_scr:
                positions.append([pos[0],pos[1] + self.height])
            if pos[1] + radius_scr > self.height:
                positions.append([pos[0],pos[1] - self.height])

            for ps in positions:
                self.draw_obj(obj,obj._id, ps , [0,obj.radius*k_screen,20,1], [ [ (1,0,0) , att.x, att.y ], [ (0,0,1) , speed.x, speed.y] ] , attacked)

    self.infoScreen.draw()

Function code that draws:

    def _draw_prepare(self):
    """ Копирует из глобальной переменной всё, что ей нужно """
    self._layers = copy.deepcopy(layers)
def _loop(self):
    global tick
    if (self.ch == b'q') or (self.ch == b'\xb1') or (self.ch == 27) or (self.ch == 113):
        isEnd = True
        self.__del__()
        del(self)
        return 0
    elif (self.ch == b's'):
        self._is_draw = not self._is_draw
        print("changed to %d" %self._is_draw)
    else:
        if (self.last_tick != tick) and (self._is_draw):
            self.layers_lock.acquire(1)
            self._draw_prepare()
            self.layers_lock.release()
            self.last_tick = tick
    # рисует сцену
    return self._main()
def _main(self):
    global tick
    self.clear()
    if self._is_draw:
        for layer in self._layers:
            self.draw(layer)
    self.update()
    self.ch = self.getch()

And on GitHub

\$\endgroup\$
  • 1
    \$\begingroup\$ First, we're a code review...not here to fix code. Having said that, your code does not follow any style-rules. Sometimes there are spaces between operators, sometimes there are not, sometimes there are spaces after a comma, sometimes not...sometimes there are English comments, sometimes they're Russian(?). \$\endgroup\$ – Bobby Apr 17 '13 at 13:43
  • \$\begingroup\$ A bad algorithm is not a broken algorithm. Voted to leave open. Further more, all facets of the code are up for review, not the performance. \$\endgroup\$ – Pimgd Aug 3 '14 at 20:39
  • \$\begingroup\$ This post was mentioned on meta. \$\endgroup\$ – RubberDuck Aug 4 '14 at 12:22
7
\$\begingroup\$

Not really sure why this line is neccesary.

print("Fuck")

Unless "Fuck" is Russian for something, this should be removed.

In addition, using % for string formatting is deprecated. One should be using str.format instead. str.format supports normal, positional, and named parameters. Here's an example:

# str.format without positional or named parameters
print("{} {}".format("Hello", "world"))

# str.format with positional parameters
print("{1} {0}".format("world", "Hello"))

# str.format with named parameters
print("{word1} {word2}".format(word1="Hello", word2="world"))

I also noticed that you're mixing English and Russian comments. I'd recommend sticking to one language or the other.

In the class ScreenOpenGL you have a "private" method named _initGL. Is there any reason why the contents of this method can't just be part of __init__?

You also don't need parentheses around Boolean conditions. For example, (self.last_tick != tick) would become self.last_tick != tick.

Finally, I noticed that you're mixing a lot of naming styles. Variables and functions should be snake_case, and classes should be PascalCase. If a variable is a constant (un-changing value), it should be in UPPER_SNAKE_CASE.

\$\endgroup\$
  • 1
    \$\begingroup\$ So, "print("Fuck")" used for debug :) Other comment's -- thank, but this code was written a long ago, and most of things I already know. Thank anyway! \$\endgroup\$ – user2286564 Jul 24 '15 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.