removed an unused script
parent
cb31210614
commit
06d6b96c6e
|
@ -1,388 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# This file is part of Mitsuba, a physically based rendering system.
|
||||
#
|
||||
# Copyright (c) 2007-2012 by Wenzel Jakob and others.
|
||||
#
|
||||
# Mitsuba is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License Version 3
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# Mitsuba is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from PySide.QtCore import QFile, QTextStream
|
||||
from xml.etree import ElementTree as et
|
||||
from lepl import Regexp, Space, Literal, Separator, List
|
||||
import numpy as np
|
||||
from OpenGL.GL import *
|
||||
from OpenGL.GLU import *
|
||||
from OpenGL.GLUT import *
|
||||
import sys
|
||||
|
||||
Real = lambda: Regexp(r'[\+\-]?(?:[0-9]*\.[0-9]+|[0-9]+\.' +
|
||||
r'|[0-9]+)(?:[eE][\+\-]?[0-9]+)?')
|
||||
|
||||
def make_path_grammar():
|
||||
sep = ~(Space() | Literal(','))[:]
|
||||
with Separator(sep):
|
||||
num = Real() >> float
|
||||
# Moveto
|
||||
M = ((Literal('M') | Literal('m')) & num[2][:])
|
||||
# Horizontal straight lines
|
||||
H = (Literal('H') | Literal('h')) & num[:]
|
||||
# Vertical straight lines
|
||||
V = (Literal('V') | Literal('v')) & num[:]
|
||||
# General straight lines
|
||||
L = (Literal('L') | Literal('l')) & num[2][:]
|
||||
# Cubic bezier curves (curveto)
|
||||
C = (Literal('C') | Literal('c')) & num[6][:]
|
||||
# Cubic bezier curves (smooth curveto)
|
||||
S = (Literal('S') | Literal('s')) & num[4][:]
|
||||
# Close the path
|
||||
z = Literal('z') | Literal('Z')
|
||||
grammar = sep & ((M|H|V|L|C|S|z) > List)[:] & sep
|
||||
grammar.config.no_compile_to_regexp()
|
||||
return grammar
|
||||
|
||||
def make_polygon_grammar():
|
||||
sep = ~(Space() | Literal(','))[:]
|
||||
with Separator(sep):
|
||||
num = Real() >> float
|
||||
grammar = sep & num[2][:] & sep
|
||||
grammar.config.no_compile_to_regexp()
|
||||
return grammar
|
||||
|
||||
class BezierSpline(object):
|
||||
def __init__(self, *args):
|
||||
if len(args) == 4:
|
||||
self.start = args[0]
|
||||
self.cp1 = args[1]
|
||||
self.cp2 = args[2]
|
||||
self.end = args[3]
|
||||
elif len(args) == 2:
|
||||
d = args[1] - args[0]
|
||||
self.start = args[0]
|
||||
self.cp1 = args[0] + 1.0/3.0 * d
|
||||
self.cp2 = args[0] + 2.0/3.0 * d
|
||||
self.end = args[1]
|
||||
else:
|
||||
raise Exception("Invalid constructor call")
|
||||
|
||||
def _eval(self, t):
|
||||
tmp = 1 - t
|
||||
tmp2, t2 = tmp*tmp, t*t
|
||||
return self.start * (tmp*tmp2) + self.cp1 * (3*tmp2*t) + \
|
||||
self.cp2 * (3*tmp*t2) + self.end * (t*t2)
|
||||
|
||||
def drawGL(self):
|
||||
steps = 10
|
||||
p = self.start
|
||||
glVertex2f(p[0], p[1])
|
||||
for i in range(1, steps):
|
||||
p = self._eval(float(i)/(steps-1))
|
||||
glVertex2f(p[0], p[1])
|
||||
|
||||
def drawGL_tess(self):
|
||||
steps = 10
|
||||
p = self.start
|
||||
gluTessVertex(tobj, [p[0], p[1], 0], [p[0], p[1], 0])
|
||||
for i in range(1, steps):
|
||||
p = self._eval(float(i)/(steps-1))
|
||||
gluTessVertex(tobj, [p[0], p[1], 0], [p[0], p[1], 0])
|
||||
|
||||
class AABB(object):
|
||||
def __init__(self):
|
||||
inf = float("inf")
|
||||
self.min = np.array([inf, inf])
|
||||
self.max = np.array([-inf, -inf])
|
||||
|
||||
def expand_by(self, p):
|
||||
self.min[0] = min(self.min[0], p[0])
|
||||
self.min[1] = min(self.min[1], p[1])
|
||||
self.max[0] = max(self.max[0], p[0])
|
||||
self.max[1] = max(self.max[1], p[1])
|
||||
|
||||
def expand_by_aabb(self, aabb):
|
||||
self.min[0] = min(self.min[0], aabb.min[0])
|
||||
self.min[1] = min(self.min[1], aabb.min[1])
|
||||
self.max[0] = max(self.max[0], aabb.max[0])
|
||||
self.max[1] = max(self.max[1], aabb.max[1])
|
||||
|
||||
def size(self):
|
||||
return self.max - self.min
|
||||
|
||||
def __repr__(self):
|
||||
return "AABB[min=%s, max=%s]" % \
|
||||
(repr(self.min), repr(self.max))
|
||||
|
||||
class Path(object):
|
||||
PathGrammar = make_path_grammar()
|
||||
PolygonGrammar = make_polygon_grammar()
|
||||
|
||||
def __init__(self, node):
|
||||
self.pos = None
|
||||
self.start = None
|
||||
self.cp2 = None
|
||||
self.splines = []
|
||||
self.aabb = AABB()
|
||||
|
||||
def getflt(key):
|
||||
value = node.get(key)
|
||||
return float(value) if value != None else 0
|
||||
|
||||
if 'path' in node.tag:
|
||||
instructions = Path.PathGrammar.parse(node.get("d"))
|
||||
elif 'polygon' in node.tag:
|
||||
points = Path.PolygonGrammar.parse(node.get("points"))
|
||||
instructions = [['M'] + points, ['z']]
|
||||
elif 'rect' in node.tag:
|
||||
x, y = getflt("x"), getflt("y")
|
||||
width, height = getflt("width"), getflt("height")
|
||||
instructions = [['M', x, y ], ['h', width], ['v', height], ['h', -width], ['z']]
|
||||
elif 'line' in node.tag:
|
||||
x1, x2 = getflt("x1"), getflt("x2")
|
||||
y1, y2 = getflt("y1"), getflt("y2")
|
||||
instructions = [['M', x1, y1, x2, y2 ]]
|
||||
else:
|
||||
raise Exception("Unknown tag!")
|
||||
|
||||
self.id = node.get("id")
|
||||
|
||||
self.stroke = self._color(node.get('stroke'))
|
||||
self.fill = self._color(node.get('fill'))
|
||||
|
||||
commandList = {
|
||||
'm' : Path._moveto,
|
||||
'h' : Path._hlineto,
|
||||
'v' : Path._vlineto,
|
||||
'l' : Path._lineto,
|
||||
'c' : Path._curveto,
|
||||
's' : Path._scurveto,
|
||||
'z' : Path._close
|
||||
}
|
||||
|
||||
self.index = 1
|
||||
for item in instructions:
|
||||
cmd, args = item[0], item[1:]
|
||||
commandList[cmd.lower()](self, cmd, args)
|
||||
self.lastcmd = cmd
|
||||
self.index += 1
|
||||
|
||||
for spline in self.splines:
|
||||
if spline:
|
||||
self.aabb.expand_by(spline.start)
|
||||
self.aabb.expand_by(spline.cp1)
|
||||
self.aabb.expand_by(spline.cp2)
|
||||
self.aabb.expand_by(spline.end)
|
||||
|
||||
def _moveto(self, cmd, args):
|
||||
if cmd == 'M':
|
||||
self.pos = np.array(args[0:2])
|
||||
else:
|
||||
self.pos =+ np.array(args[0:2])
|
||||
if self.start is None or self.lastcmd in ['z', 'Z']:
|
||||
self.start = self.pos
|
||||
if len(args) > 2:
|
||||
# Implicit lineto
|
||||
cmd = 'L' if cmd == 'M' else 'l'
|
||||
self._lineto(cmd, args[2:])
|
||||
|
||||
def _lineto(self, cmd, args):
|
||||
if cmd == 'L':
|
||||
end = np.array(args[0:2])
|
||||
else:
|
||||
end = self.pos + np.array(args[0:2])
|
||||
d = end - self.pos
|
||||
self.splines.append(BezierSpline(self.pos, end))
|
||||
self.pos = end
|
||||
if len(args) > 2:
|
||||
self._lineto(cmd, args[2:])
|
||||
|
||||
def _hlineto(self, cmd, args):
|
||||
if cmd == 'H':
|
||||
end = np.array([args[0], self.pos[1]])
|
||||
else:
|
||||
end = np.array([args[0] + self.pos[0], self.pos[1]])
|
||||
self.splines.append(BezierSpline(self.pos, end))
|
||||
self.pos = end
|
||||
if len(args) > 1:
|
||||
self._hlineto(cmd, args[1:])
|
||||
|
||||
def _vlineto(self, cmd, args):
|
||||
if cmd == 'V':
|
||||
end = np.array([self.pos[0], args[0]])
|
||||
else:
|
||||
end = np.array([self.pos[0], args[0] + self.pos[1]])
|
||||
self.splines.append(BezierSpline(self.pos, end))
|
||||
self.pos = end
|
||||
if len(args) > 1:
|
||||
self._vlineto(cmd, args[1:])
|
||||
|
||||
def _curveto(self, cmd, args):
|
||||
start = self.pos
|
||||
cp1 = np.array(args[0:2])
|
||||
cp2 = np.array(args[2:4])
|
||||
end = np.array(args[4:6])
|
||||
|
||||
if cmd == 'c':
|
||||
cp1 += start
|
||||
cp2 += start
|
||||
end += start
|
||||
|
||||
self.splines.append(BezierSpline(start, cp1, cp2, end))
|
||||
self.pos = end
|
||||
self.cp2 = cp2
|
||||
|
||||
if len(args) > 6:
|
||||
self._curveto(cmd, args[6:])
|
||||
|
||||
def _scurveto(self, cmd, args):
|
||||
start = self.pos
|
||||
cp2 = np.array(args[0:2])
|
||||
end = np.array(args[2:4])
|
||||
|
||||
if cmd == 's':
|
||||
cp2 += start
|
||||
end += start
|
||||
|
||||
if self.cp2 != None and self.lastcmd in ['C', 'c', 'S', 's']:
|
||||
cp1 = 2*start - self.cp2
|
||||
else:
|
||||
cp1 = start
|
||||
|
||||
self.splines.append(BezierSpline(start, cp1, cp2, end))
|
||||
self.pos = end
|
||||
self.cp2 = cp2
|
||||
|
||||
if len(args) > 4:
|
||||
self._scurveto(cmd, args[4:])
|
||||
|
||||
def _close(self, cmd, args):
|
||||
self._lineto('L', self.start)
|
||||
self.splines.append(None)
|
||||
|
||||
def _color(self, value):
|
||||
if value == None or value.lower() == 'none':
|
||||
return None
|
||||
r = int(value[1:3], 16) / 255.0
|
||||
g = int(value[3:5], 16) / 255.0
|
||||
b = int(value[5:7], 16) / 255.0
|
||||
return [r, g, b]
|
||||
|
||||
def drawGL(self):
|
||||
if self.fill:
|
||||
glColor4f(self.fill[0], self.fill[1], self.fill[2], 1.0)
|
||||
gluTessBeginPolygon(tobj, None)
|
||||
gluTessBeginContour(tobj)
|
||||
for spline in self.splines:
|
||||
if spline:
|
||||
spline.drawGL_tess()
|
||||
else:
|
||||
gluTessEndContour(tobj)
|
||||
gluTessBeginContour(tobj)
|
||||
gluTessEndContour(tobj)
|
||||
gluTessEndPolygon(tobj)
|
||||
|
||||
if self.stroke:
|
||||
glColor4f(self.stroke[0], self.stroke[1], self.stroke[2], 1.0)
|
||||
glBegin(GL_LINE_STRIP)
|
||||
for spline in self.splines:
|
||||
if spline:
|
||||
spline.drawGL()
|
||||
else:
|
||||
glEnd()
|
||||
glBegin(GL_LINE_LOOP)
|
||||
glEnd()
|
||||
|
||||
def export(self, out):
|
||||
if self.id:
|
||||
out.write("obj %s\n" % self.id)
|
||||
else:
|
||||
out.write("obj\n")
|
||||
|
||||
if self.stroke:
|
||||
out.write("stroke %f %f %f\n" % (self.stroke[0], self.stroke[1], self.stroke[2]))
|
||||
if self.fill:
|
||||
out.write("fill %f %f %f\n" % (self.fill[0], self.fill[1], self.fill[2]))
|
||||
for spline in self.splines:
|
||||
if spline is None:
|
||||
out.write("skip\n")
|
||||
else:
|
||||
out.write("spline %f %f %f %f %f %f %f %f\n" %
|
||||
(spline.start[0], spline.start[1], spline.cp1[0], spline.cp1[1],
|
||||
spline.cp2[0], spline.cp2[1], spline.end[0], spline.end[1]))
|
||||
|
||||
out.write("\n")
|
||||
|
||||
class Scene(object):
|
||||
def __init__(self, filename):
|
||||
ns = '{http://www.w3.org/2000/svg}'
|
||||
self.paths = []
|
||||
self.aabb = AABB()
|
||||
def register(node):
|
||||
if node.tag == ns + 'path' or node.tag == ns + 'polygon' \
|
||||
or node.tag == ns + 'line' or node.tag == ns + 'rect':
|
||||
path = Path(node)
|
||||
self.aabb.expand_by_aabb(path.aabb)
|
||||
self.paths.append(path)
|
||||
else:
|
||||
for child in node:
|
||||
register(child)
|
||||
return
|
||||
register(et.parse(filename).getroot())
|
||||
|
||||
def drawGL(self):
|
||||
glClearColor(.3, .3, .3, 1.0)
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
size = self.aabb.size().max()
|
||||
xs = self.aabb.min[0] - size * 0.1
|
||||
ys = self.aabb.min[1] - size * 0.1
|
||||
size = size * 1.2
|
||||
glOrtho(xs, size, size*6.0/8.0, ys, 0, 1)
|
||||
for path in self.paths:
|
||||
path.drawGL()
|
||||
glutSwapBuffers()
|
||||
|
||||
def export(self, target):
|
||||
with open(target, "w") as f:
|
||||
for path in self.paths:
|
||||
path.export(f)
|
||||
|
||||
def keyboard(key, x, y):
|
||||
if key == 'q' or key == "\x1b":
|
||||
sys.exit(0)
|
||||
|
||||
def initGL():
|
||||
global tobj
|
||||
tobj = gluNewTess()
|
||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
|
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
|
||||
glEnable(GL_LINE_SMOOTH)
|
||||
glEnable(GL_POLYGON_SMOOTH)
|
||||
glEnable(GL_BLEND)
|
||||
glLineWidth(2.0)
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
|
||||
gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3fv)
|
||||
gluTessCallback(tobj, GLU_TESS_BEGIN, lambda x: glBegin(x))
|
||||
gluTessCallback(tobj, GLU_TESS_END, lambda: glEnd())
|
||||
gluTessCallback(tobj, GLU_TESS_COMBINE, lambda pos, data, weights: pos)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 3:
|
||||
print('Syntax: importsvg.py <input SVG file> <output SC2 file>')
|
||||
scene = Scene(sys.argv[1])
|
||||
scene.export(sys.argv[2])
|
||||
glutInit(sys.argv)
|
||||
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
|
||||
glutInitWindowSize(800, 600)
|
||||
glutCreateWindow("Bezier spline importer")
|
||||
glutDisplayFunc(lambda: scene.drawGL())
|
||||
glutKeyboardFunc(keyboard)
|
||||
initGL()
|
||||
glutMainLoop()
|
Loading…
Reference in New Issue