5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#!/usr/bin/env python
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman'''
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanCopyright (C) 2007 John Beard john.j.beard@gmail.com
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman##This extension draws 3d objects from a Wavefront .obj 3D file stored in a local folder
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman##Many settings for appearance, lighting, rotation, etc are available.
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# ^y
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# |
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# __--``| |_--``| __--
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# __--`` | __--``| |_--``
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# | z | | |_--``|
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# | <----|--------|-----_0-----|----------------
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# | | |_--`` | |
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# | __--`` <-``| |_--``
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# |__--`` x |__--``|
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# IMAGE PLANE SCENE|
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman# |
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#Vertices are given as "v" followed by three numbers (x,y,z).
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#All files need a vertex list
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#v x.xxx y.yyy z.zzz
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#Faces are given by a list of vertices
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#(vertex 1 is the first in the list above, 2 the second, etc):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#f 1 2 3
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#Edges are given by a list of vertices. These will be broken down
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#into adjacent pairs automatically.
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#l 1 2 3
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#Faces are rendered according to the painter's algorithm and perhaps
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#back-face culling, if selected. The parameter to sort the faces by
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#is user-selectable between max, min and average z-value of the vertices
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman######LICENCE#######
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanThis program is free software; you can redistribute it and/or modify
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanit under the terms of the GNU General Public License as published by
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanthe Free Software Foundation; either version 2 of the License, or
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman(at your option) any later version.
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanThis program is distributed in the hope that it will be useful,
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanbut WITHOUT ANY WARRANTY; without even the implied warranty of
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanGNU General Public License for more details.
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanYou should have received a copy of the GNU General Public License
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanalong with this program; if not, write to the Free Software
107e00c8104649437b9520d0ba298dba659e7cd7JazzyNicoFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman'''
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNico# standard library
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNicoimport sys
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNicoimport re
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanfrom math import *
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNico# local library
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNicoimport inkex
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNicoimport simplestyle
34401423d53f5ca799a8bda956328167fadcc58b~suvfrom simpletransform import computePointInNode
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNico
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNicoinkex.localize()
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNico
e4a094fa5446f7e5e226a3b10fdb7bf676808863JazzyNico# third party
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmantry:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman from numpy import *
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanexcept:
1377e5428a6c7651884b1d87c007077a31e7310cJazzyNico inkex.errormsg(_("Failed to import the numpy module. This module is required by this extension. Please install it and try again. On a Debian-like system this can be done with the command 'sudo apt-get install python-numpy'."))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman sys.exit()
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#FILE IO ROUTINES
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_filename(self_options):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if self_options.obj == 'from_file':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould file = self_options.spec_file
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould file = self_options.obj + '.obj'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return file
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittmandef objfile(name):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman import os.path
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if __name__ == '__main__':
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman filename = sys.argv[0]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman filename = __file__
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman path = os.path.abspath(os.path.dirname(filename))
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman path = os.path.join(path, 'Poly3DObjects', name)
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman return path
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef get_obj_data(obj, name):
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman infile = open(objfile(name))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman #regular expressions
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman getname = '(.[nN]ame:\\s*)(.*)'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould floating = '([\-\+\\d*\.e]*)' #a possibly non-integer number, with +/- and exponent.
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman getvertex = '(v\\s+)'+floating+'\\s+'+floating+'\\s+'+floating
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman getedgeline = '(l\\s+)(.*)'
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman getfaceline = '(f\\s+)(.*)'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould getnextint = '(\\d+)([/\\d]*)(.*)'#we need to deal with 123\343\123 or 123\\456 as equivalent to 123 (we are ignoring the other options in the obj file)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for line in infile:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if line[0]=='#': #we have a comment line
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould m = re.search(getname, line) #check to see if this line contains a name
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if m:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould obj.name = m.group(2) #if it does, set the property
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif line[0] == 'v': #we have a vertex (maybe)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould m = re.search(getvertex, line) #check to see if this line contains a valid vertex
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if m: #we have a valid vertex
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman obj.vtx.append( [float(m.group(2)), float(m.group(3)), float(m.group(4)) ] )
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif line[0] == 'l': #we have a line (maybe)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould m = re.search(getedgeline, line) #check to see if this line begins 'l '
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if m: #we have a line beginning 'l '
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould vtxlist = [] #buffer
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman while line:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman m2 = re.search(getnextint, line)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if m2:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman vtxlist.append( int(m2.group(1)) )
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman line = m2.group(3)#remainder
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman line = None
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if len(vtxlist) > 1:#we need at least 2 vertices to make an edge
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range (len(vtxlist)-1):#we can have more than one vertex per line - get adjacent pairs
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman obj.edg.append( ( vtxlist[i], vtxlist[i+1] ) )#get the vertex pair between that vertex and the next
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif line[0] == 'f': #we have a face (maybe)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman m = re.search(getfaceline, line)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if m: #we have a line beginning 'f '
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman vtxlist = []#buffer
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman while line:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman m2 = re.search(getnextint, line)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if m2:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman vtxlist.append( int(m2.group(1)) )
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman line = m2.group(3)#remainder
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman line = None
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if len(vtxlist) > 2: #we need at least 3 vertices to make an edge
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman obj.fce.append(vtxlist)
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if obj.name == '':#no name was found, use filename, without extension (.obj)
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman obj.name = name[0:-4]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#RENDERING AND SVG OUTPUT FUNCTIONS
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef draw_SVG_dot((cx, cy), st, name, parent):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'fill': st.fill, 'stroke-opacity':st.s_opac, 'fill-opacity':st.f_opac}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman circ_attribs = {'style':simplestyle.formatStyle(style),
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman inkex.addNS('label','inkscape'):name,
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman 'r':str(st.r),
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman 'cx':str(cx), 'cy':str(-cy)}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman inkex.etree.SubElement(parent, inkex.addNS('circle','svg'), circ_attribs )
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef draw_SVG_line((x1, y1),(x2, y2), st, name, parent):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'stroke-linecap':st.linecap}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman line_attribs = {'style':simplestyle.formatStyle(style),
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman inkex.addNS('label','inkscape'):name,
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman 'd':'M '+str(x1)+','+str(-y1)+' L '+str(x2)+','+str(-y2)}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef draw_SVG_poly(pts, face, st, name, parent):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman style = { 'stroke': '#000000', 'stroke-width':str(st.th), 'stroke-linejoin':st.linejoin, \
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman 'stroke-opacity':st.s_opac, 'fill': st.fill, 'fill-opacity':st.f_opac}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(len(face)):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if i == 0:#for first point
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman d = 'M'#move to
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman d = d + 'L'#line to
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman d = d+ str(pts[face[i]-1][0]) + ',' + str(-pts[face[i]-1][1])#add point
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman d = d + 'z' #close the polygon
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman line_attribs = {'style':simplestyle.formatStyle(style),
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman inkex.addNS('label','inkscape'):name,'d': d}
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman inkex.etree.SubElement(parent, inkex.addNS('path','svg'), line_attribs )
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef draw_edges( edge_list, pts, st, parent ):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould for edge in edge_list:#for every edge
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould pt_1 = pts[ edge[0]-1 ][0:2] #the point at the start
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould pt_2 = pts[ edge[1]-1 ][0:2] #the point at the end
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould name = 'Edge'+str(edge[0])+'-'+str(edge[1])
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould draw_SVG_line(pt_1,pt_2,st, name, parent)#plot edges
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef draw_faces( faces_data, pts, obj, shading, fill_col,st, parent):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould for face in faces_data:#for every polygon that has been sorted
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if shading:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould st.fill = get_darkened_colour(fill_col, face[1]/pi)#darken proportionally to angle to lighting vector
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould st.fill = get_darkened_colour(fill_col, 1)#do not darken colour
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould face_no = face[3]#the number of the face to draw
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould draw_SVG_poly(pts, obj.fce[ face_no ], st, 'Face:'+str(face_no), parent)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_darkened_colour( (r,g,b), factor):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#return a hex triplet of colour, reduced in lightness proportionally to a value between 0 and 1
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return '#' + "%02X" % floor( factor*r ) \
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould + "%02X" % floor( factor*g ) \
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould + "%02X" % floor( factor*b ) #make the colour string
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef make_rotation_log(options):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#makes a string recording the axes and angles of each roation, so an object can be repeated
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return options.r1_ax+str('%.2f'%options.r1_ang)+':'+\
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould options.r2_ax+str('%.2f'%options.r2_ang)+':'+\
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould options.r3_ax+str('%.2f'%options.r3_ang)+':'+\
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould options.r1_ax+str('%.2f'%options.r4_ang)+':'+\
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould options.r2_ax+str('%.2f'%options.r5_ang)+':'+\
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould options.r3_ax+str('%.2f'%options.r6_ang)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#MATHEMATICAL FUNCTIONS
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_angle( vector1, vector2 ): #returns the angle between two vectors
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return acos( dot(vector1, vector2) )
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef length(vector):#return the pythagorean length of a vector
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return sqrt(dot(vector,vector))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef normalise(vector):#return the unit vector pointing in the same direction as the argument
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return vector / length(vector)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef get_normal( pts, face): #returns the normal vector for the plane passing though the first three elements of face of pts
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman #n = pt[0]->pt[1] x pt[0]->pt[3]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman a = (array(pts[ face[0]-1 ]) - array(pts[ face[1]-1 ]))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman b = (array(pts[ face[0]-1 ]) - array(pts[ face[2]-1 ]))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman return cross(a,b).flatten()
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_unit_normal(pts, face, cw_wound): #returns the unit normal for the plane passing through the first three points of face, taking account of winding
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if cw_wound:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould winding = -1 #if it is clockwise wound, reverse the vecotr direction
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould winding = 1 #else leave alone
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return winding*normalise(get_normal(pts, face))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef rotate( matrix, angle, axis ):#choose the correct rotation matrix to use
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if axis == 'x':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould matrix = rot_x(matrix, angle)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif axis == 'y':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould matrix = rot_y(matrix, angle)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif axis == 'z':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould matrix = rot_z(matrix, angle)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return matrix
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef rot_z( matrix , a):#rotate around the z-axis by a radians
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = mat(array( [[ cos(a) , -sin(a) , 0 ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [ sin(a) , cos(a) , 0 ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [ 0 , 0 , 1 ]]))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return trans_mat*matrix
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef rot_y( matrix , a):#rotate around the y-axis by a radians
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = mat(array( [[ cos(a) , 0 , sin(a) ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [ 0 , 1 , 0 ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [-sin(a) , 0 , cos(a) ]]))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return trans_mat*matrix
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef rot_x( matrix , a):#rotate around the x-axis by a radians
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = mat(array( [[ 1 , 0 , 0 ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [ 0 , cos(a) ,-sin(a) ],
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould [ 0 , sin(a) , cos(a) ]]))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return trans_mat*matrix
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_transformed_pts( vtx_list, trans_mat):#translate the points according to the matrix
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould transformed_pts = []
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould for vtx in vtx_list:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould transformed_pts.append((trans_mat * mat(vtx).T).T.tolist()[0] )#transform the points at add to the list
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return transformed_pts
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef get_max_z(pts, face): #returns the largest z_value of any point in the face
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman max_z = pts[ face[0]-1 ][2]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(1, len(face)):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if pts[ face[0]-1 ][2] >= max_z:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman max_z = pts[ face[0]-1 ][2]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman return max_z
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef get_min_z(pts, face): #returns the smallest z_value of any point in the face
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman min_z = pts[ face[0]-1 ][2]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(1, len(face)):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if pts[ face[i]-1 ][2] <= min_z:
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman min_z = pts[ face[i]-1 ][2]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman return min_z
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef get_cent_z(pts, face): #returns the centroid z_value of any point in the face
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman sum = 0
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(len(face)):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman sum += pts[ face[i]-1 ][2]
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman return sum/len(face)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef get_z_sort_param(pts, face, method): #returns the z-sorting parameter specified by 'method' ('max', 'min', 'cent')
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_sort_param = ''
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if method == 'max':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_sort_param = get_max_z(pts, face)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould elif method == 'min':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_sort_param = get_min_z(pts, face)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_sort_param = get_cent_z(pts, face)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return z_sort_param
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#OBJ DATA MANIPULATION
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Goulddef remove_duplicates(list):#removes the duplicates from a list
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould list.sort()#sort the list
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould last = list[-1]
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould for i in range(len(list)-2, -1, -1):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if last==list[i]:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould del list[i]
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould last = list[i]
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return list
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmandef make_edge_list(face_list):#make an edge vertex list from an existing face vertex list
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman edge_list = []
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(len(face_list)):#for every face
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman edges = len(face_list[i]) #number of edges around that face
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for j in range(edges):#for every vertex in that face
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould new_edge = [face_list[i][j], face_list[i][(j+1)%edges] ]
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould new_edge.sort() #put in ascending order of vertices (to ensure we spot duplicates)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould edge_list.append( new_edge )#get the vertex pair between that vertex and the next
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould return remove_duplicates(edge_list)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanclass Style(object): #container for style information
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould def __init__(self,options):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.th = options.th
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.fill= '#ff0000'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.col = '#000000'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.r = 2
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.f_opac = str(options.f_opac/100.0)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.s_opac = str(options.s_opac/100.0)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.linecap = 'round'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.linejoin = 'round'
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittmanclass Obj(object): #a 3d object defined by the vertices and the faces (eg a polyhedron)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#edges can be generated from this information
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman def __init__(self):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.vtx = []
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.edg = []
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.fce = []
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.name=''
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould def set_type(self, options):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if options.type == 'face':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if self.fce != []:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.type = 'face'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
31dad42333cb2969e86d1f69556c958140a02b51alvinpenner inkex.errormsg(_('No face data found in specified file.'))
31dad42333cb2969e86d1f69556c958140a02b51alvinpenner inkex.errormsg(_('Try selecting "Edge Specified" in the Model File tab.\n'))
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.type = 'error'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if self.edg != []:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould self.type = 'edge'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:
31dad42333cb2969e86d1f69556c958140a02b51alvinpenner inkex.errormsg(_('No edge data found in specified file.'))
31dad42333cb2969e86d1f69556c958140a02b51alvinpenner inkex.errormsg(_('Try selecting "Face Specified" in the Model File tab.\n'))
31dad42333cb2969e86d1f69556c958140a02b51alvinpenner self.type = 'error'
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittmanclass Poly_3D(inkex.Effect):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman def __init__(self):
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman inkex.Effect.__init__(self)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--tab",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="tab", default="object")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman#MODEL FILE SETTINGS
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--obj",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="obj", default='cube')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--spec_file",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="spec_file", default='great_rhombicuboct.obj')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--cw_wound",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="inkbool",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="cw_wound", default='true')
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman self.OptionParser.add_option("--type",
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman action="store", type="string",
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman dest="type", default='face')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#VEIW SETTINGS
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r1_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r1_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r2_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r2_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r3_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r3_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r4_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r4_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r5_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r5_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r6_ax",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
871e6dec0a43899a0031100adcf3343a7746bfa5Alex Valavanis dest="r6_ax", default="X-Axis")
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r1_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r1_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r2_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r2_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r3_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r3_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r4_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r4_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r5_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r5_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--r6_ang",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="r6_ang", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--scl",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="scl", default=100.0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman#STYLE SETTINGS
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--show",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="show", default='faces')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--shade",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="inkbool",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="shade", default='true')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--f_r",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="int",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="f_r", default=255)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--f_g",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="int",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="f_g", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--f_b",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="int",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="f_b", default=0)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--f_opac",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="int",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="f_opac", default=100)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--s_opac",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="int",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="s_opac", default=100)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--th",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="th", default=2)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--lv_x",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="lv_x", default=1)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--lv_y",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="lv_y", default=1)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--lv_z",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="float",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="lv_z", default=-2)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--back",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="inkbool",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="back", default='false')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--norm",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="inkbool",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="norm", default='true')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman self.OptionParser.add_option("--z_sort",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman action="store", type="string",
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman dest="z_sort", default='min')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman def effect(self):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould so = self.options#shorthand
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould #INITIALISE AND LOAD DATA
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman obj = Obj() #create the object
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould file = get_filename(so)#get the file to load data from
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould get_obj_data(obj, file)#load data from the obj file
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould obj.set_type(so)#set the type (face or edge) as per the settings
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
d99a8a5066b95590e19a7c874884fdd6075b43f4apenner scale = self.unittouu('1px') # convert to document units
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould st = Style(so) #initialise style
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould fill_col = (so.f_r, so.f_g, so.f_b) #colour tuple for the face fill
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould lighting = normalise( (so.lv_x,-so.lv_y,so.lv_z) ) #unit light vector
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould #INKSCAPE GROUP TO CONTAIN THE POLYHEDRON
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould #Put in in the centre of the current view
34401423d53f5ca799a8bda956328167fadcc58b~suv view_center = computePointInNode(list(self.view_center), self.current_layer)
34401423d53f5ca799a8bda956328167fadcc58b~suv poly_transform = 'translate(' + str( view_center[0]) + ',' + str( view_center[1]) + ')'
d99a8a5066b95590e19a7c874884fdd6075b43f4apenner if scale != 1:
d99a8a5066b95590e19a7c874884fdd6075b43f4apenner poly_transform += ' scale(' + str(scale) + ')'
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould #we will put all the rotations in the object name, so it can be repeated in
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould poly_name = obj.name+':'+make_rotation_log(so)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould poly_attribs = {inkex.addNS('label','inkscape'):poly_name,
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould 'transform':poly_transform }
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould poly = inkex.etree.SubElement(self.current_layer, 'g', poly_attribs)#the group to put everything in
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
86df60ed2c0ede4dad6684c75acd907f6146c1b6JazzyNico #TRANSFORMATION OF THE OBJECT (ROTATION, SCALE, ETC)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = mat(identity(3, float)) #init. trans matrix as identity matrix
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(1, 7):#for each rotation
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman axis = eval('so.r'+str(i)+'_ax')
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman angle = eval('so.r'+str(i)+'_ang') *pi/180
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = rotate(trans_mat, angle, axis)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould trans_mat = trans_mat*so.scl #scale by linear factor (do this only after the transforms to reduce round-off)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould transformed_pts = get_transformed_pts(obj.vtx, trans_mat) #the points as projected in the z-axis onto the viewplane
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould #RENDERING OF THE OBJECT
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if so.show == 'vtx':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould for i in range(len(transformed_pts)):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould draw_SVG_dot([transformed_pts[i][0],transformed_pts[i][1]], st, 'Point'+str(i), poly)#plot points using transformed_pts x and y coords
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman elif so.show == 'edg':
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if obj.type == 'face':#we must generate the edge list from the faces
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman edge_list = make_edge_list(obj.fce)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:#we already have an edge list
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman edge_list = obj.edg
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould draw_edges( edge_list, transformed_pts, st, poly)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman elif so.show == 'fce':
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman if obj.type == 'face':#we have a face list
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman z_list = []
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman for i in range(len(obj.fce)):
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould face = obj.fce[i] #the face we are dealing with
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould norm = get_unit_normal(transformed_pts, face, so.cw_wound) #get the normal vector to the face
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould angle = get_angle( norm, lighting )#get the angle between the normal and the lighting vector
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_sort_param = get_z_sort_param(transformed_pts, face, so.z_sort)
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould if so.back or norm[2] > 0: # include all polygons or just the front-facing ones as needed
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould z_list.append((z_sort_param, angle, norm, i))#record the maximum z-value of the face and angle to light, along with the face ID and normal
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman z_list.sort(lambda x, y: cmp(x[0],y[0])) #sort by ascending sort parameter of the face
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould draw_faces( z_list, transformed_pts, obj, so.shade, fill_col, st, poly)
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould else:#we cannot generate a list of faces from the edges without a lot of computation
2b2321eb83f7bd0173589734d6f40b4fe90961f9helix inkex.errormsg(_('Face Data Not Found. Ensure file contains face data, and check the file is imported as "Face-Specified" under the "Model File" tab.\n'))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman else:
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould inkex.errormsg(_('Internal Error. No view type selected\n'))
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
a223910930e4cf964962a08cf1d30928395652c5pjrmif __name__ == '__main__':
a223910930e4cf964962a08cf1d30928395652c5pjrm e = Poly_3D()
a223910930e4cf964962a08cf1d30928395652c5pjrm e.affect()
5ebc6b4949d9f7aea914640d3e27e0a67e23ba8dozmikepittman
9fefe969c78790b255996a6fa8ebe02c403761baozmikepittman
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99