def __init__(self, id, name, effect, xmlnode=None): """Creates a material. :param str id: A unique string identifier for the material :param str name: A name for the material :param collada.material.Effect effect: The effect instantiated in this material :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the material""" self.name = name """The name for the material""" self.effect = effect """The :class:`collada.material.Effect` instantiated in this material""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the surface.""" else: self.xmlnode = E.material( E.instance_effect(url="#%s" % self.effect.id) , id=str(self.id), name=str(self.name))
def save(self): """Saves the source back to :attr:`xmlnode`""" shape_in = self.data.shape self.data.shape = (-1,) txtdata = ' '.join(map(lambda x: '%.7g'%x , self.data.tolist())) rawlen = len( self.data ) if len(self.components) == 1 and self.components[0]==None: #no components provided self.data.shape = shape_in else: self.data.shape = (-1, len(self.components) ) acclen = len( self.data ) node = self.xmlnode.find(tag('float_array')) node.text = txtdata node.set('count', str(rawlen)) node.set('id', self.id+'-array' ) node = self.xmlnode.find('%s/%s'%(tag('technique_common'), tag('accessor'))) node.clear() node.set('count', str(acclen)) node.set('source', '#'+self.id+'-array') if len(self.components) == 1 and self.components[0]==None: node.set('stride', str(rawlen/acclen)) if shape_in[1::] == (4,4): node.append(E.param(type='float4x4')) else: node.append(E.param(type='float')) else: node.set('stride', str(len(self.components))) for c in self.components: node.append(E.param(type='float', name=c)) self.xmlnode.set('id', self.id )
def __init__(self, id, path, collada = None, xmlnode = None): """Create an image object. :param str id: A unique string identifier for the image :param str path: Path relative to the collada document where the image is located :param collada.Collada collada: The collada object this image belongs to :param xmlnode: If loaded from xml, the node this data comes from """ self.id = id """The unique string identifier for the image""" self.path = path """Path relative to the collada document where the image is located""" self.collada = collada self._data = None self._pilimage = None self._uintarray = None self._floatarray = None if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the image.""" else: self.xmlnode = E.image( E.init_from(path) , id=self.id, name=self.id)
def __init__(self, symbol, target, inputs, xmlnode = None): """Creates a material node :param str symbol: The symbol within a geometry this material should be bound to :param collada.material.Material target: The material object being bound to :param list inputs: A list of tuples of the form ``(semantic, input_semantic, set)`` mapping texcoords or other inputs to material input channels, e.g. ``('TEX0', 'TEXCOORD', '0')`` would map the effect parameter ``'TEX0'`` to the ``'TEXCOORD'`` semantic of the geometry, using texture coordinate set ``0``. :param xmlnode: When loaded, the xmlnode it comes from """ self.symbol = symbol """The symbol within a geometry this material should be bound to""" self.target = target """An object of type :class:`collada.material.Material` representing the material object being bound to""" self.inputs = inputs """A list of tuples of the form ``(semantic, input_semantic, set)`` mapping texcoords or other inputs to material input channels, e.g. ``('TEX0', 'TEXCOORD', '0')`` would map the effect parameter ``'TEX0'`` to the ``'TEXCOORD'`` semantic of the geometry, using texture coordinate set ``0``.""" if xmlnode is not None: self.xmlnode = xmlnode """ElementTree representation of the material node.""" else: self.xmlnode = E.instance_material( *[E.bind_vertex_input(semantic=sem, input_semantic=input_sem, input_set=set) for sem, input_sem, set in self.inputs] , **{'symbol': self.symbol, 'target':"#%s"%self.target.id} )
def __init__(self, id, surface, minfilter=None, magfilter=None, xmlnode=None): """Create a Sampler2D object. :param str id: A string identifier for the sampler within the local scope of the material :param collada.material.Surface surface: Surface instance that this object samples from :param str minfilter: Minification filter string id, see collada spec for details :param str magfilter: Maximization filter string id, see collada spec for details :param xmlnode: If loaded from xml, the xml node """ self.id = id """The string identifier for the sampler within the local scope of the material""" self.surface = surface """Surface instance that this object samples from""" self.minfilter = minfilter """Minification filter string id, see collada spec for details""" self.magfilter = magfilter """Maximization filter string id, see collada spec for details""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the sampler.""" else: sampler_node = E.sampler2D(E.source(self.surface.id)) if minfilter: sampler_node.append(E.minfilter(self.minfilter)) if magfilter: sampler_node.append(E.magfilter(self.magfilter)) self.xmlnode = E.newparam(sampler_node, sid=self.id)
def __init__(self, geometry, materials=None, xmlnode=None): """Creates a geometry node :param collada.geometry.Geometry geometry: A geometry to instantiate in the scene :param list materials: A list containing items of type :class:`collada.scene.MaterialNode`. Each of these represents a material that the geometry should be bound to. :param xmlnode: When loaded, the xmlnode it comes from """ self.geometry = geometry """An object of type :class:`collada.geometry.Geometry` representing the geometry to bind in the scene""" self.materials = [] """A list containing items of type :class:`collada.scene.MaterialNode`. Each of these represents a material that the geometry is bound to.""" if materials is not None: self.materials = materials if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the geometry node.""" else: self.xmlnode = E.instance_geometry(url="#%s" % self.geometry.id) if len(self.materials) > 0: self.xmlnode.append( E.bind_material( E.technique_common( *[mat.xmlnode for mat in self.materials])))
def __init__(self, id, color, xmlnode = None): """Create a new ambient light. :param str id: A unique string identifier for the light :param tuple color: Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the light""" self.color = color """Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the light.""" else: self.xmlnode = E.light( E.technique_common( E.ambient( E.color(' '.join(map(str, self.color))) ) ) , id=self.id, name=self.id)
def __init__(self, id, color, xmlnode=None): """Create a new ambient light. :param str id: A unique string identifier for the light :param tuple color: Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the light""" self.color = color """Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the light.""" else: self.xmlnode = E.light(E.technique_common( E.ambient(E.color(' '.join(map(str, self.color))))), id=self.id, name=self.id)
def __init__(self, id, color, xmlnode=None): """Create a new directional light. :param str id: A unique string identifier for the light :param tuple color: Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the light""" self.direction = numpy.array([0, 0, -1], dtype=numpy.float32) #Not documenting this because it doesn't make sense to set the direction # of an unbound light. The direction isn't set until binding in a scene. self.color = color """Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the light.""" else: self.xmlnode = E.light(E.technique_common( E.directional(E.color(' '.join(map(str, self.color))))), id=self.id, name=self.id)
def create_inertia(self, inertia, color, name=""): H_body_com = principalframe(inertia) Mcom = transport(inertia, H_body_com) mass = Mcom[5, 5] m_o_inertia = Mcom[[0, 1, 2], [0, 1, 2]] position = H_body_com[0:3, 3] yaw, pitch, roll = np.degrees( rotzyx_angles(H_body_com)) # in degrees for collada specification self.physics_model.append( E.rigid_body(E.technique_common( E.dynamic("true"), E.mass(str(mass)), E.mass_frame( E.translate(" ".join(map(str, position)), sid="location"), E.rotate(" ".join(map(str, [0, 0, 1, yaw])), sid="rotationZ"), E.rotate(" ".join(map(str, [0, 1, 0, pitch])), sid="rotationY"), E.rotate(" ".join(map(str, [1, 0, 0, roll])), sid="rotationX"), ), E.inertia(" ".join(map(str, m_o_inertia))), ), sid=name))
def _create_anim_elem(name, timeline, value): """""" idName = name + "-animation" animElem = E.animation(id=idName) animElem.append( _create_anim_src_elem(idName, timeline, "input", "float", "TIME", "float")) animElem.append( _create_anim_src_elem(idName, ["STEP"] * len(timeline), "interpolation", "Name", "INTERPOLATION", "name")) animElem.append( _create_anim_src_elem(idName, value.flatten(), "output", "float", "TRANSFORM", "float4x4")) animElem.append( E.sampler(*[ E.input(semantic=sem.upper(), source="#" + idName + "-" + sem) for sem in ["input", "output", "interpolation"] ], id=idName + "-sampler")) animElem.append( E.channel(source="#" + idName + "-sampler", target=name + "/matrix")) return animElem
def _create_anim_src_elem(anim_name, src_data, src_suffix, src_type, param_name, param_type): """""" idName = anim_name + "-" + src_suffix src_elem = E.source(id=idName) idName += "-array" count = len(src_data) / 16 if param_type == "float4x4" else len( src_data) if src_type == "float": str_src_data = " ".join( [str(round(val, precision)) for val in src_data]) + " " str_src_data = str_src_data.replace(".0 ", " ") else: str_src_data = " ".join(map(str, src_data)) src_elem.append( E(src_type + "_array", str_src_data, id=idName, count=str(count))) src_elem.append( E.technique_common( E.accessor( E.param(name=param_name, type=param_type), #accessor child source="#" + idName, count=str(count) #accessor attribs ))) if param_type == "float4x4": src_elem.find(tag("technique_common")).find(tag("accessor")).set( "stride", str(16)) return src_elem
def __init__(self, id, img, format=None, xmlnode=None): """Creates a surface. :param str id: A string identifier for the surface within the local scope of the material :param collada.material.CImage img: The image object :param str format: The format of the image :param xmlnode: If loaded from xml, the xml node """ self.id = id """The string identifier for the surface within the local scope of the material""" self.image = img """:class:`collada.material.CImage` object from the image library.""" self.format = format if format is not None else "A8R8G8B8" """Format string.""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the surface.""" else: self.xmlnode = E.newparam( E.surface( E.init_from(self.image.id), E.format(self.format) , type="2D") , sid=self.id)
def save(self): """Saves the geometry node back to :attr:`xmlnode`""" self.xmlnode.set('url', "#%s" % self.geometry.id) for m in self.materials: m.save() matparent = self.xmlnode.find('%s/%s'%( tag('bind_material'), tag('technique_common') ) ) if matparent is None and len(self.materials)==0: return elif matparent is None: matparent = E.technique_common() self.xmlnode.append(E.bind_material(matparent)) elif len(self.materials) == 0 and matparent is not None: bindnode = self.xmlnode.find('%s' % tag('bind_material')) self.xmlnode.remove(bindnode) return for m in self.materials: if m.xmlnode not in matparent: matparent.append(m.xmlnode) xmlnodes = [m.xmlnode for m in self.materials] for n in matparent: if n not in xmlnodes: matparent.remove(n)
def save(self): """Saves the geometry node back to :attr:`xmlnode`""" self.xmlnode.set('url', "#%s" % self.geometry.id) for m in self.materials: m.save() matparent = self.xmlnode.find( '%s/%s' % (tag('bind_material'), tag('technique_common'))) if matparent is None and len(self.materials) == 0: return elif matparent is None: matparent = E.technique_common() self.xmlnode.append(E.bind_material(matparent)) elif len(self.materials) == 0 and matparent is not None: bindnode = self.xmlnode.find('%s' % tag('bind_material')) self.xmlnode.remove(bindnode) return for m in self.materials: if m.xmlnode not in matparent: matparent.append(m.xmlnode) xmlnodes = [m.xmlnode for m in self.materials] for n in matparent: if n not in xmlnodes: matparent.remove(n)
def __init__(self, geometry, materials=None, xmlnode=None): """Creates a geometry node :param collada.geometry.Geometry geometry: A geometry to instantiate in the scene :param list materials: A list containing items of type :class:`collada.scene.MaterialNode`. Each of these represents a material that the geometry should be bound to. :param xmlnode: When loaded, the xmlnode it comes from """ self.geometry = geometry """An object of type :class:`collada.geometry.Geometry` representing the geometry to bind in the scene""" self.materials = [] """A list containing items of type :class:`collada.scene.MaterialNode`. Each of these represents a material that the geometry is bound to.""" if materials is not None: self.materials = materials if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the geometry node.""" else: self.xmlnode = E.instance_geometry(url="#%s" % self.geometry.id) if len(self.materials) > 0: self.xmlnode.append(E.bind_material( E.technique_common( *[mat.xmlnode for mat in self.materials] ) ))
def __init__(self, id, color, xmlnode = None): """Create a new directional light. :param str id: A unique string identifier for the light :param tuple color: Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the light""" self.direction = numpy.array( [0, 0, -1], dtype=numpy.float32 ) #Not documenting this because it doesn't make sense to set the direction # of an unbound light. The direction isn't set until binding in a scene. self.color = color """Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the light.""" else: self.xmlnode = E.light( E.technique_common( E.directional( E.color(' '.join(map(str, self.color))) ) ) , id=self.id, name=self.id)
def _create_anim_src_elem(anim_name, src_data, src_suffix, src_type, param_name, param_type): """""" idName = anim_name + "-" + src_suffix src_elem = E.source(id=idName) idName += "-array" count = len(src_data) / 16 if param_type == "float4x4" else len(src_data) if src_type == "float": str_src_data = " ".join([str(round(val, precision)) for val in src_data]) + " " str_src_data = str_src_data.replace(".0 ", " ") else: str_src_data = " ".join(map(str, src_data)) src_elem.append(E(src_type + "_array", str_src_data, id=idName, count=str(count))) src_elem.append( E.technique_common( E.accessor( E.param(name=param_name, type=param_type), # accessor child source="#" + idName, count=str(count), # accessor attribs ) ) ) if param_type == "float4x4": src_elem.find(tag("technique_common")).find(tag("accessor")).set("stride", str(16)) return src_elem
def getPropNode(prop, value): propnode = E(prop) if type(value) is Map: propnode.append(copy.deepcopy(value.xmlnode)) elif type(value) is float: propnode.append(E.float(str(value))) else: propnode.append(E.color(' '.join(map(str, value) ))) return propnode
def save(self): """Saves the collada document back to :attr:`xmlnode`""" libraries = [(self.geometries, 'library_geometries'), (self.controllers, 'library_controllers'), (self.lights, 'library_lights'), (self.cameras, 'library_cameras'), (self.images, 'library_images'), (self.effects, 'library_effects'), (self.materials, 'library_materials'), (self.nodes, 'library_nodes'), (self.scenes, 'library_visual_scenes')] self.assetInfo.save() assetnode = self.xmlnode.getroot().find(self.tag('asset')) if assetnode is not None: self.xmlnode.getroot().remove(assetnode) self.xmlnode.getroot().insert(0, self.assetInfo.xmlnode) library_loc = 0 for i, node in enumerate(self.xmlnode.getroot()): if node.tag == self.tag('asset'): library_loc = i + 1 for arr, name in libraries: node = self.xmlnode.find(self.tag(name)) if node is None: if len(arr) == 0: continue self.xmlnode.getroot().insert(library_loc, E(name)) node = self.xmlnode.find(self.tag(name)) elif node is not None and len(arr) == 0: self.xmlnode.getroot().remove(node) continue for o in arr: o.save() if o.xmlnode not in node: node.append(o.xmlnode) xmlnodes = [o.xmlnode for o in arr] for n in node: if n not in xmlnodes: node.remove(n) scenenode = self.xmlnode.find(self.tag('scene')) scenenode.clear() if self.scene is not None: sceneid = self.scene.id if sceneid not in self.scenes: raise DaeBrokenRefError('Default scene %s not found' % sceneid) scenenode.append(E.instance_visual_scene(url="#%s" % sceneid)) if self.validator is not None: if not self.validator.validate(self.xmlnode): raise DaeSaveValidationError( "Validation error when saving: " + self.validator. COLLADA_SCHEMA_1_4_1_INSTANCE.error_log.last_error.message)
def getPropNode(prop, value): propnode = E(prop) if prop == 'transparent' and self.opaque_mode == OPAQUE_MODE.RGB_ZERO: propnode.set('opaque', OPAQUE_MODE.RGB_ZERO) if type(value) is Map: propnode.append(copy.deepcopy(value.xmlnode)) elif type(value) is float: propnode.append(E.float(str(value))) else: propnode.append(E.color(' '.join(map(str, value) ))) return propnode
def _add_osg_description(self, node, description): """ """ extra = E.extra( E.technique( E.Descriptions(E.Description(description)), profile="OpenSceneGraph", ), type="Node", ) extra_node = collada.scene.ExtraNode(extra) node.children.append(extra_node)
def _add_osg_description(self, node, description): """ """ extra = E.extra( E.technique( E.Descriptions( E.Description(description) ), profile="OpenSceneGraph", ), type="Node", ) extra_node = collada.scene.ExtraNode(extra) node.children.append(extra_node)
def __init__(self, id, color, constant_att=None, linear_att=None, quad_att=None, zfar=None, xmlnode = None): """Create a new sun light. :param str id: A unique string identifier for the light :param tuple color: Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light :param float constant_att: Constant attenuation factor :param float linear_att: Linear attenuation factor :param float quad_att: Quadratic attenuation factor :param float zfar: Distance to the far clipping plane :param xmlnode: If loaded from xml, the xml node """ self.id = id """The unique string identifier for the light""" self.position = numpy.array( [0, 0, 0], dtype=numpy.float32 ) #Not documenting this because it doesn't make sense to set the position # of an unbound light. The position isn't set until binding in a scene. self.color = color """Either a tuple of size 3 containing the RGB color value of the light or a tuple of size 4 containing the RGBA color value of the light""" self.constant_att = constant_att """Constant attenuation factor.""" self.linear_att = linear_att """Linear attenuation factor.""" self.quad_att = quad_att """Quadratic attenuation factor.""" self.zfar = zfar """Distance to the far clipping plane""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the light.""" else: pnode = E.point( E.color(' '.join(map(str, self.color ) )) ) if self.constant_att is not None: pnode.append(E.constant_attenuation(str(self.constant_att))) if self.linear_att is not None: pnode.append(E.linear_attenuation(str(self.linear_att))) if self.quad_att is not None: pnode.append(E.quadratic_attenuation(str(self.quad_att))) if self.zfar is not None: pnode.append(E.zfar(str(self.zvar))) self.xmlnode = E.light( E.technique_common(pnode) , id=self.id, name=self.id)
def __init__(self, id, data, components, xmlnode=None): """Create a name source instance. :param str id: A unique string identifier for the source :param numpy.array data: Numpy array (unshaped) with the source values :param tuple components: Tuple of strings describing the semantic of the data, e.g. ``('JOINT')`` would cause :attr:`data` to be reshaped as ``(-1, 1)`` :param xmlnode: When loaded, the xmlnode it comes from. """ self.id = id """The unique string identifier for the source""" self.data = data """Numpy array with the source values. This will be shaped as ``(-1,N)`` where ``N = len(self.components)``""" self.data.shape = (-1, len(components)) self.components = components """Tuple of strings describing the semantic of the data, e.g. ``('JOINT')``""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the source.""" else: self.data.shape = (-1, ) txtdata = ' '.join(map(str, self.data.tolist())) rawlen = len(self.data) self.data.shape = (-1, len(self.components)) acclen = len(self.data) stridelen = len(self.components) sourcename = "%s-array" % self.id self.xmlnode = E.source(E.Name_array(txtdata, count=str(rawlen), id=sourcename), E.technique_common( E.accessor( *[ E.param(type='Name', name=c) for c in self.components ], **{ 'count': str(acclen), 'stride': str(stridelen), 'source': sourcename })), id=self.id)
def __init__(self, x, y, z, xmlnode=None): """Creates a translation transformation :param float x: x coordinate :param float y: y coordinate :param float z: z coordinate :param xmlnode: When loaded, the xmlnode it comes from """ self.x = x """x coordinate""" self.y = y """y coordinate""" self.z = z """z coordinate""" self.matrix = numpy.identity(4, dtype=numpy.float32) """The resulting transformation matrix. This will be a numpy.array of size 4x4.""" self.matrix[:3, 3] = [x, y, z] self.xmlnode = xmlnode """ElementTree representation of the transform.""" if xmlnode is None: self.xmlnode = E.translate(' '.join([str(x), str(y), str(z)]))
def __init__(self, id, nodes, xmlnode=None, collada=None): """Create a scene :param str id: A unique string identifier for the scene :param list nodes: A list of type :class:`collada.scene.Node` representing the nodes in the scene :param xmlnode: When loaded, the xmlnode it comes from :param collada: The collada instance this is part of """ self.id = id """The unique string identifier for the scene""" self.nodes = nodes """A list of type :class:`collada.scene.Node` representing the nodes in the scene""" self.collada = collada """The collada instance this is part of""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the scene node.""" else: self.xmlnode = E.visual_scene(id=self.id) for node in nodes: self.xmlnode.append( node.xmlnode )
def __init__(self, x, y, z, xmlnode=None): """Creates a translation transformation :param float x: x coordinate :param float y: y coordinate :param float z: z coordinate :param xmlnode: When loaded, the xmlnode it comes from """ self.x = x """x coordinate""" self.y = y """y coordinate""" self.z = z """z coordinate""" self.matrix = numpy.identity(4, dtype=numpy.float32) """The resulting transformation matrix. This will be a numpy.array of size 4x4.""" self.matrix[:3,3] = [ x, y, z ] self.xmlnode = xmlnode """ElementTree representation of the transform.""" if xmlnode is None: self.xmlnode = E.translate(' '.join([str(x),str(y),str(z)]))
def __init__(self, id, nodes, xmlnode=None, collada=None): """Create a scene :param str id: A unique string identifier for the scene :param list nodes: A list of type :class:`collada.scene.Node` representing the nodes in the scene :param xmlnode: When loaded, the xmlnode it comes from :param collada: The collada instance this is part of """ self.id = id """The unique string identifier for the scene""" self.nodes = nodes """A list of type :class:`collada.scene.Node` representing the nodes in the scene""" self.collada = collada """The collada instance this is part of""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the scene node.""" else: self.xmlnode = E.visual_scene(id=self.id) for node in nodes: self.xmlnode.append(node.xmlnode)
def __init__(self, x, y, z, angle, xmlnode=None): """Creates a rotation transformation :param float x: x coordinate :param float y: y coordinate :param float z: z coordinate :param float angle: angle of rotation, in radians :param xmlnode: When loaded, the xmlnode it comes from """ self.x = x """x coordinate""" self.y = y """y coordinate""" self.z = z """z coordinate""" self.angle = angle """angle of rotation, in radians""" self.matrix = makeRotationMatrix(x, y, z, angle*numpy.pi/180.0) """The resulting transformation matrix. This will be a numpy.array of size 4x4.""" self.xmlnode = xmlnode """ElementTree representation of the transform.""" if xmlnode is None: self.xmlnode = E.rotate(' '.join([str(x),str(y),str(z),str(angle)]))
def __init__(self, x, y, z, angle, xmlnode=None): """Creates a rotation transformation :param float x: x coordinate :param float y: y coordinate :param float z: z coordinate :param float angle: angle of rotation, in degrees :param xmlnode: When loaded, the xmlnode it comes from """ self.x = x """x coordinate""" self.y = y """y coordinate""" self.z = z """z coordinate""" self.angle = angle """angle of rotation, in degrees""" self.matrix = makeRotationMatrix(x, y, z, angle * numpy.pi / 180.0) """The resulting transformation matrix. This will be a numpy.array of size 4x4.""" self.xmlnode = xmlnode """ElementTree representation of the transform.""" if xmlnode is None: self.xmlnode = E.rotate(' '.join( [str(x), str(y), str(z), str(angle)]))
def _recreateXmlNode(self): perspective_node = E.perspective() if self.xfov is not None: perspective_node.append(E.xfov(str(self.xfov))) if self.yfov is not None: perspective_node.append(E.yfov(str(self.yfov))) if self.aspect_ratio is not None: perspective_node.append(E.aspect_ratio(str(self.aspect_ratio))) perspective_node.append(E.znear(str(self.znear))) perspective_node.append(E.zfar(str(self.zfar))) self.xmlnode = E.camera(E.optics(E.technique_common(perspective_node)), id=self.id, name=self.id)
def __init__(self, filename, scale=1.0, options=None): """ """ DrawerDriver.__init__(self, scale) self.filename = filename self.dae = collada.Collada() self.shapes_dae = collada.Collada(os.path.join(os.path.dirname(os.path.abspath(__file__)), "simple_shapes.dae")) # create library_physics_models self.physics_model = E.physics_model(id="world") self.dae.xmlnode.getroot().insert(1, E.library_physics_models(self.physics_model)) # insert just after asset self.ground_node = None self.scene = None self._materials = {} self._names = []
def __init__(self, sources, material, polygons, xmlnode=None): """A Polygons should not be created manually. Instead, call the :meth:`collada.geometry.Geometry.createPolygons` method after creating a geometry instance. """ max_offset = max([ max([input[0] for input in input_type_array]) for input_type_array in sources.values() if len(input_type_array) > 0 ]) vcounts = numpy.zeros(len(polygons), dtype=numpy.int32) for i, poly in enumerate(polygons): vcounts[i] = len(poly) / (max_offset + 1) if len(polygons) > 0: indices = numpy.concatenate(polygons) else: indices = numpy.array([], dtype=numpy.int32) super(Polygons, self).__init__(sources, material, indices, vcounts, xmlnode) if xmlnode is not None: self.xmlnode = xmlnode else: acclen = len(polygons) self.xmlnode = E.polygons(count=str(acclen), material=self.material) all_inputs = [] for semantic_list in self.sources.values(): all_inputs.extend(semantic_list) for offset, semantic, sourceid, set, src in all_inputs: inpnode = E.input(offset=str(offset), semantic=semantic, source=sourceid) if set is not None: inpnode.set('set', str(set)) self.xmlnode.append(inpnode) for poly in polygons: self.xmlnode.append( E.p(' '.join(map(str, poly.flatten().tolist()))))
def _correctValInNode(outernode, tagname, value): innernode = outernode.find( tag(tagname) ) if value is None and innernode is not None: outernode.remove(innernode) elif innernode is not None: innernode.text = str(value) elif value is not None: outernode.append(E(tagname, str(value)))
def _recreateXmlNode(self): orthographic_node = E.orthographic() if self.xmag is not None: orthographic_node.append(E.xmag(str(self.xmag))) if self.ymag is not None: orthographic_node.append(E.ymag(str(self.ymag))) if self.aspect_ratio is not None: orthographic_node.append(E.aspect_ratio(str(self.aspect_ratio))) orthographic_node.append(E.znear(str(self.znear))) orthographic_node.append(E.zfar(str(self.zfar))) self.xmlnode = E.camera(E.optics( E.technique_common(orthographic_node)), id=self.id, name=self.id)
def node(self, b_matrix=None): node = Node(id=None, xmlnode=E.node()) # construct my own xmlnode to avoid setting an id or name # (should be optional according to Collada spec) if b_matrix != None: node.transforms.append(self.matrix(b_matrix)) #end if node.save() return node
def save(self): """Saves the collada document back to :attr:`xmlnode`""" libraries = [(self.geometries, 'library_geometries'), (self.controllers, 'library_controllers'), (self.lights, 'library_lights'), (self.cameras, 'library_cameras'), (self.images, 'library_images'), (self.effects, 'library_effects'), (self.materials, 'library_materials'), (self.nodes, 'library_nodes'), (self.scenes, 'library_visual_scenes')] self.assetInfo.save() assetnode = self.xmlnode.getroot().find(tag('asset')) if assetnode is not None: self.xmlnode.getroot().replace(assetnode, self.assetInfo.xmlnode) else: self.xmlnode.getroot().insert(0, self.assetInfo.xmlnode) library_loc = 0 for i, node in enumerate(self.xmlnode.getroot()): if node.tag == tag('asset'): library_loc = i+1 for arr, name in libraries: node = self.xmlnode.find( tag(name) ) if node is None: if len(arr) == 0: continue self.xmlnode.getroot().insert(library_loc, E(name)) node = self.xmlnode.find( tag(name) ) elif node is not None and len(arr) == 0: self.xmlnode.getroot().remove(node) continue for o in arr: o.save() if o.xmlnode not in node: node.append(o.xmlnode) xmlnodes = [o.xmlnode for o in arr] for n in node: if n not in xmlnodes: node.remove(n) scenenode = self.xmlnode.find(tag('scene')) scenenode.clear() if self.scene is not None: sceneid = self.scene.id if sceneid not in self.scenes: raise DaeBrokenRefError('Default scene %s not found' % sceneid) scenenode.append(E.instance_visual_scene(url="#%s" % sceneid)) if self.validator is not None: if not self.validator.validate(self.xmlnode): raise DaeSaveValidationError("Validation error when saving: " + schema.COLLADA_SCHEMA_1_4_1_INSTANCE.error_log.last_error.message)
def _recreateXmlNode(self): perspective_node = E.perspective() if self.xfov is not None: perspective_node.append(E.xfov(str(self.xfov))) if self.yfov is not None: perspective_node.append(E.yfov(str(self.yfov))) if self.aspect_ratio is not None: perspective_node.append(E.aspect_ratio(str(self.aspect_ratio))) perspective_node.append(E.znear(str(self.znear))) perspective_node.append(E.zfar(str(self.zfar))) self.xmlnode = E.camera( E.optics( E.technique_common(perspective_node) ) , id=self.id, name=self.id)
def _recreateXmlNode(self): orthographic_node = E.orthographic() if self.xmag is not None: orthographic_node.append(E.xmag(str(self.xmag))) if self.ymag is not None: orthographic_node.append(E.ymag(str(self.ymag))) if self.aspect_ratio is not None: orthographic_node.append(E.aspect_ratio(str(self.aspect_ratio))) orthographic_node.append(E.znear(str(self.znear))) orthographic_node.append(E.zfar(str(self.zfar))) self.xmlnode = E.camera( E.optics( E.technique_common(orthographic_node) ) , id=self.id, name=self.id)
def __init__(self, id, data, components, xmlnode=None): """Create a name source instance. :param str id: A unique string identifier for the source :param numpy.array data: Numpy array (unshaped) with the source values :param tuple components: Tuple of strings describing the semantic of the data, e.g. ``('JOINT')`` would cause :attr:`data` to be reshaped as ``(-1, 1)`` :param xmlnode: When loaded, the xmlnode it comes from. """ self.id = id """The unique string identifier for the source""" self.data = data """Numpy array with the source values. This will be shaped as ``(-1,N)`` where ``N = len(self.components)``""" self.data.shape = (-1, len(components) ) self.components = components """Tuple of strings describing the semantic of the data, e.g. ``('JOINT')``""" if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the source.""" else: self.data.shape = (-1,) txtdata = ' '.join(map(str, self.data.tolist() )) rawlen = len( self.data ) self.data.shape = (-1, len(self.components) ) acclen = len( self.data ) stridelen = len(self.components) sourcename = "%s-array"%self.id self.xmlnode = E.source( E.Name_array(txtdata, count=str(rawlen), id=sourcename), E.technique_common( E.accessor( *[E.param(type='Name', name=c) for c in self.components] , **{'count':str(acclen), 'stride':str(stridelen), 'source':sourcename}) ) , id=self.id )
def blender_technique(self, as_extra, obj): # experimental: add Blender-specific attributes via a custom <technique>. if self._add_blender_extensions: if isinstance(obj, DaeObject): obj = obj.xmlnode #end if blendstuff = E.technique(profile="BLENDER028") if as_extra: parent = E.extra() else: parent = obj #end if parent.append(blendstuff) if as_extra: obj.append(parent) #end if else: blendstuff = None #end if return blendstuff
def _recreateXmlNode(self): self.index.shape = (-1) acclen = len(self.index) txtindices = ' '.join(map(str, self.index.tolist())) self.index.shape = (-1, 3, self.nindices) self.xmlnode = E.triangles(count=str(self.ntriangles)) if self.material is not None: self.xmlnode.set('material', self.material) all_inputs = [] for semantic_list in self.sources.values(): all_inputs.extend(semantic_list) for offset, semantic, sourceid, set, src in all_inputs: inpnode = E.input(offset=str(offset), semantic=semantic, source=sourceid) if set is not None: inpnode.set('set', str(set)) self.xmlnode.append(inpnode) self.xmlnode.append(E.p(txtindices))
def _recreateXmlNode(self): self.index.shape = -1 acclen = len(self.index) txtindices = " ".join(map(str, self.index.tolist())) self.index.shape = (-1, 3, self.nindices) self.xmlnode = E.triangles(count=str(self.ntriangles)) if self.material is not None: self.xmlnode.set("material", self.material) all_inputs = [] for semantic_list in self.sources.values(): all_inputs.extend(semantic_list) for offset, semantic, sourceid, set, src in all_inputs: inpnode = E.input(offset=str(offset), semantic=semantic, source=sourceid) if set is not None: inpnode.set("set", str(set)) self.xmlnode.append(inpnode) self.xmlnode.append(E.p(txtindices))
def _recreateXmlNode(self): self.xmlnode = E.asset() for contributor in self.contributors: self.xmlnode.append(contributor.xmlnode) self.xmlnode.append(E.created(self.created.isoformat())) if self.keywords is not None: self.xmlnode.append(E.keywords(self.keywords)) self.xmlnode.append(E.modified(self.modified.isoformat())) if self.revision is not None: self.xmlnode.append(E.revision(self.revision)) if self.subject is not None: self.xmlnode.append(E.subject(self.subject)) if self.title is not None: self.xmlnode.append(E.title(self.title)) if self.unitmeter is not None and self.unitname is not None: self.xmlnode.append(E.unit(name=self.unitname, meter=str(self.unitmeter))) self.xmlnode.append(E.up_axis(self.upaxis))
def save(self): """Saves the surface data back to :attr:`xmlnode`""" surfacenode = self.xmlnode.find( tag('surface') ) initnode = surfacenode.find( tag('init_from') ) if self.format: formatnode = surfacenode.find( tag('format') ) if formatnode is None: surfacenode.append(E.format(self.format)) else: formatnode.text = self.format initnode.text = self.image.id self.xmlnode.set('sid', self.id)
def __init__(self, xmlnode): """Create an extra node which stores arbitrary xml :param xmlnode: Should be an ElementTree instance of tag type <extra> """ if xmlnode != None: self.xmlnode = xmlnode """ElementTree representation of the extra node.""" else: self.xmlnode = E.extra()
def __init__(self, sources, material, polygons, xmlnode=None): """A Polygons should not be created manually. Instead, call the :meth:`collada.geometry.Geometry.createPolygons` method after creating a geometry instance. """ max_offset = max([ max([input[0] for input in input_type_array]) for input_type_array in sources.values() if len(input_type_array) > 0]) vcounts = numpy.zeros(len(polygons), dtype=numpy.int32) for i, poly in enumerate(polygons): vcounts[i] = len(poly) / (max_offset + 1) if len(polygons) > 0: indices = numpy.concatenate(polygons) else: indices = numpy.array([], dtype=numpy.int32) super(Polygons, self).__init__(sources, material, indices, vcounts, xmlnode) if xmlnode is not None: self.xmlnode = xmlnode else: acclen = len(polygons) self.xmlnode = E.polygons(count=str(acclen), material=self.material) all_inputs = [] for semantic_list in self.sources.values(): all_inputs.extend(semantic_list) for offset, semantic, sourceid, set, src in all_inputs: inpnode = E.input(offset=str(offset), semantic=semantic, source=sourceid) if set is not None: inpnode.set('set', str(set)) self.xmlnode.append(inpnode) for poly in polygons: self.xmlnode.append(E.p(' '.join(map(str, poly.flatten().tolist()))))
def _create_anim_elem(name, timeline, value): """""" idName = name + "-animation" animElem = E.animation(id=idName) animElem.append(_create_anim_src_elem(idName, timeline, "input", "float", "TIME", "float")) animElem.append( _create_anim_src_elem(idName, ["STEP"] * len(timeline), "interpolation", "Name", "INTERPOLATION", "name") ) animElem.append(_create_anim_src_elem(idName, value.flatten(), "output", "float", "TRANSFORM", "float4x4")) animElem.append( E.sampler( *[ E.input(semantic=sem.upper(), source="#" + idName + "-" + sem) for sem in ["input", "output", "interpolation"] ], id=idName + "-sampler" ) ) animElem.append(E.channel(source="#" + idName + "-sampler", target=name + "/matrix")) return animElem
def create_inertia(self, inertia, color, name=""): H_body_com = principalframe(inertia) Mcom = transport(inertia, H_body_com) mass = Mcom[5, 5] m_o_inertia = Mcom[[0, 1, 2], [0, 1, 2]] position = H_body_com[0:3, 3] yaw, pitch, roll = np.degrees(rotzyx_angles(H_body_com)) # in degrees for collada specification self.physics_model.append( E.rigid_body( E.technique_common( E.dynamic("true"), E.mass(str(mass)), E.mass_frame( E.translate(" ".join(map(str, position)), sid="location"), E.rotate(" ".join(map(str, [0, 0, 1, yaw])), sid="rotationZ"), E.rotate(" ".join(map(str, [0, 1, 0, pitch])), sid="rotationY"), E.rotate(" ".join(map(str, [1, 0, 0, roll])), sid="rotationX"), ), E.inertia(" ".join(map(str, m_o_inertia))), ), sid=name, ) )
def save(self): """Saves the material node back to :attr:`xmlnode`""" self.xmlnode.set('symbol', self.symbol) self.xmlnode.set('target', "#%s"%self.target.id) inputs_in = [] for i in self.xmlnode.findall( tag('bind_vertex_input') ): input_tuple = ( i.get('semantic'), i.get('input_semantic'), i.get('input_set') ) if input_tuple not in self.inputs: self.xmlnode.remove(i) else: inputs_in.append(input_tuple) for i in self.inputs: if i not in inputs_in: self.xmlnode.append(E.bind_vertex_input(semantic=i[0], input_semantic=i[1], input_set=i[2]))