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
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
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))
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))
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)
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)
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)
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)
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