Пример #1
0
    def load( collada, localscope, node ):
        id = node.get("id") or ""
        name = node.get("name") or ""
        meshnode = node.find(tag('mesh'))
        if meshnode is None: raise DaeUnsupportedError('Unknown geometry node')
        sourcebyid = {}
        sources = []
        sourcenodes = node.findall('%s/%s'%(tag('mesh'), tag('source')))
        for sourcenode in sourcenodes:
            ch = source.Source.load(collada, {}, sourcenode)
            sources.append(ch)
            sourcebyid[ch.id] = ch

        verticesnode = meshnode.find(tag('vertices'))
        if verticesnode is None:
            vertexsource = None
        else:
            inputnodes = {}
            for inputnode in verticesnode.findall(tag('input')):
                semantic = inputnode.get('semantic')
                inputsource = inputnode.get('source')
                if not semantic or not inputsource or not inputsource.startswith('#'):
                    raise DaeIncompleteError('Bad input definition inside vertices')
                inputnodes[semantic] = sourcebyid.get(inputsource[1:])
            if (not verticesnode.get('id') or len(inputnodes)==0 or
                not 'POSITION' in inputnodes):
                raise DaeIncompleteError('Bad vertices definition in mesh')
            sourcebyid[verticesnode.get('id')] = inputnodes
            vertexsource = verticesnode.get('id')

        double_sided_node = node.find('.//%s//%s' % (tag('extra'), tag('double_sided')))
        double_sided = False
        if double_sided_node is not None and double_sided_node.text is not None:
            try:
                val = int(double_sided_node.text)
                if val == 1:
                    double_sided = True
            except ValueError: pass

        _primitives = []
        for subnode in meshnode:
            if subnode.tag == tag('polylist'):
                _primitives.append( polylist.Polylist.load( collada, sourcebyid, subnode ) )
            elif subnode.tag == tag('triangles'):
                _primitives.append( triangleset.TriangleSet.load( collada, sourcebyid, subnode ) )
            elif subnode.tag == tag('lines'):
                _primitives.append( lineset.LineSet.load( collada, sourcebyid, subnode ) )
            elif subnode.tag == tag('polygons'):
                _primitives.append( polygons.Polygons.load( collada, sourcebyid, subnode ) )
            elif subnode.tag != tag('source') and subnode.tag != tag('vertices') and subnode.tag != tag('extra'):
                raise DaeUnsupportedError('Unknown geometry tag %s' % subnode.tag)
        geom = Geometry(collada, id, name, sourcebyid, _primitives, xmlnode=node, double_sided=double_sided )
        return geom
Пример #2
0
 def _loadShadingParam( collada, localscope, node ):
     """Load from the node a definition for a material property."""
     children = node.getchildren()
     if not children: raise DaeIncompleteError('Incorrect effect shading parameter '+node.tag)
     vnode = children[0]
     if vnode.tag == tag('color'):
         try:
             value = tuple([ float(v) for v in vnode.text.split() ])
         except ValueError as ex:
             raise DaeMalformedError('Corrupted color definition in effect '+id)
         except IndexError as ex:
             raise DaeMalformedError('Corrupted color definition in effect '+id)
     elif vnode.tag == tag('float'):
         try: value = float(vnode.text)
         except ValueError as ex:
             raise DaeMalformedError('Corrupted float definition in effect '+id)
     elif vnode.tag == tag('texture'):
         value = Map.load(collada, localscope, vnode)
     elif vnode.tag == tag('param'):
         refid = vnode.get('ref')
         if refid is not None and refid in localscope:
             value = localscope[refid]
         else:
             return None
     else:
         raise DaeUnsupportedError('Unknown shading param definition ' + \
                 vnode.tag)
     return value
Пример #3
0
def loadNode(collada, node, localscope):
    """Generic scene node loading from an xml `node` and a `collada` object.

    Knowing the supported nodes, create the appropriate class for the given node
    and return it.

    """
    if node.tag == collada.tag('node'):
        return Node.load(collada, node, localscope)
    elif node.tag == collada.tag('translate'):
        return TranslateTransform.load(collada, node)
    elif node.tag == collada.tag('rotate'):
        return RotateTransform.load(collada, node)
    elif node.tag == collada.tag('scale'):
        return ScaleTransform.load(collada, node)
    elif node.tag == collada.tag('matrix'):
        return MatrixTransform.load(collada, node)
    elif node.tag == collada.tag('lookat'):
        return LookAtTransform.load(collada, node)
    elif node.tag == collada.tag('instance_geometry'):
        return GeometryNode.load(collada, node)
    elif node.tag == collada.tag('instance_camera'):
        return CameraNode.load(collada, node)
    elif node.tag == collada.tag('instance_light'):
        return LightNode.load(collada, node)
    elif node.tag == collada.tag('instance_controller'):
        return ControllerNode.load(collada, node)
    elif node.tag == collada.tag('instance_node'):
        return NodeNode.load(collada, node, localscope)
    elif node.tag == collada.tag('extra'):
        return ExtraNode.load(collada, node)
    elif node.tag == collada.tag('asset'):
        return None
    else:
        raise DaeUnsupportedError('Unknown scene node %s' % str(node.tag))
Пример #4
0
    def addInput(self, offset, semantic, src, set=None):
        """Add an input source to this input list.

        :param int offset:
          Offset for this source within the geometry's indices
        :param str semantic:
          The semantic for the input source. Currently supported options are:
            * VERTEX
            * NORMAL
            * TEXCOORD
            * TEXBINORMAL
            * TEXTANGENT
            * COLOR
            * TANGENT
            * BINORMAL
        :param str src:
          A string identifier of the form `#srcid` where `srcid` is a source
          within the geometry's :attr:`~collada.geometry.Geometry.sourceById` array.
        :param str set:
          Indicates a set number for the source. This is used, for example,
          when there are multiple texture coordinate sets.

        """
        if semantic not in self.semantics:
            raise DaeUnsupportedError("Unsupported semantic %s" % semantic)
        self.inputs[semantic].append(self.Input(offset, semantic, src, set))
Пример #5
0
 def load(collada, localscope, node):
     tecnode = node.find(
         '%s/%s' % (collada.tag('optics'), collada.tag('technique_common')))
     if tecnode is None or len(tecnode) == 0:
         raise DaeIncompleteError('Missing common technique in camera')
     camnode = tecnode[0]
     if camnode.tag == collada.tag('perspective'):
         return PerspectiveCamera.load(collada, localscope, node)
     elif camnode.tag == collada.tag('orthographic'):
         return OrthographicCamera.load(collada, localscope, node)
     else:
         raise DaeUnsupportedError('Unrecognized camera type: %s' %
                                   camnode.tag)
Пример #6
0
 def load(collada, localscope, node):
     tecnode = node.find(tag('technique_common'))
     if tecnode is None or len(tecnode) == 0:
         raise DaeIncompleteError('Missing common technique in light')
     lightnode = tecnode[0]
     if lightnode.tag == tag('directional'):
         return DirectionalLight.load(collada, localscope, node)
     elif lightnode.tag == tag('point'):
         return PointLight.load(collada, localscope, node)
     elif lightnode.tag == tag('ambient'):
         return AmbientLight.load(collada, localscope, node)
     elif lightnode.tag == tag('spot'):
         return SpotLight.load(collada, localscope, node)
     else:
         raise DaeUnsupportedError('Unrecognized light type: %s' %
                                   lightnode.tag)
Пример #7
0
    def load( collada, localscope, node ):
        controller = node.find(tag('skin'))
        if controller is None:
            controller = node.find(tag('morph'))
        if controller is None: raise DaeUnsupportedError('Unknown controller node')

        sourcebyid = {}
        sources = []
        sourcenodes = node.findall('%s/%s'%(controller.tag, tag('source')))
        for sourcenode in sourcenodes:
            ch = source.Source.load(collada, {}, sourcenode)
            sources.append(ch)
            sourcebyid[ch.id] = ch

        if controller.tag == tag('skin'):
            return Skin.load(collada, sourcebyid, controller, node)
        else:
            return Morph.load(collada, sourcebyid, controller, node)
Пример #8
0
    def load(collada, localscope, node):
        localscope = {} # we have our own scope, shadow it
        params = []
        id = node.get('id')
        profilenode = node.find( tag('profile_COMMON') )
        if profilenode is None:
            raise DaeUnsupportedError('Found effect with profile other than profile_COMMON')

        #<image> can be local to a material instead of global in <library_images>
        for imgnode in profilenode.findall( tag('image') ):
            local_image = CImage.load(collada, localscope, imgnode)
            localscope[local_image.id] = local_image

            global_image_id = local_image.id
            uniquenum = 2
            while global_image_id in collada.images:
                global_image_id = local_image.id + "-" + uniquenum
                uniquenum += 1
            collada.images.append(local_image)

        Effect.getEffectParameters(collada, profilenode, localscope, params)
        
        tecnode = profilenode.find( tag('technique') )
        
        Effect.getEffectParameters(collada, tecnode, localscope, params)
        
        shadnode = None
        for shad in Effect.shaders:
            shadnode = tecnode.find(tag(shad))
            shadingtype = shad
            if not shadnode is None:
                break
        if shadnode is None: raise DaeIncompleteError('No material properties found in effect')
        props = {}
        for key in Effect.supported:
            pnode = shadnode.find( tag(key) )
            if pnode is None: props[key] = None
            else:
                try: props[key] = Effect._loadShadingParam(collada, localscope, pnode)
                except DaeMissingSampler2D as ex:
                    if ex.samplerid in collada.images:
                        #Whoever exported this collada file didn't include the proper references so we will create them
                        surf = Surface(ex.samplerid + '-surface', collada.images[ex.samplerid], 'A8R8G8B8')
                        sampler = Sampler2D(ex.samplerid, surf, None, None);
                        params.append(surf)
                        params.append(sampler)
                        localscope[surf.id] = surf
                        localscope[sampler.id] = sampler
                        try:
                            props[key] = Effect._loadShadingParam(
                                    collada, localscope, pnode)
                        except DaeUnsupportedError as ex:
                            props[key] = None
                            collada.handleError(ex)
                except DaeUnsupportedError as ex:
                    props[key] = None
                    collada.handleError(ex) # Give the chance to ignore error and load the rest

                if key == 'transparent' and key in props and props[key] is not None:
                    opaque_mode = pnode.get('opaque')
                    if opaque_mode is not None and opaque_mode == OPAQUE_MODE.RGB_ZERO:
                        props['opaque_mode'] = OPAQUE_MODE.RGB_ZERO
        props['xmlnode'] = node

        bumpnode = node.find('.//%s//%s' % (tag('extra'), tag('texture')))
        if bumpnode is not None:
            bumpmap =  Map.load(collada, localscope, bumpnode)
        else:
            bumpmap = None

        double_sided_node = node.find('.//%s//%s' % (tag('extra'), tag('double_sided')))
        double_sided = False
        if double_sided_node is not None and double_sided_node.text is not None:
            try:
                val = int(double_sided_node.text)
                if val == 1:
                    double_sided = True
            except ValueError:
                pass
        return Effect(id, params, shadingtype, bumpmap, double_sided, **props)
Пример #9
0
    def _getInputsFromList(collada, localscope, inputs):
        #first let's save any of the source that are references to a dict
        to_append = []
        for input in inputs:
            offset, semantic, source, set = input
            if semantic == 'VERTEX':
                vertex_source = localscope.get(source[1:])
                if isinstance(vertex_source, dict):
                    for inputsemantic, inputsource in vertex_source.items():
                        if inputsemantic == 'POSITION':
                            to_append.append([offset, 'VERTEX', '#' + inputsource.id, set])
                        else:
                            to_append.append([offset, inputsemantic, '#' + inputsource.id, set])

        #remove all the dicts
        inputs[:] = [input for input in inputs
                if not isinstance(localscope.get(input[2][1:]), dict)]

        #append the dereferenced dicts
        for a in to_append:
            inputs.append(a)

        vertex_inputs = []
        normal_inputs = []
        texcoord_inputs = []
        textangent_inputs = []
        texbinormal_inputs = []
        color_inputs = []
        tangent_inputs = []
        binormal_inputs = []

        all_inputs = {}

        for input in inputs:
            offset, semantic, source, set = input
            if len(source) < 2 or source[0] != '#':
                raise DaeMalformedError('Incorrect source id "%s" in input' % source)
            if source[1:] not in localscope:
                raise DaeBrokenRefError('Source input id "%s" not found' % source)
            input = (input[0], input[1], input[2], input[3], localscope[source[1:]])
            if semantic == 'VERTEX':
                vertex_inputs.append(input)
            elif semantic == 'NORMAL':
                normal_inputs.append(input)
            elif semantic == 'TEXCOORD':
                texcoord_inputs.append(input)
            elif semantic == 'TEXTANGENT':
                textangent_inputs.append(input)
            elif semantic == 'TEXBINORMAL':
                texbinormal_inputs.append(input)
            elif semantic == 'COLOR':
                color_inputs.append(input)
            elif semantic == 'TANGENT':
                tangent_inputs.append(input)
            elif semantic == 'BINORMAL':
                binormal_inputs.append(input)
            else:
                try:
                    raise DaeUnsupportedError('Unknown input semantic: %s' % semantic)
                except DaeUnsupportedError as ex:
                    collada.handleError(ex)
                unknown_input = all_inputs.get(semantic, [])
                unknown_input.append(input)
                all_inputs[semantic] = unknown_input

        all_inputs['VERTEX'] = vertex_inputs
        all_inputs['NORMAL'] = normal_inputs
        all_inputs['TEXCOORD'] = texcoord_inputs
        all_inputs['TEXBINORMAL'] = texbinormal_inputs
        all_inputs['TEXTANGENT'] = textangent_inputs
        all_inputs['COLOR'] = color_inputs
        all_inputs['TANGENT'] = tangent_inputs
        all_inputs['BINORMAL'] = binormal_inputs

        return all_inputs