Exemple #1
0
    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
Exemple #2
0
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 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)
Exemple #4
0
 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
Exemple #5
0
    def save(self):
        """Saves the effect back to :attr:`xmlnode`"""
        self.xmlnode.set('id', self.id)
        self.xmlnode.set('name', self.id)
        profilenode = self.xmlnode.find( tag('profile_COMMON') )
        tecnode = profilenode.find( tag('technique') )
        tecnode.set('sid', 'common')

        self._fixColorValues()

        for param in self.params:
            param.save()
            if param.xmlnode not in profilenode.getchildren():
                profilenode.insert(list(profilenode).index(tecnode),
                        param.xmlnode)

        deletenodes = []
        for oldparam in profilenode.findall( tag('newparam') ):
            if oldparam not in [param.xmlnode for param in self.params]:
                deletenodes.append(oldparam)
        for d in deletenodes:
            profilenode.remove(d)

        for shader in self.shaders:
            shadnode = tecnode.find(tag(shader))
            if shadnode is not None and shader != self.shadingtype:
                tecnode.remove(shadnode)

        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

        shadnode = tecnode.find(tag(self.shadingtype))
        if shadnode is None:
            shadnode = E(self.shadingtype)
            for prop in self.supported:
                value = getattr(self, prop)
                if value is None: continue
                shadnode.append(getPropNode(prop, value))
            tecnode.append(shadnode)
        else:
            for prop in self.supported:
                value = getattr(self, prop)
                propnode = shadnode.find(tag(prop))
                if propnode is not None:
                    shadnode.remove(propnode)
                if value is not None:
                    shadnode.append(getPropNode(prop, value))

        double_sided_node = profilenode.find('.//%s//%s' % (tag('extra'), tag('double_sided')))
        if double_sided_node is None or double_sided_node.text is None:
            extranode = profilenode.find(tag('extra'))
            if extranode is None:
                extranode = E.extra()
                profilenode.append(extranode)

            teqnodes = extranode.findall(tag('technique'))
            goognode = None
            for teqnode in teqnodes:
                if teqnode.get('profile') == 'GOOGLEEARTH':
                    goognode = teqnode
                    break
            if goognode is None:
                goognode = E.technique(profile='GOOGLEEARTH')
                extranode.append(goognode)
            double_sided_node = goognode.find(tag('double_sided'))
            if double_sided_node is None:
                double_sided_node = E.double_sided()
                goognode.append(double_sided_node)

        double_sided_node.text = "1" if self.double_sided else "0"
Exemple #6
0
    def __init__(self, id, params, shadingtype, bumpmap = None, double_sided = False,
                       emission = (0.0, 0.0, 0.0, 1.0),
                       ambient = (0.0, 0.0, 0.0, 1.0),
                       diffuse = (0.0, 0.0, 0.0, 1.0),
                       specular = (0.0, 0.0, 0.0, 1.0),
                       shininess = 0.0,
                       reflective = (0.0, 0.0, 0.0, 1.0),
                       reflectivity = 0.0,
                       transparent = (0.0, 0.0, 0.0, 1.0),
                       transparency = None,
                       index_of_refraction = None,
                       opaque_mode = None,
                       xmlnode = None):
        """Create an effect instance out of properties.

        :param str id:
          A string identifier for the effect
        :param list params:
          A list containing elements of type :class:`collada.material.Sampler2D`
          and :class:`collada.material.Surface`
        :param str shadingtype:
          The type of shader to be used for this effect. Right now, we
          only supper the shaders listed in :attr:`shaders`
        :param `collada.material.Map` bumpmap:
          The bump map for this effect, or None if there isn't one
        :param bool double_sided:
          Whether or not the material should be rendered double sided
        :param emission:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param ambient:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param diffuse:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param specular:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param shininess:
          Either a single float or an instance of :class:`collada.material.Map`
        :param reflective:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param reflectivity:
          Either a single float or an instance of :class:`collada.material.Map`
        :param tuple transparent:
          Either an RGBA-format tuple of four floats or an instance
          of :class:`collada.material.Map`
        :param transparency:
          Either a single float or an instance of :class:`collada.material.Map`
        :param float index_of_refraction:
          A single float indicating the index of refraction for perfectly
          refracted light
        :param `collada.material.OPAQUE_MODE` opaque_mode:
          The opaque mode for the effect. If not specified, defaults to A_ONE.
        :param xmlnode:
          If loaded from xml, the xml node

        """
        self.id = id
        """The string identifier for the effect"""
        self.params = params
        """A list containing elements of type :class:`collada.material.Sampler2D`
          and :class:`collada.material.Surface`"""
        self.shadingtype = shadingtype
        """String with the type of the shading."""
        self.bumpmap = bumpmap
        """Either the bump map of the effect of type :class:`collada.material.Map`
        or None if there is none."""
        self.double_sided = double_sided
        """A boolean indicating whether or not the material should be rendered double sided"""
        self.emission = emission
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.ambient = ambient
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.diffuse = diffuse
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.specular = specular
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.shininess = shininess
        """Either a single float or an instance of :class:`collada.material.Map`"""
        self.reflective = reflective
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.reflectivity = reflectivity
        """Either a single float or an instance of :class:`collada.material.Map`"""
        self.transparent = transparent
        """Either an RGB-format tuple of three floats or an instance
          of :class:`collada.material.Map`"""
        self.transparency = transparency
        """Either a single float or an instance of :class:`collada.material.Map`"""
        self.index_of_refraction = index_of_refraction
        """A single float indicating the index of refraction for perfectly
          refracted light"""
        self.opaque_mode = OPAQUE_MODE.A_ONE if opaque_mode is None else opaque_mode
        """The opaque mode for the effect. An instance of :class:`collada.material.OPAQUE_MODE`."""

        if self.transparency is None:
            if self.opaque_mode == OPAQUE_MODE.A_ONE:
                self.transparency = 1.0
            else:
                self.transparency = 0.0

        self._fixColorValues()

        if xmlnode is not None:
            self.xmlnode = xmlnode
            """ElementTree representation of the effect"""
        else:
            shadnode = E(self.shadingtype)

            for prop in self.supported:
                value = getattr(self, prop)
                if value is None: continue
                propnode = E(prop)
                if prop == 'transparent' and self.opaque_mode == OPAQUE_MODE.RGB_ZERO:
                    propnode.set('opaque', OPAQUE_MODE.RGB_ZERO)
                shadnode.append( propnode )
                if type(value) is Map:
                    propnode.append(value.xmlnode)
                elif type(value) is float:
                    propnode.append(E.float(str(value)))
                else:
                    propnode.append(E.color(' '.join(map(str, value) )))

            effect_nodes = [param.xmlnode for param in self.params]
            effect_nodes.append(E.technique(shadnode, sid='common'))
            self.xmlnode = E.effect(
                E.profile_COMMON(*effect_nodes)
            , id=self.id, name=self.id)
Exemple #7
0
def write_collada_animation_from_transforms(collada_animation, collada_scene,
                                            timeline, transforms, precision):
    """
    """
    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 _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

    dae = collada.Collada(collada_scene)
    # save animation node: this is not supported by pycollada, so the xml node is written using pycollada.common.E
    anim_lib = dae.xmlnode.find(tag('library_animations'))
    if anim_lib is None:
        children = list(dae.xmlnode.getroot())
        dae.xmlnode.getroot().insert(
            children.index(dae.xmlnode.find(tag("scene"))),
            E('library_animations'))

        anim_lib = dae.xmlnode.find(tag('library_animations'))

    for name, val in transforms.items():
        anim_lib.append(_create_anim_elem(name, timeline, val))

    _write_pycollada_in_file(dae, collada_animation)