chiark / gitweb /
e448fdeba304db3951bbe553fb20e5b6f604d21e
[cura.git] / Cura / util / meshLoaders / dae.py
1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 from  xml.parsers.expat import ParserCreate
5
6 from Cura.util import mesh
7
8 def loadScene(filename):
9         loader = daeLoader(filename)
10         return [loader.obj]
11
12 class daeLoader(object):
13         def __init__(self, filename):
14                 self.obj = mesh.printableObject()
15                 self.mesh = self.obj._addMesh()
16
17                 r = ParserCreate()
18                 r.StartElementHandler = self._StartElementHandler
19                 r.EndElementHandler = self._EndElementHandler
20                 r.CharacterDataHandler = self._CharacterDataHandler
21
22                 self._base = {}
23                 self._cur = self._base
24                 self._idMap = {}
25                 self._geometryList = []
26                 self._faceCount = 0
27                 r.ParseFile(open(filename, "r"))
28                 
29                 self.vertexCount = 0
30                 for instance_visual_scene in self._base['collada'][0]['scene'][0]['instance_visual_scene']:
31                         for node in self._idMap[instance_visual_scene['_url']]['node']:
32                                 self._ProcessNode1(node)
33                 self.mesh._prepareFaceCount(self._faceCount)
34                 for instance_visual_scene in self._base['collada'][0]['scene'][0]['instance_visual_scene']:
35                         for node in self._idMap[instance_visual_scene['_url']]['node']:
36                                 self._ProcessNode2(node)
37
38                 scale = float(self._base['collada'][0]['asset'][0]['unit'][0]['_meter']) * 1000
39                 self.mesh.vertexes *= scale
40                 
41                 self._base = None
42                 self._cur = None
43                 self._idMap = None
44                 
45                 self.obj._postProcessAfterLoad()
46
47         def _ProcessNode1(self, node):
48                 if 'node' in node:
49                         for n in node['node']:
50                                 self._ProcessNode1(n)
51                 if 'instance_geometry' in node:
52                         for instance_geometry in node['instance_geometry']:
53                                 mesh = self._idMap[instance_geometry['_url']]['mesh'][0]
54                                 if 'triangles' in mesh:
55                                         for triangles in mesh['triangles']:
56                                                 self._faceCount += int(triangles['_count'])
57                                 elif 'lines' in mesh:
58                                         pass #Ignore lines
59                                 else:
60                                         print mesh.keys()
61                 if 'instance_node' in node:
62                         for instance_node in node['instance_node']:
63                                 self._ProcessNode1(self._idMap[instance_node['_url']])
64
65         def _ProcessNode2(self, node, matrix = None):
66                 if 'matrix' in node:
67                         oldMatrix = matrix
68                         matrix = map(float, node['matrix'][0]['__data'].split())
69                         if oldMatrix is not None:
70                                 newMatrix = [0]*16
71                                 newMatrix[0] = oldMatrix[0] * matrix[0] + oldMatrix[1] * matrix[4] + oldMatrix[2] * matrix[8] + oldMatrix[3] * matrix[12]
72                                 newMatrix[1] = oldMatrix[0] * matrix[1] + oldMatrix[1] * matrix[5] + oldMatrix[2] * matrix[9] + oldMatrix[3] * matrix[13]
73                                 newMatrix[2] = oldMatrix[0] * matrix[2] + oldMatrix[1] * matrix[6] + oldMatrix[2] * matrix[10] + oldMatrix[3] * matrix[14]
74                                 newMatrix[3] = oldMatrix[0] * matrix[3] + oldMatrix[1] * matrix[7] + oldMatrix[2] * matrix[11] + oldMatrix[3] * matrix[15]
75                                 newMatrix[4] = oldMatrix[4] * matrix[0] + oldMatrix[5] * matrix[4] + oldMatrix[6] * matrix[8] + oldMatrix[7] * matrix[12]
76                                 newMatrix[5] = oldMatrix[4] * matrix[1] + oldMatrix[5] * matrix[5] + oldMatrix[6] * matrix[9] + oldMatrix[7] * matrix[13]
77                                 newMatrix[6] = oldMatrix[4] * matrix[2] + oldMatrix[5] * matrix[6] + oldMatrix[6] * matrix[10] + oldMatrix[7] * matrix[14]
78                                 newMatrix[7] = oldMatrix[4] * matrix[3] + oldMatrix[5] * matrix[7] + oldMatrix[6] * matrix[11] + oldMatrix[7] * matrix[15]
79                                 newMatrix[8] = oldMatrix[8] * matrix[0] + oldMatrix[9] * matrix[4] + oldMatrix[10] * matrix[8] + oldMatrix[11] * matrix[12]
80                                 newMatrix[9] = oldMatrix[8] * matrix[1] + oldMatrix[9] * matrix[5] + oldMatrix[10] * matrix[9] + oldMatrix[11] * matrix[13]
81                                 newMatrix[10] = oldMatrix[8] * matrix[2] + oldMatrix[9] * matrix[6] + oldMatrix[10] * matrix[10] + oldMatrix[11] * matrix[14]
82                                 newMatrix[11] = oldMatrix[8] * matrix[3] + oldMatrix[9] * matrix[7] + oldMatrix[10] * matrix[11] + oldMatrix[11] * matrix[15]
83                                 newMatrix[12] = oldMatrix[12] * matrix[0] + oldMatrix[13] * matrix[4] + oldMatrix[14] * matrix[8] + oldMatrix[15] * matrix[12]
84                                 newMatrix[13] = oldMatrix[12] * matrix[1] + oldMatrix[13] * matrix[5] + oldMatrix[14] * matrix[9] + oldMatrix[15] * matrix[13]
85                                 newMatrix[14] = oldMatrix[12] * matrix[2] + oldMatrix[13] * matrix[6] + oldMatrix[14] * matrix[10] + oldMatrix[15] * matrix[14]
86                                 newMatrix[15] = oldMatrix[12] * matrix[3] + oldMatrix[13] * matrix[7] + oldMatrix[14] * matrix[11] + oldMatrix[15] * matrix[15]
87                                 matrix = newMatrix
88                 if 'node' in node:
89                         for n in node['node']:
90                                 self._ProcessNode2(n, matrix)
91                 if 'instance_geometry' in node:
92                         for instance_geometry in node['instance_geometry']:
93                                 mesh = self._idMap[instance_geometry['_url']]['mesh'][0]
94                                 
95                                 if 'triangles' in mesh:
96                                         for triangles in mesh['triangles']:
97                                                 for input in triangles['input']:
98                                                         if input['_semantic'] == 'VERTEX':
99                                                                 vertices = self._idMap[input['_source']]
100                                                 for input in vertices['input']:
101                                                         if input['_semantic'] == 'POSITION':
102                                                                 vertices = self._idMap[input['_source']]
103                                                 indexList = map(int, triangles['p'][0]['__data'].split())
104                                                 positionList = map(float, vertices['float_array'][0]['__data'].split())
105
106                                                 faceCount = int(triangles['_count'])
107                                                 stepSize = len(indexList) / (faceCount * 3)
108                                                 for i in xrange(0, faceCount):
109                                                         idx0 = indexList[((i * 3) + 0) * stepSize]
110                                                         idx1 = indexList[((i * 3) + 1) * stepSize]
111                                                         idx2 = indexList[((i * 3) + 2) * stepSize]
112                                                         x0 = positionList[idx0*3]
113                                                         y0 = positionList[idx0*3+1]
114                                                         z0 = positionList[idx0*3+2]
115                                                         x1 = positionList[idx1*3]
116                                                         y1 = positionList[idx1*3+1]
117                                                         z1 = positionList[idx1*3+2]
118                                                         x2 = positionList[idx2*3]
119                                                         y2 = positionList[idx2*3+1]
120                                                         z2 = positionList[idx2*3+2]
121                                                         if matrix is not None:
122                                                                 self.mesh._addFace(
123                                                                         x0 * matrix[0] + y0 * matrix[1] + z0 * matrix[2] + matrix[3], x0 * matrix[4] + y0 * matrix[5] + z0 * matrix[6] + matrix[7], x0 * matrix[8] + y0 * matrix[9] + z0 * matrix[10] + matrix[11],
124                                                                         x1 * matrix[0] + y1 * matrix[1] + z1 * matrix[2] + matrix[3], x1 * matrix[4] + y1 * matrix[5] + z1 * matrix[6] + matrix[7], x1 * matrix[8] + y1 * matrix[9] + z1 * matrix[10] + matrix[11],
125                                                                         x2 * matrix[0] + y2 * matrix[1] + z2 * matrix[2] + matrix[3], x2 * matrix[4] + y2 * matrix[5] + z2 * matrix[6] + matrix[7], x2 * matrix[8] + y2 * matrix[9] + z2 * matrix[10] + matrix[11]
126                                                                 )
127                                                         else:
128                                                                 self.mesh._addFace(x0, y0, z0, x1, y1, z1, x2, y2, z2)
129                 if 'instance_node' in node:
130                         for instance_node in node['instance_node']:
131                                 self._ProcessNode2(self._idMap[instance_node['_url']], matrix)
132         
133         def _StartElementHandler(self, name, attributes):
134                 name = name.lower()
135                 if not name in self._cur:
136                         self._cur[name] = []
137                 new = {'__name': name, '__parent': self._cur}
138                 self._cur[name].append(new)
139                 self._cur = new
140                 for k in attributes.keys():
141                         self._cur['_' + k] = attributes[k]
142                 
143                 if 'id' in attributes:
144                         self._idMap['#' + attributes['id']] = self._cur
145                 
146         def _EndElementHandler(self, name):
147                 self._cur = self._cur['__parent']
148
149         def _CharacterDataHandler(self, data):
150                 if len(data.strip()) < 1:
151                         return
152                 if '__data' in self._cur:
153                         self._cur['__data'] += data
154                 else:
155                         self._cur['__data'] = data
156         
157         def _GetWithKey(self, item, basename, key, value):
158                 input = basename
159                 while input in item:
160                         if item[basename]['_'+key] == value:
161                                 return self._idMap[item[input]['_source']]
162                         basename += "!"