def setup(self):
        self.width = 640
        self.height = 480
        self.batch = pl.graphics.Batch()
        self.boxSize = 2.0
        self.ballNumber = 50 # initial parameters
        self.ballSize = 0.1
        self.collisionNumber = 0

        #-----------------------------------------#
        self.labels = [
            pl.text.Label('Ball Number: '+str(self.ballNumber), x=10, y=100,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Ball Size: '+str(self.ballSize), x=10, y=60,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Box Size: '+str(self.boxSize), x=10, y=20,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Collision Number: '+str(self.collisionNumber), x=10, y=140,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch)]
        """
        self.widgets = [
            TextWidget('', 150, 100, 50, self.batch),
            TextWidget('', 150, 60, 50, self.batch),
            TextWidget('', 150, 20, 50, self.batch)
        ]
        self.text_cursor = self.get_system_mouse_cursor('text')
        
        self.focus = None
        self.set_focus(self.widgets[0])
        """
        #-----------------------------------------#
        
        self.box = CollisionBox(array([0.0,0.0,-7.0]),self.boxSize)
        #self.radius = 1
        #self.pos_array =[]
        #self.vel_array =[]
        #self.ballList = []
        for i in range(self.ballNumber):
            rval = self.boxSize/1.5
            randVec = array([uniform(-rval,rval),uniform(-rval,rval),uniform(-rval,rval)])
            start_vel = randVec*.02
            #start_vel = 0.0
            #self.ballList.append(Particle(randVec,start_vel,self.ballSize))
            self.pos_array.append(randVec)
            self.vel_array.append(start_vel)
            

        self.InitGL(self.width, self.height)
        
        pl.clock.schedule_interval(self.update, 1/60.0) # update at 60Hz
        self.fps_display = pl.clock.ClockDisplay()
class World(pl.window.Window):
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __init__(self, *args, **kwargs):
        config = Config(sample_buffers=1, samples=4,
                        depth_size=16, double_buffer=True,)
        try:
            super(World, self).__init__(resizable=True, config=config, caption='Collisions')
        except:
            super(World, self).__init__(resizable=True , caption='Collisions')
        self.pos_array = []
        self.vel_array = []
        self.setup()

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def setup(self):
        self.width = 640
        self.height = 480
        self.batch = pl.graphics.Batch()
        self.boxSize = 2.0
        self.ballNumber = 50 # initial parameters
        self.ballSize = 0.1
        self.collisionNumber = 0

        #-----------------------------------------#
        self.labels = [
            pl.text.Label('Ball Number: '+str(self.ballNumber), x=10, y=100,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Ball Size: '+str(self.ballSize), x=10, y=60,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Box Size: '+str(self.boxSize), x=10, y=20,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch),
            pl.text.Label('Collision Number: '+str(self.collisionNumber), x=10, y=140,
                              anchor_y='bottom',color=(0, 0, 0, 255), batch=self.batch)]
        """
        self.widgets = [
            TextWidget('', 150, 100, 50, self.batch),
            TextWidget('', 150, 60, 50, self.batch),
            TextWidget('', 150, 20, 50, self.batch)
        ]
        self.text_cursor = self.get_system_mouse_cursor('text')
        
        self.focus = None
        self.set_focus(self.widgets[0])
        """
        #-----------------------------------------#
        
        self.box = CollisionBox(array([0.0,0.0,-7.0]),self.boxSize)
        #self.radius = 1
        #self.pos_array =[]
        #self.vel_array =[]
        #self.ballList = []
        for i in range(self.ballNumber):
            rval = self.boxSize/1.5
            randVec = array([uniform(-rval,rval),uniform(-rval,rval),uniform(-rval,rval)])
            start_vel = randVec*.02
            #start_vel = 0.0
            #self.ballList.append(Particle(randVec,start_vel,self.ballSize))
            self.pos_array.append(randVec)
            self.vel_array.append(start_vel)
            

        self.InitGL(self.width, self.height)
        
        pl.clock.schedule_interval(self.update, 1/60.0) # update at 60Hz
        self.fps_display = pl.clock.ClockDisplay()
        
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # A general OpenGL initialization function.  Sets all of the initial parameters.
    def InitGL(self,Width, Height):             # We call this right after our OpenGL window is created.
        glClearColor(1.0, 1.0, 1.0, 1.0)       # This Will Clear The Background Color To Black
        glClearDepth(1.0)                         # Enables Clearing Of The Depth Buffer
        glDepthFunc(GL_LESS)                      # The Type Of Depth Test To Do
        glEnable(GL_DEPTH_TEST)                 # Enables Depth Testing
        glEnable (GL_LIGHTING);
        glEnable (GL_LIGHT0);
        glShadeModel(GL_SMOOTH)             # Enables Smooth Color Shading
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()                          # Reset The Projection Matrix
                                                    # Calculate The Aspect Ratio Of The Window
        #(pyglet initializes the screen so we ignore this call)
        #gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
        glMatrixMode(GL_MODELVIEW)
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # The function called when our window is resized (which shouldn't happen if you enable fullscreen, below)
    def ReSizeGLScene(self,Width, Height):
        if Height == 0:                           # Prevent A Divide By Zero If The Window Is Too Small
              Height = 1
        glViewport(0, 0, Width, Height)     # Reset The Current Viewport And Perspective Transformation
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
        glMatrixMode(GL_MODELVIEW)
        #self.label.draw()
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # The main drawing function.
    def DrawGLScene(self):
        pl.gl.glClearColor(1, 1, 1, 1)
        #self.clear()
        
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); # Clear The Screen And The Depth Buffer
        glTranslatef(0,0,0)
        glLoadIdentity()
        
        self.box.drawBox()
        self.drawBalls()
        self.drawOverlay()

        
    #load 2d overlay then convert back to 3d view
    def drawOverlay(self):
        height = self.height
        width = self.width
        
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glPushMatrix()
        gl.glLoadIdentity()
        gl.glOrtho(0, width, 0, height, -1, 1)
        gl.glMatrixMode(gl.GL_MODELVIEW)
        gl.glPushMatrix()
        gl.glLoadIdentity()
        
        ####draw stuff here####
        glTranslatef(0,height-160,0)
        self.batch.draw()
        gl.glLoadIdentity()
        glTranslatef(width-140,0,0)
        self.fps_display.draw()

        gl.glPopMatrix()
        gl.glMatrixMode(gl.GL_PROJECTION)
        gl.glPopMatrix()
        gl.glMatrixMode(gl.GL_MODELVIEW)
        
    
    def drawParticle(self,position):
        #Set position
        glTranslatef(position[0],position[1],position[2])
        
        #Draw sphere
        glColor3f(0.0,0.0,0.5)
        sphere = gluNewQuadric()
        gluSphere(sphere,self.ballSize,10,10)

    def drawBalls(self):
       # for i in range(len(self.ballList)):
        for i in range(self.ballNumber):     
            glLoadIdentity()
            glTranslatef(self.box.getPosition()[0],\
                         self.box.getPosition()[1],\
                         self.box.getPosition()[2])
            xtot,ytot,ztot = self.box.getRotation() # get box rotation to cancel it out
            glRotatef(xtot,1.0,0.0,0.0)       # Rotate on X
            glRotatef(ytot,0.0,1.0,0.0)       # Rotate on Y 
            glRotatef(ztot,0.0,0.0,1.0)       # Rotate on Z
            
           # iball = self.ballList[i]
            #ipos = iball.getPosition()
            ipos = self.pos_array[i]
            ivel = self.vel_array[i]
            
            self.drawParticle(ipos)
            #iball.update()
            ipos += ivel
            
            #collision detection
            bound = self.boxSize
            if (ipos[0] - self.ballSize <= -bound)or(ipos[0] + self.ballSize >= bound):
                #iball.velocity[0] *= -1
                ivel[0] *= -1
            if (ipos[1] - self.ballSize <= -bound)or(ipos[1] + self.ballSize >= bound):
                #iball.velocity[1] *= -1
                ivel[1] *= -1
            if (ipos[2] - self.ballSize <= -bound)or(ipos[2] + self.ballSize >= bound):
                #iball.velocity[2] *= -1
                ivel[2] *= -1

            
            # ball-ball collisions
           # for j in range(len(self.ballList)):
            for j in range(self.ballNumber):
                #jball = self.ballList[j]
                if (i != j):
                    self.resolveCollisions(i,j)

    def resolveCollisions(self,i,j):
        #iball = ball_1
        #ipos = iball.getPosition()
        #ivel = iball.getVelocity()
        #jball = ball_2
        #jpos = jball.getPosition()
        #jvel = jball.getVelocity()
        ipos = self.pos_array[i]
        ivel = self.vel_array[i]
        jpos = self.pos_array[j]
        jvel = self.vel_array[j]
        
        diameter = self.ballSize*2
        seperation = spatial.distance.euclidean(ipos, jpos)
        
        if seperation <= diameter:
            #collision vector
            collisionV = subtract(ipos,jpos)
            ncollisionV = collisionV/linalg.norm(collisionV)
            iInit = dot(ivel,ncollisionV)
            jInit = dot(jvel,ncollisionV)

            #momentum exchange
            iFin = jInit
            jFin = iInit
            iDiff = iFin - iInit
            jDiff = jFin - jInit
            iProj = multiply(ncollisionV,iDiff)
            jProj = multiply(ncollisionV,jDiff)
            newi = add(ivel,iProj)
            newj = add(jvel,jProj)
            #iball.setVelocity(newi)
            #jball.setVelocity(newj)
            self.vel_array[i] = newi
            self.vel_array[j] = newj

            #increment collision number
            self.collisionNumber+=1
            self.labels[3].text = "Collisions: " + str(self.collisionNumber)
    

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def update(self,dt):
        self.DrawGLScene()

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def on_draw(self):
        self.DrawGLScene()
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    def on_resize(self,w,h):
        self.ReSizeGLScene(w,h)
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def on_key_press(self, symbol, modifiers):
        rotspeed = .5
        if symbol == key.ESCAPE:
            self.dispatch_event('on_close')
            pl.app.exit()
        elif symbol == key.LEFT:
            self.box.rotateBox(0.0,-rotspeed,0.0)
        elif symbol == key.RIGHT:
            self.box.rotateBox(0.0,rotspeed,0.0)
        elif symbol == key.UP:
            self.box.rotateBox(-rotspeed,0.0,0.0)
        elif symbol == key.DOWN:
            self.box.rotateBox(rotspeed,0.0,0.0)
        """
        elif symbol == pl.window.key.TAB:
            if modifiers & pl.window.key.MOD_SHIFT:
                dir = -1
            else:
                dir = 1

            if self.focus in self.widgets:
                i = self.widgets.index(self.focus)
            else:
                i = 0
                dir = 0

            self.set_focus(self.widgets[(i + dir) % len(self.widgets)])
        """

    def on_key_release(self, symbol, modifiers):
        if symbol == key.LEFT or key.RIGHT:
            self.box.rotateY(0.0)
        if symbol == key.UP or key.DOWN:
            self.box.rotateX(0.0)
            #self.box.rotateZ(0.0)
    """