rendered paste body#! /usr/bin/python
from canvas2d import *
import sys
import lex
import yacc
import Camera
from transform import *
tokens = ('NUMBER', 'LBRACE', 'RBRACE', 'LBRAC', 'RBRAC',
'TRANSLAT','ROT','SFACTOR','FDIST','NDIST','ORIENT',
'COORDINDEX','TOP','LEFT','RIGHT','BOTTOM','SEPARATOR',
'COORD3','PCAMERA','TRANSFORM','POS','IFS','COMMA',
'POINT')
#Tokens
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LBRAC = r'\['
t_RBRAC = r'\]'
t_TRANSLAT = r'translation'
t_ROT = r'rotation'
t_SFACTOR = r'scaleFactor'
t_FDIST = r'farDistance'
t_NDIST = r'nearDistance'
t_LEFT = r'left'
t_RIGHT = r'right'
t_TOP = r'top'
t_BOTTOM = r'bottom'
t_SEPARATOR = r'Separator'
t_COORDINDEX= r'coordIndex'
t_COORD3 = r'Coordinate3'
t_PCAMERA = r'PerspectiveCamera'
t_TRANSFORM = r'Transform'
t_POS = r'position'
t_IFS = r'IndexedFaceSet'
t_ORIENT = r'orientation'
t_COMMA = r','
t_POINT = r'point'
#All numbers will be interpreted as floating point numbers
def t_NUMBER(t):
r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?'
try:
t.value = float(t.value)
except ValueError:
print "Unable to convert to float",t.value
sys.exit()
return t
def t_COMMENT(t):
r'\#.*'
pass
t_ignore = " \t" #ignore whitespace
#line counter
def t_newline(t):
r'[\n\r]'
t.lineno += 1
#error handler
def t_error(t):
print "Illegal character '%s' on line %d" % (t.value[0], t.lineno)
sys.exit()
lex.lex() #build the lexer
## Data structures
mycamera = Camera.camera()
mytransforms = [trans((0,0,0))]
myifs = [[]]
mycoords = [[]]
#Parsing
def p_blocks(p):
'''blocks : block
| block blocks'''
pass
def p_block(p):
'''block : camerablock
| sepblock'''
pass
def p_camerablock(p):
'camerablock : PCAMERA LBRACE cameralines RBRACE'
for i in range(0,len(p[3])):
if p[3][i][0] == 'position':
mycamera.position = p[3][i][1]
elif p[3][i][0] == 'orientation':
mycamera.orientation = p[3][i][1]
elif p[3][i][0] == 'nearDistance':
mycamera.nearDistance = p[3][i][1]
elif p[3][i][0] == 'farDistance':
mycamera.farDistance = p[3][i][1]
elif p[3][i][0] == 'left':
mycamera.left = p[3][i][1]
elif p[3][i][0] == 'right':
mycamera.right = p[3][i][1]
elif p[3][i][0] == 'top':
mycamera.top = p[3][i][1]
elif p[3][i][0] == 'bottom':
mycamera.bottom = p[3][i][1]
def p_cameralines(p):
'''cameralines : cameraline
| cameraline cameralines'''
p[0] = [ p[1] ]
if len(p) == 3:
p[0].extend(p[2])
def p_cameraline(p):
'''cameraline : POS triple
| ORIENT quad
| NDIST NUMBER
| FDIST NUMBER
| LEFT NUMBER
| RIGHT NUMBER
| TOP NUMBER
| BOTTOM NUMBER'''
p[0] = (p[1] , p[2] )
#Camera lines will be put into the camera structure in the
#camerablock rule
def p_sepblock(p):
'sepblock : SEPARATOR LBRACE sepitems RBRACE'
mytransforms.append(trans((0,0,0))) #append identity matrix
myifs.append([])
mycoords.append([])
def p_sepitems(p):
'''sepitems : sepitem
| sepitem sepitems'''
pass
def p_sepitem(p):
'''sepitem : TRANSFORM LBRACE translines RBRACE
| COORD3 LBRACE POINT LBRAC triples RBRAC RBRACE
| IFS LBRACE ifsline RBRACE'''
if p[1] == "Transform":
mytransforms[-1] = matrixmultiply(mytransforms[-1],p[3])
elif p[1] == "IndexedFaceSet":
myifs[-1].append(p[3])
else:
mycoords[-1].append(p[5])
def p_translines(p):
'''translines : transline
| transline translines'''
p[0] = p[1]
if len(p) == 3:
p[0] = matrixmultiply(p[1],p[2])
def p_transline(p):
'''transline : TRANSLAT triple
| SFACTOR triple
| ROT quad'''
if p[1] == 'translation':
p[0] = trans(p[2])
elif p[1] == 'rotation':
p[0] = rot(p[2])
elif p[1] == 'scaleFactor':
p[0] = scale(p[2])
def p_ifsline(p):
'ifsline : COORDINDEX LBRAC singles RBRAC'
p[0] = p[3]
def p_quad (p):
'quad : NUMBER NUMBER NUMBER NUMBER'
p[0] = (p[1],p[2],p[3],p[4])
def p_triple(p):
'triple : NUMBER NUMBER NUMBER'
p[0] = (p[1],p[2],p[3])
def p_triples(p):
'''triples : triple
| triple COMMA triples '''
p[0] = [ p[1] ]
if len(p) == 4:
p[0].extend( p[3] )
def p_singles(p):
'''singles : single
| single COMMA singles'''
p[0] = [ p[1] ]
if len(p) == 4:
p[0].extend(p[3])
def p_single(p):
'single : NUMBER'
p[0] = p[1]
def p_error(t):
print "Syntax error at '%s'" % t.value
#build parser
yacc.yacc()
def main():
# check input arguments
if len(sys.argv) != 3:
sys.stderr.write("Incorrect command line options\n")
sys.exit(-1)
#std to lexer, then parse
lex.input(sys.stdin.read())
yacc.parse(sys.stdin.read())
#Ensure data sanity at a basic level
if len(mytransforms) != len(mycoords):
if len(mycoords) != len(myifs):
print "Error in Open IV file formatting. Layout is not correct."
numblocks = len(mytransforms) - 1
#Done with lexing and parsing
T_world_cam = inverse(matrixmultiply(trans(mycamera.position),
rot(mycamera.orientation)))
T_perspective = perspective((mycamera.top,mycamera.bottom,
mycamera.left,mycamera.right,
mycamera.nearDistance,mycamera.farDistance))
#mycanvas = canvas2d(mycamera.left,mycamera.right,mycamera.top,
# mycamera.bottom, int(sys.argv[1]),int(sys.argv[2]))
mycanvas = canvas2d(-1.0,1.0,1.0,-1.0,int(sys.argv[1]),int(sys.argv[2]))
for i in range(numblocks): #for each block
for k in range(len(myifs[i])): #for each index set
faces = [[]]
for n in range(len(myifs[i][k])): #iterate over indecies
if myifs[i][k][n] == -1:
faces.append([])
else:
point = mycoords[i][0][int(myifs[i][k][n])]
point = (point[0],point[1],point[2],1.0)
point = matrixmultiply(mytransforms[i],point)
point = matrixmultiply(T_world_cam,point)
point = matrixmultiply(T_perspective,point)
point = (point[0] / point[3], point[1] / point[3],
point[2] / point[3],1.0)
faces[-1].append(list(point))
#Faces is now full of polys for this block, transform, and IFS,
# so we'll start drawing!
for m in range(len(faces)-1):
mycanvas.line(faces[m][-1][0],faces[m][-1][1],
faces[m][0][0],faces[m][0][1])
for w in range(len(faces[m])-1):
mycanvas.line(faces[m][w][0],faces[m][w][1],
faces[m][w+1][0],faces[m][w+1][1])
mycanvas.toPPM()
if __name__ == '__main__': main()