def geometry_from_mesh(dae, mesh): from collada import source, geometry srcs = [] # v srcs.append(source.FloatSource("verts-array", mesh.v, ('X', 'Y', 'Z'))) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#verts-array") # vc if mesh.vc is not None: input_list.addInput(len(srcs), 'COLOR', "#color-array") srcs.append( source.FloatSource("color-array", mesh.vc[mesh.f.ravel()], ('X', 'Y', 'Z'))) # f geom = geometry.Geometry(str(mesh), "geometry0", "mymesh", srcs) indices = np.dstack([mesh.f for _ in srcs]).ravel() triset = geom.createTriangleSet(indices, input_list, "materialref") geom.primitives.append(triset) # e if mesh.e is not None: indices = np.dstack([mesh.e for _ in srcs]).ravel() lineset = geom.createLineSet(indices, input_list, "materialref") geom.primitives.append(lineset) dae.geometries.append(geom) return geom
def colladaMesh(name, v, n, f, collada_xml, matnode=None): vertzyx = numpy.array(v) # * numpy.array([1,1,-1]) z, y, x = vertzyx.transpose() if SWAPZ: vertxyz = numpy.vstack([x, y, z]).transpose() * numpy.array([1, 1, -1]) else: vertxyz = numpy.vstack([x, y, z]).transpose() # vertxyz = numpy.vstack([x,y,z]).transpose()* numpy.array([1,1,-1]) vert_src = source.FloatSource(name + "_verts-array", vertxyz.flatten(), ('X', 'Y', 'Z')) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + name + "_verts-array") if type(n) != type(None) and len(n): norzyx = numpy.array(n) nz, ny, nx = norzyx.transpose() norxyz = numpy.vstack([nx, ny, nz]).transpose() #* numpy.array([1,1,-1]) # if SWAPZ : # norxyz = numpy.vstack([nx,ny,nz]).transpose()* numpy.array([1,1,-1]) # else : # norxyz = numpy.vstack([nx,ny,nz]).transpose() normal_src = source.FloatSource(name + "_normals-array", norxyz.flatten(), ('X', 'Y', 'Z')) geom = geometry.Geometry(scene, "geometry" + name, name, [vert_src, normal_src]) input_list.addInput(0, 'NORMAL', "#" + name + "_normals-array") else: geom = geometry.Geometry(scene, "geometry" + name, name, [vert_src]) #invert all the face fi = numpy.array(f, int)[:, ::-1] # if SWAPZ : # fi=numpy.array(f,int)[:,::-1] # else : # fi=numpy.array(f,int) triset = geom.createTriangleSet(fi.flatten(), input_list, name + "materialref") geom.primitives.append(triset) collada_xml.geometries.append(geom) master_geomnode = scene.GeometryNode(geom, [matnode]) master_node = scene.Node("node_" + name, children=[ master_geomnode, ]) #,transforms=[tr,rz,ry,rx,s]) return master_node
def main(): """ Generate .dae file. """ mesh = Collada() effect = material.Effect('effect0', [], 'phong', diffuse=(1, 0, 0), specular=(0, 1, 0)) mat = material.Material('material0', 'mymaterial', effect) mesh.effects.append(effect) mesh.materials.append(mat) vert_floats = numpy.array([ -50, 50, 50, 50, 50, 50, -50, -50, 50, 50, -50, 50, -50, 50, -50, 50, 50, -50, -50, -50, -50, 50, -50, -50 ]) normal_floats = numpy.array([ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 ]) componests = ('X', 'Y', 'Z') vert_src = source.FloatSource('cubeverts-array', vert_floats, componests) normal_src = source.FloatSource('cubenormals-array', normal_floats, componests) input_list = source.InputList() input_list.addInput(0, 'VERTEX', '#cubeverts-array') input_list.addInput(1, 'NORMAL', '#cubenormals-array') indices = numpy.array([ 0, 0, 2, 1, 3, 2, 0, 0, 3, 2, 1, 3, 0, 4, 1, 5, 5, 6, 0, 4, 5, 6, 4, 7, 6, 8, 7, 9, 3, 10, 6, 8, 3, 10, 2, 11, 0, 12, 4, 13, 6, 14, 0, 12, 6, 14, 2, 15, 3, 16, 7, 17, 5, 18, 3, 16, 5, 18, 1, 19, 5, 20, 7, 21, 6, 22, 5, 20, 6, 22, 4, 23 ]) geom = geometry.Geometry(mesh, 'geometry0', 'mycube', [vert_src, normal_src]) triset = geom.createTriangleSet(indices, input_list, 'materialref') geom.primitives.append(triset) mesh.geometries.append(geom) matnode = scene.MaterialNode('materialref', mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) node = scene.Node('node0', children=[geomnode]) myscene = scene.Scene('myscene', [node]) mesh.scenes.append(myscene) mesh.scene = myscene mesh.write('collada_sample.dae')
def buildMeshGeom(name, vertices, faces, vnormals, collada_xml, matnode): iname = name vertxyz = numpy.array(vertices) # * numpy.array([1,1,-1]) vert_src = source.FloatSource(iname + "_verts-array", vertxyz.flatten(), ('X', 'Y', 'Z')) geom = geometry.Geometry(collada_xml, "geometry" + iname, iname, [vert_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + iname + "_verts-array") fi = numpy.array(faces, int) #[:,::-1] triset = geom.createTriangleSet(fi.flatten(), input_list, iname + "materialref") geom.primitives.append(triset) collada_xml.geometries.append(geom) master_geomnode = scene.GeometryNode(geom, [matnode]) master_node = scene.Node("node_" + iname, children=[ master_geomnode, ]) #,transforms=[tr,rz,ry,rx,s]) return master_node
def export_dae(vertices, indices, fname): mesh = Collada() effect = material.Effect("effect0", [], "phong", diffuse=(1, 0, 0), specular=(0, 1, 0)) mat = material.Material("material0", "mymaterial", effect) mesh.effects.append(effect) mesh.materials.append(mat) vert_src = source.FloatSource('verts-array', numpy.array(vertices), ('X', 'Y', 'Z')) inlist = source.InputList() inlist.addInput(0, 'VERTEX', '#verts-array') indices = numpy.array(indices) geom = geometry.Geometry(mesh, 'geometry0', 'linac', [vert_src]) triset = geom.createTriangleSet(indices, inlist, "materialref") geom.primitives.append(triset) mesh.geometries.append(geom) matnode = scene.MaterialNode("materialref", mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) node = scene.Node("node0", children=[geomnode]) myscene = scene.Scene("myscene", [node]) mesh.scenes.append(myscene) mesh.scene = myscene mesh.write(fname)
def buildIngredientGeom(ingr, collada_xml, matnode): iname = ingr.o_name vertzyx = numpy.array(ingr.vertices) # * numpy.array([1,1,-1]) z, y, x = vertzyx.transpose() if SWAPZ: vertxyz = numpy.vstack([x, y, z]).transpose() * numpy.array([1, 1, -1]) else: vertxyz = numpy.vstack([x, y, z]).transpose() vert_src = source.FloatSource(iname + "_verts-array", vertxyz.flatten(), ('X', 'Y', 'Z')) if ingr.vnormals: norzyx = numpy.array(ingr.vnormals) nz, ny, nx = norzyx.transpose() if SWAPZ: norxyz = numpy.vstack([nx, ny, nz]).transpose() * numpy.array( [1, 1, -1]) else: norxyz = numpy.vstack([nx, ny, nz]).transpose() normal_src = source.FloatSource(iname + "_normals-array", norxyz.flatten(), ('X', 'Y', 'Z')) geom = geometry.Geometry(collada_xml, "geometry" + iname, iname, [vert_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + iname + "_verts-array") # input_list.addInput(0, 'NORMAL', "#"+iname+"_normals-array") #invert all the face fi = numpy.array(ingr.faces, int)[:, ::-1] # if SWAPZ : # fi=numpy.array(ingr.faces,int)[:,::-1] # else : # fi=numpy.array(ingr.faces,int) triset = geom.createTriangleSet(fi.flatten(), input_list, iname + "materialref") geom.primitives.append(triset) collada_xml.geometries.append(geom) master_geomnode = scene.GeometryNode(geom, [matnode]) master_node = scene.Node("node_" + iname, children=[ master_geomnode, ]) #,transforms=[tr,rz,ry,rx,s]) return master_node
def _save_dae(self, name): """\ Save the model as a collada file. """ mesh = Collada() effect = material.Effect("effect0", [], "phong", diffuse=(0.9,0.9,0.9), \ specular=(0.1,0.1,0.1)) mat = material.Material("material0", "mymaterial", effect) mesh.effects.append(effect) mesh.materials.append(mat) vert_floats = [] norm_floats = [] for vertex in self.vertices: vert_floats.append(vertex.x) vert_floats.append(vertex.y) vert_floats.append(vertex.z) for normal in self.normals: norm_floats.append(normal.x) norm_floats.append(normal.y) norm_floats.append(normal.z) indices = array(self.collada_indices) vert_src = source.FloatSource("vert-array", array(vert_floats), \ ('X', 'Y', 'Z')) norm_src = source.FloatSource("norm-array", array(norm_floats), \ ('X', 'Y', 'Z')) geom = geometry.Geometry(mesh, "geometry0", "solid", [vert_src, norm_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#vert-array") input_list.addInput(1, 'NORMAL', "#norm-array") triset = geom.createTriangleSet(indices, input_list, "materialref") geom.primitives.append(triset) mesh.geometries.append(geom) matnode = scene.MaterialNode("materialref", mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) node = scene.Node("node0", children=[geomnode]) myscene = scene.Scene("myscene", [node]) mesh.scenes.append(myscene) mesh.scene = myscene mesh.write(name+'.dae')
def occtopo_2_collada(dae_filepath, occface_list=None, face_rgb_colour_list=None, occedge_list=None): """ This function converts OCCtopologies into a pycollada Collada class. The units are in meter. Parameters ---------- occface_list : list of OCCfaces The geometries to be visualised with the results. The list of geometries must correspond to the list of results. Other OCCtopologies are also accepted, but the OCCtopology must contain OCCfaces. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface. dae_filepath : str The file path of the DAE (Collada) file. face_rgb_colour_list : list of tuple of floats, optional Each tuple is a r,g,b that is specifying the colour of the face. The number of colours must correspond to the number of OCCfaces. occedge_list : list of OCCedges, optional OCCedges to be visualised together, Default = None. Returns ------- mesh : pycollada Collada class object The collada object from pycollada library. """ import collada from collada import asset, material, source, geometry, scene import numpy mesh = collada.Collada() mesh.assetInfo.upaxis = asset.UP_AXIS.Z_UP mesh.assetInfo.unitmeter = 1.0 mesh.assetInfo.unitname = "meter" if face_rgb_colour_list != None: mat_list = [] colour_cnt = 0 for rgb_colour in face_rgb_colour_list: effect = material.Effect("effect" + str(colour_cnt), [], "phong", diffuse=rgb_colour, specular=rgb_colour, double_sided=True) mat = material.Material("material" + str(colour_cnt), "mymaterial" + str(colour_cnt), effect) mesh.effects.append(effect) mesh.materials.append(mat) mat_list.append(mat) colour_cnt += 1 else: effect = material.Effect("effect0", [], "phong", diffuse=(1, 1, 1), specular=(1, 1, 1)) mat = material.Material("material0", "mymaterial", effect) mesh.effects.append(effect) mesh.materials.append(mat) edgeeffect = material.Effect("edgeeffect0", [], "phong", diffuse=(1, 1, 1), specular=(1, 1, 1), double_sided=True) edgemat = material.Material("edgematerial0", "myedgematerial", effect) mesh.effects.append(edgeeffect) mesh.materials.append(edgemat) geomnode_list = [] shell_cnt = 0 if occface_list: for occshell in occface_list: vert_floats = [] normal_floats = [] vcnt = [] indices = [] face_list = fetch.topo_explorer(occshell, "face") vert_cnt = 0 for face in face_list: wire_list = fetch.topo_explorer(face, "wire") nwire = len(wire_list) if nwire == 1: pyptlist = fetch.points_frm_occface(face) vcnt.append(len(pyptlist)) face_nrml = calculate.face_normal(face) pyptlist.reverse() for pypt in pyptlist: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) normal_floats.append(face_nrml[0]) normal_floats.append(face_nrml[1]) normal_floats.append(face_nrml[2]) indices.append(vert_cnt) vert_cnt += 1 if nwire > 1: tri_face_list = construct.simple_mesh(face) for tface in tri_face_list: pyptlist = fetch.points_frm_occface(tface) vcnt.append(len(pyptlist)) face_nrml = calculate.face_normal(tface) pyptlist.reverse() for pypt in pyptlist: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) normal_floats.append(face_nrml[0]) normal_floats.append(face_nrml[1]) normal_floats.append(face_nrml[2]) indices.append(vert_cnt) vert_cnt += 1 vert_id = "ID" + str(shell_cnt) + "1" vert_src = source.FloatSource(vert_id, numpy.array(vert_floats), ('X', 'Y', 'Z')) normal_id = "ID" + str(shell_cnt) + "2" normal_src = source.FloatSource(normal_id, numpy.array(normal_floats), ('X', 'Y', 'Z')) geom = geometry.Geometry(mesh, "geometry" + str(shell_cnt), "geometry" + str(shell_cnt), [vert_src, normal_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + vert_id) #input_list.addInput(1, 'NORMAL', "#"+normal_id) vcnt = numpy.array(vcnt) indices = numpy.array(indices) if face_rgb_colour_list != None: mat_name = "materialref" + str(shell_cnt) polylist = geom.createPolylist(indices, vcnt, input_list, mat_name) geom.primitives.append(polylist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, mat_list[shell_cnt], inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) else: mat_name = "materialref" polylist = geom.createPolylist(indices, vcnt, input_list, mat_name) geom.primitives.append(polylist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) shell_cnt += 1 if occedge_list: edge_cnt = 0 for occedge in occedge_list: vert_floats = [] indices = [] pypt_list = fetch.points_frm_edge(occedge) if len(pypt_list) == 2: vert_cnt = 0 for pypt in pypt_list: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) indices.append(vert_cnt) vert_cnt += 1 vert_id = "ID" + str(edge_cnt + shell_cnt) + "1" vert_src = source.FloatSource(vert_id, numpy.array(vert_floats), ('X', 'Y', 'Z')) geom = geometry.Geometry( mesh, "geometry" + str(edge_cnt + shell_cnt), "geometry" + str(edge_cnt + shell_cnt), [vert_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + vert_id) indices = numpy.array(indices) mat_name = "edgematerialref" linelist = geom.createLineSet(indices, input_list, mat_name) geom.primitives.append(linelist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, edgemat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) edge_cnt += 1 vis_node = scene.Node("node0", children=geomnode_list) myscene = scene.Scene("myscene", [vis_node]) mesh.scenes.append(myscene) mesh.scene = myscene return mesh
def generate_collada(coords, relative_texture_path): """generate the pycollada mesh out of the coordinates array Arguments: coords {[[[]]]} -- 2d array of 3d coordinates relative_texture_path {str} -- relative path to the texture, relative to the generated collada file Returns: Collada -- final collada mesh """ # create the mesh mesh = Collada() # create source arrays vert_src = source.FloatSource('verts-array', generate_vertex_array(coords), ('X', 'Y', 'Z')) normal_src = source.FloatSource('normals-array', generate_normal_array(coords), ('X', 'Y', 'Z')) uv_src = source.FloatSource('uv-array', generate_uv_array(coords), ('S', 'T')) # create geometry and add the sources geom = geometry.Geometry(mesh, 'geometry', 'terrain', [vert_src, normal_src, uv_src]) # define inputs to triangle set input_list = source.InputList() input_list.addInput(0, 'VERTEX', '#verts-array') input_list.addInput(1, 'NORMAL', '#normals-array') input_list.addInput(2, 'TEXCOORD', '#uv-array', set='0') # create index array indices = generate_index_array(coords) # repeat each of the entries for vertex, normal, uv indices = np.repeat(indices, 3) # create triangle set, add it to list of geometries in the mesh triset = geom.createTriangleSet(indices, input_list, 'material') geom.primitives.append(triset) mesh.geometries.append(geom) # add a material image = material.CImage('material-image', relative_texture_path) surface = material.Surface('material-image-surface', image) sampler2d = material.Sampler2D('material-image-sampler', surface) material_map = material.Map(sampler2d, 'UVSET0') effect = material.Effect('material-effect', [surface, sampler2d], 'lambert', emission=(0.0, 0.0, 0.0, 1), ambient=(0.0, 0.0, 0.0, 1), diffuse=material_map, transparent=material_map, transparency=0.0, double_sided=True) mat = material.Material('materialID', 'material', effect) mesh.effects.append(effect) mesh.materials.append(mat) mesh.images.append(image) # instantiate geometry into a scene node matnode = scene.MaterialNode('material', mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) node = scene.Node('model', children=[geomnode]) # create scene myscene = scene.Scene('scene', [node]) mesh.scenes.append(myscene) mesh.scene = myscene return mesh
def instancesToCollada(self, parent_object, collada_xml=None, instance_node=True, **kw): try: from upy.transformation import decompose_matrix from collada import Collada from collada import material from collada import source from collada import geometry from collada import scene except: return inst_parent = parent_object #self.getCurrentSelection()[0] ch = self.getChilds(inst_parent) transpose = True if "transpose" in kw: transpose = kw["transpose"] #instance master if "mesh" in kw and kw["mesh"] is not None: inst_master = kw["mesh"] f, v, vn = self.DecomposeMesh(kw["mesh"], edit=False, copy=False, tri=True, transform=False) else: inst_master = self.getMasterInstance(ch[0]) print "master is ", inst_master #grabb v,f,n of inst_master f, v, vn = self.DecomposeMesh(inst_master, edit=False, copy=False, tri=True, transform=False) #special case when come from x-z swap # v=[[vv[2],vv[1],vv[0]] for vv in v] # go back to regular #-90degree rotation onY mry90 = self.rotation_matrix(-math.pi / 2.0, [0.0, 1.0, 0.0]) #? v = self.ApplyMatrix(v, mry90) #same for the normal? vn = self.ApplyMatrix(vn, mry90) #same for the normal? iname = self.getName(inst_master) pname = self.getName(inst_parent) if collada_xml is None: collada_xml = Collada() collada_xml.assetInfo.unitname = "centimeter" collada_xml.assetInfo.unitmeter = 0.01 mat = self.getMaterialObject(inst_master) if len(mat): mat = mat[0] props = self.getMaterialProperty(mat, color=1) #,specular_color=1) print "colors is ", props effect = material.Effect( "effect" + iname, [], "phong", diffuse=[props["color"][0], props["color"][1], props["color"][2], 1.0]) # specular = props["specular_color"]) mat = material.Material("material" + iname, iname + "material", effect) collada_xml.effects.append(effect) collada_xml.materials.append(mat) matnode = scene.MaterialNode(iname + "material" + "ref", mat, inputs=[]) #the geom #invert Z ? for C4D? vertzyx = numpy.array(v) #* numpy.array([1,1,-1]) z, y, x = vertzyx.transpose() vertxyz = numpy.vstack([x, y, z]).transpose() #* numpy.array([1,1,-1]) vert_src = source.FloatSource(iname + "_verts-array", vertxyz.flatten(), ('X', 'Y', 'Z')) norzyx = numpy.array(vn) nz, ny, nx = norzyx.transpose() norxyz = numpy.vstack([nx, ny, nz]).transpose() * numpy.array([1, 1, -1]) normal_src = source.FloatSource(iname + "_normals-array", norxyz.flatten(), ('X', 'Y', 'Z')) geom = geometry.Geometry(collada_xml, "geometry" + iname, iname, [vert_src, normal_src]) # normal_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + iname + "_verts-array") input_list.addInput(0, 'NORMAL', "#" + iname + "_normals-array") #invert all the face fi = numpy.array(f, int) #[:,::-1] triset = geom.createTriangleSet(fi.flatten(), input_list, iname + "materialref") geom.primitives.append(triset) collada_xml.geometries.append(geom) #the noe #instance here ? #creae the instance maser node : if instance_node: master_geomnode = scene.GeometryNode(geom, [matnode]) #doesn work ? master_node = scene.Node("node_" + iname, children=[ master_geomnode, ]) #,transforms=[tr,rz,ry,rx,s]) g = [] for c in ch: #collada.scene.NodeNode if instance_node: geomnode = scene.NodeNode(master_node) else: geomnode = scene.GeometryNode(geom, [matnode]) matrix = self.ToMat( self.getTransformation(c)) #.transpose()#.flatten() if transpose: matrix = numpy.array(matrix).transpose() scale, shear, euler, translate, perspective = decompose_matrix(matrix) scale = self.getScale(c) p = translate #matrix[3,:3]/100.0#unit problem tr = scene.TranslateTransform(p[0], p[1], p[2]) rx = scene.RotateTransform(1, 0, 0, numpy.degrees(euler[0])) ry = scene.RotateTransform(0, 1, 0, numpy.degrees(euler[1])) rz = scene.RotateTransform(0, 0, 1, numpy.degrees(euler[2])) # rx=scene.RotateTransform(-1,0,0,numpy.degrees(euler[0])) # ry=scene.RotateTransform(0,-1,0,numpy.degrees(euler[1])) # rz=scene.RotateTransform(0,0,1,numpy.degrees(euler[2])) s = scene.ScaleTransform(scale[0], scale[1], scale[2]) #n = scene.NodeNode(master_node,transforms=[tr,rz,ry,rx,s]) # gnode = scene.Node(self.getName(c)+"_inst", children=[geomnode,]) n = scene.Node( self.getName(c), children=[ geomnode, ], transforms=[tr, rz, ry, rx, s] ) #scene.MatrixTransform(matrix)[scene.MatrixTransform(numpy.array(matrix).reshape(16,))] # n = scene.Node(self.getName(c), children=[geomnode,], # transforms=[scene.MatrixTransform(numpy.array(matrix).reshape(16,))]) #scene.MatrixTransform(matrix)[scene.MatrixTransform(numpy.array(matrix).reshape(16,))] g.append(n) node = scene.Node( pname, children=g) #,transforms=[scene.RotateTransform(0,1,0,90.0)]) if "parent_node" in kw: kw["parent_node"].children.append(node) node = kw["parent_node"] if not len(collada_xml.scenes): myscene = scene.Scene("myscene", [node]) collada_xml.scenes.append(myscene) collada_xml.scene = myscene else: if "parent_node" not in kw: collada_xml.scene.nodes.append(node) if instance_node: collada_xml.nodes.append(master_node) return collada_xml