def _getFileFromZip(self, fname): """Return the binary data of an auxiliary file from a zip archive as a string.""" if not self.zfile: raise DaeBrokenRefError('Trying to load an auxiliary file %s but we are not reading from a zip'%fname) basepath = posixpath.dirname(self.filename) aux_path = posixpath.normpath(posixpath.join(basepath, fname)) if aux_path not in self.zfile.namelist(): raise DaeBrokenRefError('Auxiliar file %s not found in archive' % fname) return self.zfile.read( aux_path )
def _getFileFromDisk(self, fname): """Return the binary data of an auxiliary file from the local disk relative to the file path loaded.""" if self.zfile: raise DaeBrokenRefError('Trying to load an auxiliary file %s from disk but we are reading from a zip file'%fname) basepath = os.path.dirname(self.filename) aux_path = os.path.normpath(os.path.join(basepath, fname)) if not os.path.exists(aux_path): raise DaeBrokenRefError('Auxiliar file %s not found on disk'%fname) fdata = open(aux_path, 'rb') return fdata.read()
def load(collada, localscope, morphnode, controllernode): baseid = morphnode.get('source') if len(baseid) < 2 or baseid[0] != '#' or \ not baseid[1:] in collada.geometries: raise DaeBrokenRefError('Base source of morph %s not found' % baseid) basegeom = collada.geometries[baseid[1:]] method = morphnode.get('method') if method is None: method = 'NORMALIZED' if not (method == 'NORMALIZED' or method == 'RELATIVE'): raise DaeMalformedError( "Morph method must be either NORMALIZED or RELATIVE. Found '%s'" % method) inputnodes = morphnode.findall( '%s/%s' % (collada.tag('targets'), collada.tag('input'))) if inputnodes is None or len(inputnodes) < 2: raise DaeIncompleteError("Not enough inputs in a morph") try: inputs = [(i.get('semantic'), i.get('source')) for i in inputnodes] except ValueError as ex: raise DaeMalformedError('Corrupted inputs in morph') target_source = None weight_source = None for i in inputs: if len(i[1]) < 2 or i[1][0] != '#' or not i[1][1:] in localscope: raise DaeBrokenRefError('Input in morph node %s not found' % i[1]) if i[0] == 'MORPH_TARGET': target_source = localscope[i[1][1:]] elif i[0] == 'MORPH_WEIGHT': weight_source = localscope[i[1][1:]] if not type(target_source) is source.IDRefSource or \ not type(weight_source) is source.FloatSource: raise DaeIncompleteError("Not enough inputs in targets of morph") if len(target_source) != len(weight_source): raise DaeMalformedError("Morph inputs must be of same length") target_list = [] for target, weight in zip(target_source, weight_source): if len(target) < 1 or not (target in collada.geometries): raise DaeBrokenRefError( "Targeted geometry %s in morph not found" % target) target_list.append((collada.geometries[target], weight[0])) return Morph(basegeom, target_list, controllernode)
def __wrapped(fname): res = aux_file_loader(fname) if res is None: raise DaeBrokenRefError( 'Auxiliar file %s from auxiliary file loader not found' % fname) return res
def load(collada, node): url = node.get('url') if not url.startswith('#'): raise DaeMalformedError('Invalid url in camera instance %s' % url) camera = collada.cameras.get(url[1:]) if not camera: raise DaeBrokenRefError('Camera %s not found in library' % url) return CameraNode(camera, xmlnode=node)
def load(collada, node): url = node.get('url') if not url.startswith('#'): raise DaeMalformedError('Invalid url in light instance %s' % url) light = collada.lights.get(url[1:]) if not light: raise DaeBrokenRefError('Light %s not found in library' % url) return LightNode(light, xmlnode=node)
def load(collada, node): inputs = [] for inputnode in node.findall( tag('bind_vertex_input') ): inputs.append( ( inputnode.get('semantic'), inputnode.get('input_semantic'), inputnode.get('input_set') ) ) targetid = node.get('target') if not targetid.startswith('#'): raise DaeMalformedError('Incorrect target id in material '+targetid) target = collada.materials.get(targetid[1:]) if not target: raise DaeBrokenRefError('Material %s not found'%targetid) return MaterialNode(node.get('symbol'), target, inputs, xmlnode = 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(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 load( collada, node ): url = node.get('url') if not url.startswith('#'): raise DaeMalformedError('Invalid url in geometry instance %s' % url) geometry = collada.geometries.get(url[1:]) if not geometry: raise DaeBrokenRefError('Geometry %s not found in library'%url) matnodes = node.findall('%s/%s/%s'%( tag('bind_material'), tag('technique_common'), tag('instance_material') ) ) materials = [] for matnode in matnodes: materials.append( MaterialNode.load(collada, matnode) ) return GeometryNode( geometry, materials, xmlnode=node)
def load( collada, node ): url = node.get('url') if not url.startswith('#'): raise DaeMalformedError('Invalid url in controller instance %s' % url) controller = collada.controllers.get(url[1:]) if not controller: raise DaeBrokenRefError('Controller %s not found in library'%url) matnodes = node.findall('%s/%s/%s'%( tag('bind_material'), tag('technique_common'), tag('instance_material') ) ) materials = [] for matnode in matnodes: materials.append( MaterialNode.load(collada, matnode) ) return ControllerNode( controller, materials, xmlnode=node)
def _loadDefaultScene(self): """Loads the default scene from <scene> tag in the root node.""" node = self.xmlnode.find('%s/%s' % (tag('scene'), tag('instance_visual_scene'))) try: if node != None: sceneid = node.get('url') if not sceneid.startswith('#'): raise DaeMalformedError('Malformed default scene reference to %s: '%sceneid) self.scene = self.scenes.get(sceneid[1:]) if not self.scene: raise DaeBrokenRefError('Default scene %s not found' % sceneid) except DaeError as ex: self.handleError(ex)
def load( collada, localscope, node ): matid = node.get('id') matname = node.get('name') effnode = node.find( tag('instance_effect')) if effnode is None: raise DaeIncompleteError('No effect inside material') effectid = effnode.get('url') if not effectid.startswith('#'): raise DaeMalformedError('Corrupted effect reference in material %s' % effectid) effect = collada.effects.get(effectid[1:]) if not effect: raise DaeBrokenRefError('Effect not found: '+effectid) return Material(matid, matname, effect, xmlnode=node)
def load( collada, localscope, node ): surfacenode = node.find( tag('surface') ) if surfacenode is None: raise DaeIncompleteError('No surface found in newparam') if surfacenode.get('type') != '2D': raise DaeMalformedError('Hard to imagine a non-2D surface, isn\'t it?') initnode = surfacenode.find( tag('init_from') ) if initnode is None: raise DaeIncompleteError('No init image found in surface') formatnode = surfacenode.find( tag('format') ) if formatnode is None: format = None else: format = formatnode.text imgid = initnode.text id = node.get('sid') if imgid in localscope: img = localscope[imgid] else: img = collada.images.get(imgid) if img is None: raise DaeBrokenRefError("Missing image '%s' in surface '%s'" % (imgid, id)) return Surface(id, img, format, xmlnode=node)
def load( collada, localscope, node ): samplernode = node.find( tag('sampler2D') ) if samplernode is None: raise DaeIncompleteError('No sampler found in newparam') sourcenode = samplernode.find( tag('source') ) if sourcenode is None: raise DaeIncompleteError('No source found in sampler') minnode = samplernode.find( tag('minfilter') ) if minnode is None: minfilter = None else: minfilter = minnode.text magnode = samplernode.find( tag('magfilter') ) if magnode is None: magfilter = None else: magfilter = magnode.text surfaceid = sourcenode.text id = node.get('sid') surface = localscope.get(surfaceid) if surface is None or type(surface) != Surface: raise DaeBrokenRefError('Missing surface ' + surfaceid) return Sampler2D(id, surface, minfilter, magfilter, xmlnode=node)
def load(collada, node): id = node.get('id') nodes = [] tried_loading = [] succeeded = False localscope = {} for nodenode in node.findall(collada.tag('node')): try: N = loadNode(collada, nodenode, localscope) except DaeInstanceNotLoadedError as ex: tried_loading.append((nodenode, ex)) except DaeError as ex: collada.handleError(ex) else: if N is not None: nodes.append(N) if N.id and N.id not in localscope: localscope[N.id] = N succeeded = True while len(tried_loading) > 0 and succeeded: succeeded = False next_tried = [] for nodenode, ex in tried_loading: try: N = loadNode(collada, nodenode, localscope) except DaeInstanceNotLoadedError as ex: next_tried.append((nodenode, ex)) except DaeError as ex: collada.handleError(ex) else: if N is not None: nodes.append(N) succeeded = True tried_loading = next_tried if len(tried_loading) > 0: for nodenode, ex in tried_loading: raise DaeBrokenRefError(ex.msg) return Scene(id, nodes, xmlnode=node, collada=collada)
def _loadNodes(self): libnodes = self.xmlnode.findall(self.tag('library_nodes')) if libnodes is not None: for libnode in libnodes: if libnode is not None: tried_loading = [] succeeded = False for node in libnode.findall(self.tag('node')): try: N = scene.loadNode(self, node, {}) except scene.DaeInstanceNotLoadedError as ex: tried_loading.append((node, ex)) except DaeError as ex: self.handleError(ex) else: if N is not None: self.nodes.append(N) succeeded = True while len(tried_loading) > 0 and succeeded: succeeded = False next_tried = [] for node, ex in tried_loading: try: N = scene.loadNode(self, node, {}) except scene.DaeInstanceNotLoadedError as ex: next_tried.append((node, ex)) except DaeError as ex: self.handleError(ex) else: if N is not None: self.nodes.append(N) succeeded = True tried_loading = next_tried if len(tried_loading) > 0: for node, ex in tried_loading: raise DaeBrokenRefError(ex.msg)
def load(collada, localscope, skinnode, controllernode): if len(localscope) < 3: raise DaeMalformedError('Not enough sources in skin') geometry_source = skinnode.get('source') if geometry_source is None or len(geometry_source) < 2 \ or geometry_source[0] != '#': raise DaeBrokenRefError('Invalid source attribute of skin node') if not geometry_source[1:] in collada.geometries: raise DaeBrokenRefError('Source geometry for skin node not found') geometry = collada.geometries[geometry_source[1:]] bind_shape_mat = skinnode.find(collada.tag('bind_shape_matrix')) if bind_shape_mat is None: bind_shape_mat = numpy.identity(4, dtype=numpy.float32) bind_shape_mat.shape = (-1, ) else: try: values = [float(v) for v in bind_shape_mat.text.split()] except ValueError: raise DaeMalformedError('Corrupted bind shape matrix in skin') bind_shape_mat = numpy.array(values, dtype=numpy.float32) inputnodes = skinnode.findall( '%s/%s' % (collada.tag('joints'), collada.tag('input'))) if inputnodes is None or len(inputnodes) < 2: raise DaeIncompleteError("Not enough inputs in skin joints") try: inputs = [(i.get('semantic'), i.get('source')) for i in inputnodes] except ValueError as ex: raise DaeMalformedError('Corrupted inputs in skin') joint_source = None matrix_source = None for i in inputs: if len(i[1]) < 2 or i[1][0] != '#': raise DaeBrokenRefError('Input in skin node %s not found' % i[1]) if i[0] == 'JOINT': joint_source = i[1][1:] elif i[0] == 'INV_BIND_MATRIX': matrix_source = i[1][1:] weightsnode = skinnode.find(collada.tag('vertex_weights')) if weightsnode is None: raise DaeIncompleteError("No vertex_weights found in skin") indexnode = weightsnode.find(collada.tag('v')) if indexnode is None: raise DaeIncompleteError('Missing indices in skin vertex weights') vcountnode = weightsnode.find(collada.tag('vcount')) if vcountnode is None: raise DaeIncompleteError('Missing vcount in skin vertex weights') inputnodes = weightsnode.findall(collada.tag('input')) try: index = numpy.array([float(v) for v in indexnode.text.split()], dtype=numpy.int32) vcounts = numpy.array([int(v) for v in vcountnode.text.split()], dtype=numpy.int32) inputs = [(i.get('semantic'), i.get('source'), int(i.get('offset'))) for i in inputnodes] except ValueError as ex: raise DaeMalformedError( 'Corrupted index or offsets in skin vertex weights') weight_joint_source = None weight_source = None offsets = [0, 0] for i in inputs: if len(i[1]) < 2 or i[1][0] != '#': raise DaeBrokenRefError('Input in skin node %s not found' % i[1]) if i[0] == 'JOINT': weight_joint_source = i[1][1:] offsets[0] = i[2] elif i[0] == 'WEIGHT': weight_source = i[1][1:] offsets[1] = i[2] if joint_source is None or weight_source is None: raise DaeMalformedError( 'Not enough inputs for vertex weights in skin') return Skin(localscope, bind_shape_mat, joint_source, matrix_source, weight_source, weight_joint_source, vcounts, index, offsets, geometry, controllernode, skinnode)
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
def _nullGetFile(self, fname): raise DaeBrokenRefError( 'Trying to load auxiliary file but collada was not loaded from disk, zip, or with custom handler' )
def __init__(self, sourcebyid, bind_shape_matrix, joint_source, joint_matrix_source, weight_source, weight_joint_source, vcounts, vertex_weight_index, offsets, geometry, controller_node=None, skin_node=None): """Create a skin. :Parameters: sourceById A dict mapping id's to a collada source bind_shape_matrix A numpy array of floats (pre-shape) joint_source The string id for the joint source joint_matrix_source The string id for the joint matrix source weight_source The string id for the weight source weight_joint_source The string id for the joint source of weights vcounts A list with the number of influences on each vertex vertex_weight_index An array with the indexes as they come from <v> array offsets A list with the offsets in the weight index array for each source in (joint, weight) geometry The source geometry this should be applied to (geometry.Geometry) controller_node XML node of the <controller> tag which is the parent of this skin_node XML node of the <skin> tag if this is from there """ self.sourcebyid = sourcebyid self.bind_shape_matrix = bind_shape_matrix self.joint_source = joint_source self.joint_matrix_source = joint_matrix_source self.weight_source = weight_source self.weight_joint_source = weight_joint_source self.vcounts = vcounts self.vertex_weight_index = vertex_weight_index self.offsets = offsets self.geometry = geometry self.controller_node = controller_node self.skin_node = skin_node self.xmlnode = controller_node if not type(self.geometry) is Geometry: raise DaeMalformedError('Invalid reference geometry in skin') self.id = controller_node.get('id') if self.id is None: raise DaeMalformedError('Controller node requires an ID') self.nindices = max(self.offsets) + 1 if len(bind_shape_matrix) != 16: raise DaeMalformedError('Corrupted bind shape matrix in skin') self.bind_shape_matrix.shape = (4, 4) if not (joint_source in sourcebyid and joint_matrix_source in sourcebyid): raise DaeBrokenRefError("Input in joints not found") if not (type(sourcebyid[joint_source]) is source.NameSource or type(sourcebyid[joint_source]) is source.IDRefSource): raise DaeIncompleteError( "Could not find joint name input for skin") if not type(sourcebyid[joint_matrix_source]) is source.FloatSource: raise DaeIncompleteError( "Could not find joint matrix source for skin") joint_names = [j for j in sourcebyid[joint_source]] joint_matrices = sourcebyid[joint_matrix_source].data joint_matrices.shape = (-1, 4, 4) if len(joint_names) != len(joint_matrices): raise DaeMalformedError( "Skin joint and matrix inputs must be same length") self.joint_matrices = {} for n, m in zip(joint_names, joint_matrices): self.joint_matrices[n] = m if not (weight_source in sourcebyid and weight_joint_source in sourcebyid): raise DaeBrokenRefError("Weights input in joints not found") if not type(sourcebyid[weight_source]) is source.FloatSource: raise DaeIncompleteError("Could not find weight inputs for skin") if not (type(sourcebyid[weight_joint_source]) is source.NameSource or type(sourcebyid[weight_joint_source]) is source.IDRefSource): raise DaeIncompleteError( "Could not find weight joint source input for skin") self.weights = sourcebyid[weight_source] self.weight_joints = sourcebyid[weight_joint_source] try: newshape = [] at = 0 for ct in self.vcounts: this_set = self.vertex_weight_index[self.nindices * at:self.nindices * (at + ct)] this_set.shape = (ct, self.nindices) newshape.append(numpy.array(this_set)) at += ct self.index = newshape except: raise DaeMalformedError( 'Corrupted vcounts or index in skin weights') try: self.joint_index = [ influence[:, self.offsets[0]] for influence in self.index ] self.weight_index = [ influence[:, self.offsets[1]] for influence in self.index ] except: raise DaeMalformedError('Corrupted joint or weight index in skin') self.max_joint_index = numpy.max([ numpy.max(joint) if len(joint) > 0 else 0 for joint in self.joint_index ]) self.max_weight_index = numpy.max([ numpy.max(weight) if len(weight) > 0 else 0 for weight in self.weight_index ]) checkSource(self.weight_joints, ('JOINT', ), self.max_joint_index) checkSource(self.weights, ('WEIGHT', ), self.max_weight_index)
def __init__(self, sourcebyid, bind_shape_matrix, joint_source, joint_matrix_source, weight_source, weight_joint_source, vcounts, vertex_weight_index, offsets, geometry, controller_node=None, skin_node=None, controllerID=None): """Create a skin. :Parameters: sourceById A dict mapping id's to a collada source bind_shape_matrix A numpy array of floats (pre-shape) joint_source The string id for the joint source joint_matrix_source The string id for the joint matrix source weight_source The string id for the weight source weight_joint_source The string id for the joint source of weights vcounts A list with the number of influences on each vertex vertex_weight_index An array with the indexes as they come from <v> array offsets A list with the offsets in the weight index array for each source in (joint, weight) geometry The source geometry this should be applied to (geometry.Geometry) controller_node XML node of the <controller> tag which is the parent of this skin_node XML node of the <skin> tag if this is from there controllerID The string id for current controller (optional) if controller_node is not provided, feed controllerID from here directly """ self.sourceById = sourcebyid self.bind_shape_matrix = bind_shape_matrix self.joint_source = joint_source self.joint_matrix_source = joint_matrix_source self.weight_source = weight_source self.weight_joint_source = weight_joint_source self.vcounts = vcounts self.vertex_weight_index = vertex_weight_index self.offsets = offsets self.geometry = geometry self.controller_node = controller_node self.skin_node = skin_node if not type(self.geometry) is Geometry: raise DaeMalformedError('Invalid reference geometry in skin') if controller_node is not None: self.id = controller_node.get('id') else: if controllerID: self.id = controllerID if self.id is None: raise DaeMalformedError('Controller node requires an ID') self.nindices = max(self.offsets) + 1 if len(bind_shape_matrix) != 16: raise DaeMalformedError('Corrupted bind shape matrix in skin') self.bind_shape_matrix.shape = (4, 4) if not (joint_source in sourcebyid and joint_matrix_source in sourcebyid): raise DaeBrokenRefError("Input in joints not found") if not (type(sourcebyid[joint_source]) is source.NameSource or type(sourcebyid[joint_source]) is source.IDRefSource): raise DaeIncompleteError( "Could not find joint name input for skin") if not type(sourcebyid[joint_matrix_source]) is source.FloatSource: raise DaeIncompleteError( "Could not find joint matrix source for skin") joint_names = [j for j in sourcebyid[joint_source]] joint_matrices = sourcebyid[joint_matrix_source].data joint_matrices.shape = (-1, 4, 4) if len(joint_names) != len(joint_matrices): raise DaeMalformedError( "Skin joint and matrix inputs must be same length") self.joint_matrices = {} for n, m in zip(joint_names, joint_matrices): self.joint_matrices[n] = m if not (weight_source in sourcebyid and weight_joint_source in sourcebyid): raise DaeBrokenRefError("Weights input in joints not found") if not type(sourcebyid[weight_source]) is source.FloatSource: raise DaeIncompleteError("Could not find weight inputs for skin") if not (type(sourcebyid[weight_joint_source]) is source.NameSource or type(sourcebyid[weight_joint_source]) is source.IDRefSource): raise DaeIncompleteError( "Could not find weight joint source input for skin") self.weights = sourcebyid[weight_source] self.weight_joints = sourcebyid[weight_joint_source] try: newshape = [] at = 0 for ct in self.vcounts: this_set = self.vertex_weight_index[self.nindices * at:self.nindices * (at + ct)] this_set.shape = (ct, self.nindices) newshape.append(numpy.array(this_set)) at += ct self.index = newshape except: raise DaeMalformedError( 'Corrupted vcounts or index in skin weights') try: self.joint_index = [ influence[:, self.offsets[0]] for influence in self.index ] self.weight_index = [ influence[:, self.offsets[1]] for influence in self.index ] except: raise DaeMalformedError('Corrupted joint or weight index in skin') self.max_joint_index = numpy.max([ numpy.max(joint) if len(joint) > 0 else 0 for joint in self.joint_index ]) self.max_weight_index = numpy.max([ numpy.max(weight) if len(weight) > 0 else 0 for weight in self.weight_index ]) checkSource(self.weight_joints, ('JOINT', ), self.max_joint_index) checkSource(self.weights, ('WEIGHT', ), self.max_weight_index) # original lib missing xml reconstruct clause if controller_node is not None: self.xmlnode = controller_node else: sourcenodes = [] for srcid, src in self.sourceById.items(): sourcenodes.append(src.xmlnode) controllernode = E.skin(*sourcenodes) if len(geometry.id) > 0: controllernode.set("source", '#' + geometry.id) #construct bind_shape_matrix xml node node = E.bind_shape_matrix() bind_shape_matrix.shape = (-1, ) node.text = ' '.join(map(str, bind_shape_matrix.tolist())) controllernode.append(node) #construct <joints> node node = E.joints() node.append( E.input(semantic="JOINT", source="#%s" % self.joint_source)) node.append( E.input(semantic="INV_BIND_MATRIX", source="#%s" % self.joint_matrix_source)) controllernode.append(node) #construct <vertex_weights> node node = E.vertex_weights() #todo: offset is hardcoded here. node.append( E.input(semantic="JOINT", offset="0", source="#%s" % self.weight_joint_source)) node.append( E.input(semantic="WEIGHT", offset="1", source="#%s" % self.weight_source)) nodevcount = E.vcount() nodevcount.text = ' '.join(map(str, self.vcounts)) node.append(nodevcount) nodev = E.v() nodev.text = ' '.join(map(str, self.vertex_weight_index)) node.set("count", str(len(self.vcounts))) node.append(nodev) controllernode.append(node) self.xmlnode = E.controller(controllernode) if len(self.id) > 0: self.xmlnode.set("id", self.id)