##These are objects which correspond to OpenGL geometric primitives. Notice that display lists are implemented. 

from Numeric import *
from OpenGL.GL import *
from whrandom import *

class Points:
    def __init__(self,n):
        self.n = n
        self.vertices = zeros((n,3), Float)
	self.pcount = 0
	
    def addpoint(self,x,y,z):
        if self.pcount == self.n:
	    return()
	else:
	    self.vertices[self.pcount][0] = x
	    self.vertices[self.pcount][1] = y
	    self.vertices[self.pcount][2] = z
	    self.pcount = self.pcount + 1
	    
    def changepoint(self,n,x,y,z):
 	    self.vertices[n][0] = x
	    self.vertices[n][1] = y
	    self.vertices[n][2] = z
	  
    def draw(self):
	glBegin(GL_POINTS)
	glVertex(self.vertices)
	glEnd()
    
class Lines:
    def __init__(self,n):
        self.n = n*2
        self.vertices = zeros((self.n,3), Float)
	self.lcount = 0
	
    def addline(self,p1,p2):
        if self.lcount == self.n:
	    return()
	else:
	    self.vertices[self.lcount][0] = p1[0]
	    self.vertices[self.lcount][1] = p1[1]
	    self.vertices[self.lcount][2] = p1[2]
	    self.vertices[self.lcount+1][0] = p2[0]
	    self.vertices[self.lcount+1][1] = p2[1]
	    self.vertices[self.lcount+1][2] = p2[2]
	    self.lcount = self.lcount + 2
	    	  
    def draw(self):
	glBegin(GL_LINES)
	glVertex(self.vertices)
	glEnd()
	
class Linestrip:
    def __init__(self,n):
        self.n = n
        self.vertices = zeros((self.n,3), Float)
        self.lcount = 0
	
    def addline(self,p):
        if self.lcount == self.n:
            return()
        else:
            self.vertices[self.lcount][0] = p[0]
            self.vertices[self.lcount][1] = p[1]
            self.vertices[self.lcount][2] = p[2]
            self.lcount = self.lcount + 1
	    	  
    def draw(self):
        glBegin(GL_LINE_STRIP)
        glVertex(self.vertices)
        glEnd()
    
class Lineloop:
    def __init__(self,n):
        self.n = n
        self.vertices = zeros((self.n,3), Float)
        self.lcount = 0
	
    def addline(self,x,y,z):
        if self.lcount == self.n:
            return()
        else:
            self.vertices[self.lcount][0] = x
            self.vertices[self.lcount][1] = y
            self.vertices[self.lcount][2] = z
            self.lcount = self.lcount + 1
	    	  
    def draw(self):
        glBegin(GL_LINE_LOOP)
        glVertex(self.vertices)
        glEnd()
    
class LineloopGroup:
    def __init__(self,n,m):
        self.n = n
        self.loops = []
        for i in range(n):
            self.loops.append(Lineloop(m))
        self.whichloop = -1
	
    def startloop(self):
        if self.whichloop >= self.n:
            return
        self.whichloop = self.whichloop + 1

    def addline(self,p):
        self.loops[self.whichloop].addline(p)
	
    def draw(self):
        for loop in self.loops:
            loop.draw()
	        
class Quads:
    def __init__(self,n):
        self.n = n*4
        self.vertices = zeros((self.n,3), Float)
        self.lines = Lines(self.n)
        self.count = 0
        	
    def addquad(self,quad):
        if self.count >= self.n:
            print 'quads object full up'
            return()
        else:
            self.lines.addline(quad[0],quad[1])
            self.lines.addline(quad[1],quad[2])
            self.lines.addline(quad[2],quad[3])
            self.lines.addline(quad[3],quad[0])
            self.vertices[self.count][0] = quad[0][0]
            self.vertices[self.count][1] =  quad[0][1]
            self.vertices[self.count][2] =  quad[0][2]
            self.vertices[self.count+1][0] =  quad[1][0]
            self.vertices[self.count+1][1] =  quad[1][1]
            self.vertices[self.count+1][2] =  quad[1][2]
            self.vertices[self.count+2][0] =  quad[2][0]
            self.vertices[self.count+2][1] =  quad[2][1]
            self.vertices[self.count+2][2] =  quad[2][2]
            self.vertices[self.count+3][0] =  quad[3][0]
            self.vertices[self.count+3][1] =  quad[3][1]
            self.vertices[self.count+3][2] =  quad[3][2]
            self.count = self.count + 4
	    
    def draw(self,color = '(1.0,1.0,1.0)'):
        exec('glColor3f'+color)
        glBegin(GL_QUADS)
        glVertex(self.vertices)
        glEnd()

    def drawlines(self,color = '(0.0,0.0,0.0)'):
        exec('glColor3f'+color)
        self.lines.draw()    
class Quadstrip:
    def __init__(self,n):
        self.n = n*2+2
        self.vertices = zeros((self.n,3), Float)
        self.count = 0
	
    def firstquad(self,quad):
        self.vertices[0][0] = quad[0][0]
        self.vertices[0][1] =  quad[0][1]
        self.vertices[0][2] =  quad[0][2]
        self.vertices[1][0] =  quad[1][0]
        self.vertices[1][1] =  quad[1][1]
        self.vertices[1][2] =  quad[1][2]
        self.vertices[2][0] = quad[2][0]
        self.vertices[2][1] =  quad[2][1]
        self.vertices[2][2] =  quad[2][2]
        self.vertices[3][0] =  quad[3][0]
        self.vertices[3][1] =  quad[3][1]
        self.vertices[3][2] =  quad[3][2]

    def addquad(self,p1,p2):
        if self.count == self.n:
            return()
        else:
            self.vertices[self.count][0] = p1[0]
            self.vertices[self.count][1] = p1[1]
            self.vertices[self.count][2] = p1[2]
            self.vertices[self.count+1][0] = p2[0]
            self.vertices[self.count+1][1] = p2[1]
            self.vertices[self.count+1][2] = p2[2]
            self.count = self.count + 2
	    	  
    def draw(self):
	glBegin(GL_QUAD_STRIP)
	glVertex(self.vertices)
	glEnd()

class Quadmesh:
    def __init__(self,array):
        if len(array.shape) != 2:
            raise "Error: a mesh must be a two-dimensional array"
        self.vertices = array
        self.n = array.shape[0]
        self.m = array.shape[1]
        self.strip()
	
    def strip(self):
        self.strips = []
        v = self.vertices
        for i in range(self.n-1):
            strip = Quadstrip(self.n-1)
            strip.firstquad(((i,0,v[i][0]),(i+1,0,v[i+1][0]),(i,1,v[i][1]),(i+1,1,v[i+1][1])))
            for j in range(2,self.m):
	        strip.addquad((i,j,v[i][j]),(i+1,j,v[i+1][j]))
            self.strips.append(strip)
        self.line_vertices_n = zeros((self.n,self.m,3),Float)	    
        for i in range(self.n):
            for j in range(self.m):
	        self.line_vertices_n[i][j][0] = i
	        self.line_vertices_n[i][j][1] = j
	        self.line_vertices_n[i][j][2] = v[i][j]
        self.line_vertices_m = zeros((self.m,self.n,3),Float)	    
        for j in range(self.m):
            for i in range(self.n):
	        self.line_vertices_m[j][i][0] = i
	        self.line_vertices_m[j][i][1] = j
	        self.line_vertices_m[j][i][2] = v[i][j]
	    	
    def draw(self):
        glEnable(GL_LIGHTING)
        for strip in self.strips:
            pass
            strip.draw()
        glDisable(GL_LIGHTING)
        glColor3f(0,0,0)
        for i in range(self.n):
            glBegin(GL_LINE_STRIP)
            glVertex(self.line_vertices_n[i])
            glEnd()
        for j in range(self.m):
            glBegin(GL_LINE_STRIP)
            glVertex(self.line_vertices_m[j])
            glEnd()
	    
class ColorPointmesh:
    def __init__(self,array):
        if len(array.shape) != 2:
	    raise "Error: a mesh must be a two-dimensional array"
        self.vertices = array
	self.n = array.shape[0]
	self.m = array.shape[1]
	
    def draw(self,distance):
        glPointSize(10.0 - distance/10) 
	glDisable(GL_LIGHTING)
	glBegin(GL_POINTS)
	for row in range(self.n):
	    for col in range(self.m):
	        z = self.vertices[row][col]
		glColor3f(z,0,0)
		glVertex3f(row,col,z)
	glEnd()
	
class Tris:
    def __init__(self,n):
        self.n = n*3
        self.vertices = zeros((self.n,3), Float)
	self.count = 0
	
    def addtri(self,tri):
        if self.count == self.n:
	    return()
	else:
	    self.vertices[self.count][0] = tri[0][0]
	    self.vertices[self.count][1] = tri[0][1]
	    self.vertices[self.count][2] = tri[0][2]
	    self.vertices[self.count+1][0] = tri[1][0]
	    self.vertices[self.count+1][1] = tri[1][1]
	    self.vertices[self.count+1][2] = tri[1][2]
	    self.vertices[self.count+2][0] = tri[2][0]
	    self.vertices[self.count+2][1] = tri[2][1]
	    self.vertices[self.count+2][2] = tri[2][2]
	    self.count = self.count + 3
	    	  
    def draw(self):
	glBegin(GL_QUADS)
	glVertex(self.vertices)
	glEnd()

class Tristrip:
    def __init__(self,n):
        self.n = n+2
        self.vertices = zeros((self.n,3), Float)
	self.count = 0
	
    def firsttri(self,tri):
	self.vertices[0][0] = tri[0][0]
	self.vertices[0][1] = tri[0][1]
	self.vertices[0][2] = tri[0][2]
	self.vertices[1][0] = tri[1][0]
	self.vertices[1][1] = tri[1][1]
	self.vertices[1][2] = tri[1][2]
	self.vertices[2][0] = tri[2][0]
	self.vertices[2][1] = tri[2][1]
	self.vertices[2][2] = tri[2][2]
	self.count = 3

    def addtri(self,point):
        if self.count == self.n:
	    return()
	else:
	    self.vertices[self.count][0] = point[0]
	    self.vertices[self.count][1] =point[1]
	    self.vertices[self.count][2] =point[2]
	    self.count = self.count + 1
	    	  
    def draw(self):
	glBegin(GL_TRIANGLE_STRIP)
	glVertex(self.vertices)
	glEnd()
	
class Trimesh:
    def __init__(self,array):
        self.strips = []
	for i in range(m):
	    self.strips.append(Tristrip(n))

    def draw(self):
        for strip in self.strips:
	    strip.draw()
    
class Trifan:
    def __init__(self,n):
        self.n = n+2
        self.vertices = zeros((self.n,3), Float)
	self.count = 0
	
    def apex(self,point):
	self.vertices[0][0] =  point[0]
	self.vertices[0][1] =  point[1]
	self.vertices[0][2] =  point[2]
	self.count = 1

    def addtri(self,point):
        if self.count == self.n:
	    return()
	else:
	    self.vertices[self.count][0] = point[0]
	    self.vertices[self.count][1] =point[1]
	    self.vertices[self.count][2] =point[2]
	    self.count = self.count + 1
	    	  
    def draw(self):
	glBegin(GL_TRIANGLE_FAN)
	glVertex(self.vertices)
	glEnd()
    
class Dlist:
    def __init__(self):
        self.list = glGenLists(1)
	
    def begininit(self):
	glNewList(self.list, GL_COMPILE_AND_EXECUTE)
	
    def endinit(self):
        glEndList()
	
    def draw(self):
        glCallList(self.list)

