def test_collada_duck_poly(self): f = os.path.join(self.datadir, "duck_polylist.dae") mesh = collada.Collada(f, validate_output=True) self.assertEqual(mesh.scene.id, 'VisualSceneNode') self.assertIn('LOD3spShape-lib', mesh.geometries) self.assertIn('directionalLightShape1-lib', mesh.lights) self.assertIn('cameraShape1', mesh.cameras) self.assertIn('file2', mesh.images) self.assertIn('blinn3-fx', mesh.effects) self.assertIn('blinn3', mesh.materials) self.assertEqual(len(mesh.nodes), 0) self.assertIn('VisualSceneNode', mesh.scenes) s = BytesIO() mesh.write(s) out = s.getvalue() t = BytesIO(out) mesh = collada.Collada(t, validate_output=True) self.assertEqual(mesh.scene.id, 'VisualSceneNode') self.assertIn('LOD3spShape-lib', mesh.geometries) self.assertIn('directionalLightShape1-lib', mesh.lights) self.assertIn('cameraShape1', mesh.cameras) self.assertIn('file2', mesh.images) self.assertIn('blinn3-fx', mesh.effects) self.assertIn('blinn3', mesh.materials) self.assertEqual(len(mesh.nodes), 0) self.assertIn('VisualSceneNode', mesh.scenes)
def _getColladaSchemaInstance(self): if self._COLLADA_SCHEMA_1_4_1_INSTANCE is None: self._parser = lxml.etree.XMLParser() self._parser.resolvers.add(ColladaResolver()) self.COLLADA_SCHEMA_1_4_1_DOC = lxml.etree.parse( BytesIO(bytes(COLLADA_SCHEMA_1_4_1, encoding='utf-8')), self._parser) self._COLLADA_SCHEMA_1_4_1_INSTANCE = lxml.etree.XMLSchema( self.COLLADA_SCHEMA_1_4_1_DOC) return self._COLLADA_SCHEMA_1_4_1_INSTANCE
def getImage(self): if pil is None or self._pilimage is _FAILED: return None if self._pilimage: return self._pilimage else: data = self.getData() if not data: self._pilimage = _FAILED return None try: self._pilimage = pil.open( BytesIO(data) ) self._pilimage.load() except IOError as ex: self._pilimage = _FAILED return None return self._pilimage
def __init__(self, filename=None, ignore=None, aux_file_loader=None, zip_filename=None, validate_output=False): """Load collada data from filename or file like object. :param filename: String containing path to filename to open or file-like object. Uncompressed .dae files are supported, as well as zip file archives. If this is set to ``None``, a new collada instance is created. :param list ignore: A list of :class:`common.DaeError` types that should be ignored when loading the collada document. Instances of these types will be added to :attr:`errors` after loading but won't be raised. Only used if `filename` is not ``None``. :param function aux_file_loader: Referenced files (e.g. texture images) are loaded from disk when reading from the local filesystem and from the zip archive when loading from a zip file. If these files are coming from another source (e.g. database) and/or you're loading with StringIO, set this to a function that given a filename, returns the binary data in the file. If `filename` is ``None``, you must set this parameter if you want to load auxiliary files. :param str zip_filename: If the file being loaded is a zip archive, you can set this parameter to indicate the file within the archive that should be loaded. If not set, a file that ends with .dae will be searched. :param bool validate_output: If set to True, the XML written when calling :meth:`save` will be validated against the COLLADA 1.4.1 schema. If validation fails, the :class:`common.DaeSaveValidationError` exception will be thrown. """ self.errors = [] """List of :class:`common.common.DaeError` objects representing errors encountered while loading collada file""" self.assetInfo = None """Instance of :class:`collada.asset.Asset` containing asset information""" self._geometries = IndexedList([], ('id', )) self._controllers = IndexedList([], ('id', )) self._animations = IndexedList([], ('id', )) self._lights = IndexedList([], ('id', )) self._cameras = IndexedList([], ('id', )) self._images = IndexedList([], ('id', )) self._effects = IndexedList([], ('id', )) self._materials = IndexedList([], ('id', )) self._nodes = IndexedList([], ('id', )) self._scenes = IndexedList([], ('id', )) self.scene = None """The default scene. This is either an instance of :class:`collada.scene.Scene` or `None`.""" # a function which will apply the namespace self.tag = tag if validate_output and schema: self.validator = schema.ColladaValidator() else: self.validator = None self.maskedErrors = [] if ignore is not None: self.ignoreErrors(*ignore) if filename is None: self.filename = None self.zfile = None self.getFileData = self._nullGetFile if aux_file_loader is not None: self.getFileData = self._wrappedFileLoader(aux_file_loader) self.xmlnode = ElementTree.ElementTree( E.COLLADA(E.library_cameras(), E.library_controllers(), E.library_effects(), E.library_geometries(), E.library_images(), E.library_lights(), E.library_materials(), E.library_nodes(), E.library_visual_scenes(), E.scene(), version='1.4.1')) """ElementTree representation of the collada document""" self.assetInfo = asset.Asset() return if isinstance(filename, basestring): fdata = open(filename, 'rb') self.filename = filename self.getFileData = self._getFileFromDisk else: fdata = filename # assume it is a file like object self.filename = None self.getFileData = self._nullGetFile strdata = fdata.read() try: self.zfile = zipfile.ZipFile(BytesIO(strdata), 'r') except: self.zfile = None if self.zfile: self.filename = '' daefiles = [] if zip_filename is not None: self.filename = zip_filename else: for name in self.zfile.namelist(): if name.upper().endswith('.DAE'): daefiles.append(name) for name in daefiles: if not self.filename: self.filename = name elif "MACOSX" in self.filename: self.filename = name if not self.filename or self.filename not in self.zfile.namelist(): raise DaeIncompleteError( 'COLLADA file not found inside zip compressed file') data = self.zfile.read(self.filename) self.getFileData = self._getFileFromZip else: data = strdata if aux_file_loader is not None: self.getFileData = self._wrappedFileLoader(aux_file_loader) etree_parser = ElementTree.XMLParser() try: self.xmlnode = ElementTree.ElementTree(element=None, file=BytesIO(data)) except ElementTree.ParseError as e: raise DaeMalformedError("XML Parsing Error: %s" % e) # if we can't get the current namespace # the tagger from above will use a hardcoded default try: # get the root node, same for both etree and lxml xml_root = self.xmlnode.getroot() if hasattr(xml_root, 'nsmap'): # lxml has an nsmap # use the first value in the namespace map namespace = next(iter(xml_root.nsmap.values())) elif hasattr(xml_root, 'tag'): # for xml.etree we need to extract ns from root tag namespace = xml_root.tag.split('}')[0].lstrip('{') # create a tagging function using the extracted namespace self.tag = tagger(namespace) except BaseException: # failed to extract a namespace, using default traceback.print_exc() # functions which will load various things into collada object self._loadAssetInfo() self._loadImages() self._loadEffects() self._loadMaterials() self._loadAnimations() self._loadGeometry() self._loadControllers() self._loadLights() self._loadCameras() self._loadNodes() self._loadScenes() self._loadDefaultScene()
def test_collada_duck_tris(self): f = os.path.join(self.datadir, "duck_triangles.dae") mesh = collada.Collada(f, validate_output=True) self.assertEqual(mesh.assetInfo.contributors[0].author, 'gcorson') self.assertEqual(mesh.assetInfo.contributors[0].authoring_tool, 'Maya 8.0 | ColladaMaya v3.02 | FCollada v3.2') self.assertEqual( mesh.assetInfo.contributors[0].source_data, 'file:///C:/vs2005/sample_data/Complete_Packages/SCEA_Private/Maya_MoonLander/Moonlander/untitled' ) self.assertEqual(len(mesh.assetInfo.contributors[0].copyright), 595) self.assertEqual(len(mesh.assetInfo.contributors[0].comments), 449) self.assertEqual(mesh.assetInfo.unitmeter, 0.01) self.assertEqual(mesh.assetInfo.unitname, 'centimeter') self.assertEqual(mesh.assetInfo.upaxis, collada.asset.UP_AXIS.Y_UP) self.assertIsNone(mesh.assetInfo.title) self.assertIsNone(mesh.assetInfo.subject) self.assertIsNone(mesh.assetInfo.revision) self.assertIsNone(mesh.assetInfo.keywords) self.assertEqual(mesh.assetInfo.created, dateutil.parser.parse('2006-08-23T22:29:59Z')) self.assertEqual(mesh.assetInfo.modified, dateutil.parser.parse('2007-02-21T22:52:44Z')) self.assertEqual(mesh.scene.id, 'VisualSceneNode') self.assertIn('LOD3spShape-lib', mesh.geometries) self.assertIn('directionalLightShape1-lib', mesh.lights) self.assertIn('cameraShape1', mesh.cameras) self.assertIn('file2', mesh.images) self.assertIn('blinn3-fx', mesh.effects) self.assertIn('blinn3', mesh.materials) self.assertEqual(len(mesh.nodes), 0) self.assertIn('VisualSceneNode', mesh.scenes) triset = mesh.geometries[0].primitives[0] input_list = triset.getInputList().getList() self.assertEqual(3, len(input_list)) self.assertIsNotNone(str(list(mesh.scene.objects('geometry')))) self.assertIsNotNone(str(list(mesh.scene.objects('light')))) self.assertIsNotNone(str(list(mesh.scene.objects('camera')))) s = BytesIO() mesh.write(s) out = s.getvalue() t = BytesIO(out) mesh = collada.Collada(t, validate_output=True) self.assertEqual(mesh.assetInfo.contributors[0].author, 'gcorson') self.assertEqual(mesh.assetInfo.contributors[0].authoring_tool, 'Maya 8.0 | ColladaMaya v3.02 | FCollada v3.2') self.assertEqual( mesh.assetInfo.contributors[0].source_data, 'file:///C:/vs2005/sample_data/Complete_Packages/SCEA_Private/Maya_MoonLander/Moonlander/untitled' ) self.assertEqual(len(mesh.assetInfo.contributors[0].copyright), 595) self.assertEqual(len(mesh.assetInfo.contributors[0].comments), 449) self.assertEqual(mesh.assetInfo.unitmeter, 0.01) self.assertEqual(mesh.assetInfo.unitname, 'centimeter') self.assertEqual(mesh.assetInfo.upaxis, collada.asset.UP_AXIS.Y_UP) self.assertIsNone(mesh.assetInfo.title) self.assertIsNone(mesh.assetInfo.subject) self.assertIsNone(mesh.assetInfo.revision) self.assertIsNone(mesh.assetInfo.keywords) self.assertEqual(mesh.assetInfo.created, dateutil.parser.parse('2006-08-23T22:29:59Z')) self.assertEqual(mesh.assetInfo.modified, dateutil.parser.parse('2007-02-21T22:52:44Z')) self.assertEqual(mesh.scene.id, 'VisualSceneNode') self.assertIn('LOD3spShape-lib', mesh.geometries) self.assertIn('directionalLightShape1-lib', mesh.lights) self.assertIn('cameraShape1', mesh.cameras) self.assertIn('file2', mesh.images) self.assertIn('blinn3-fx', mesh.effects) self.assertIn('blinn3', mesh.materials) self.assertEqual(len(mesh.nodes), 0) self.assertIn('VisualSceneNode', mesh.scenes) self.assertIsNotNone(str(list(mesh.scene.objects('geometry')))) self.assertIsNotNone(str(list(mesh.scene.objects('light')))) self.assertIsNotNone(str(list(mesh.scene.objects('camera'))))
def test_collada_saving(self): mesh = collada.Collada(validate_output=True) self.assertEqual(len(mesh.geometries), 0) self.assertEqual(len(mesh.controllers), 0) self.assertEqual(len(mesh.lights), 0) self.assertEqual(len(mesh.cameras), 0) self.assertEqual(len(mesh.images), 0) self.assertEqual(len(mesh.effects), 0) self.assertEqual(len(mesh.materials), 0) self.assertEqual(len(mesh.nodes), 0) self.assertEqual(len(mesh.scenes), 0) self.assertEqual(mesh.scene, None) self.assertIsNotNone(str(mesh)) floatsource = collada.source.FloatSource("myfloatsource", numpy.array([0.1, 0.2, 0.3]), ('X', 'Y', 'Z')) geometry1 = collada.geometry.Geometry(mesh, "geometry1", "mygeometry1", {"myfloatsource": floatsource}) mesh.geometries.append(geometry1) linefloats = [ 1, 1, -1, 1, -1, -1, -1, -0.9999998, -1, -0.9999997, 1, -1, 1, 0.9999995, 1, 0.9999994, -1.000001, 1 ] linefloatsrc = collada.source.FloatSource("mylinevertsource", numpy.array(linefloats), ('X', 'Y', 'Z')) geometry2 = collada.geometry.Geometry(mesh, "geometry2", "mygeometry2", [linefloatsrc]) input_list = collada.source.InputList() input_list.addInput(0, 'VERTEX', "#mylinevertsource") indices = numpy.array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5]) lineset1 = geometry2.createLineSet(indices, input_list, "mymaterial2") geometry2.primitives.append(lineset1) mesh.geometries.append(geometry2) ambientlight = collada.light.AmbientLight("myambientlight", (1, 1, 1)) pointlight = collada.light.PointLight("mypointlight", (1, 1, 1)) mesh.lights.append(ambientlight) mesh.lights.append(pointlight) camera1 = collada.camera.PerspectiveCamera("mycam1", 45.0, 0.01, 1000.0) camera2 = collada.camera.PerspectiveCamera("mycam2", 45.0, 0.01, 1000.0) mesh.cameras.append(camera1) mesh.cameras.append(camera2) cimage1 = collada.material.CImage("mycimage1", "./whatever.tga", mesh) cimage2 = collada.material.CImage("mycimage2", "./whatever.tga", mesh) mesh.images.append(cimage1) mesh.images.append(cimage2) effect1 = collada.material.Effect("myeffect1", [], "phong") effect2 = collada.material.Effect("myeffect2", [], "phong") mesh.effects.append(effect1) mesh.effects.append(effect2) mat1 = collada.material.Material("mymaterial1", "mymat1", effect1) mat2 = collada.material.Material("mymaterial2", "mymat2", effect2) mesh.materials.append(mat1) mesh.materials.append(mat2) rotate = collada.scene.RotateTransform(0.1, 0.2, 0.3, 90) scale = collada.scene.ScaleTransform(0.1, 0.2, 0.3) mynode1 = collada.scene.Node('mynode1', children=[], transforms=[rotate, scale]) mynode2 = collada.scene.Node('mynode2', children=[], transforms=[]) mesh.nodes.append(mynode1) mesh.nodes.append(mynode2) geomnode = collada.scene.GeometryNode(geometry2) mynode3 = collada.scene.Node('mynode3', children=[geomnode], transforms=[]) mynode4 = collada.scene.Node('mynode4', children=[], transforms=[]) scene1 = collada.scene.Scene('myscene1', [mynode3]) scene2 = collada.scene.Scene('myscene2', [mynode4]) mesh.scenes.append(scene1) mesh.scenes.append(scene2) mesh.scene = scene1 out = BytesIO() mesh.write(out) toload = BytesIO(out.getvalue()) loaded_mesh = collada.Collada(toload, validate_output=True) self.assertEqual(len(loaded_mesh.geometries), 2) self.assertEqual(len(loaded_mesh.controllers), 0) self.assertEqual(len(loaded_mesh.lights), 2) self.assertEqual(len(loaded_mesh.cameras), 2) self.assertEqual(len(loaded_mesh.images), 2) self.assertEqual(len(loaded_mesh.effects), 2) self.assertEqual(len(loaded_mesh.materials), 2) self.assertEqual(len(loaded_mesh.nodes), 2) self.assertEqual(len(loaded_mesh.scenes), 2) self.assertEqual(loaded_mesh.scene.id, scene1.id) self.assertIn('geometry1', loaded_mesh.geometries) self.assertIn('geometry2', loaded_mesh.geometries) self.assertIn('mypointlight', loaded_mesh.lights) self.assertIn('myambientlight', loaded_mesh.lights) self.assertIn('mycam1', loaded_mesh.cameras) self.assertIn('mycam2', loaded_mesh.cameras) self.assertIn('mycimage1', loaded_mesh.images) self.assertIn('mycimage2', loaded_mesh.images) self.assertIn('myeffect1', loaded_mesh.effects) self.assertIn('myeffect2', loaded_mesh.effects) self.assertIn('mymaterial1', loaded_mesh.materials) self.assertIn('mymaterial2', loaded_mesh.materials) self.assertIn('mynode1', loaded_mesh.nodes) self.assertIn('mynode2', loaded_mesh.nodes) self.assertIn('myscene1', loaded_mesh.scenes) self.assertIn('myscene2', loaded_mesh.scenes) linefloatsrc2 = collada.source.FloatSource("mylinevertsource2", numpy.array(linefloats), ('X', 'Y', 'Z')) geometry3 = collada.geometry.Geometry(mesh, "geometry3", "mygeometry3", [linefloatsrc2]) loaded_mesh.geometries.pop(0) loaded_mesh.geometries.append(geometry3) dirlight = collada.light.DirectionalLight("mydirlight", (1, 1, 1)) loaded_mesh.lights.pop(0) loaded_mesh.lights.append(dirlight) camera3 = collada.camera.PerspectiveCamera("mycam3", 45.0, 0.01, 1000.0) loaded_mesh.cameras.pop(0) loaded_mesh.cameras.append(camera3) cimage3 = collada.material.CImage("mycimage3", "./whatever.tga", loaded_mesh) loaded_mesh.images.pop(0) loaded_mesh.images.append(cimage3) effect3 = collada.material.Effect("myeffect3", [], "phong") loaded_mesh.effects.pop(0) loaded_mesh.effects.append(effect3) mat3 = collada.material.Material("mymaterial3", "mymat3", effect3) loaded_mesh.materials.pop(0) loaded_mesh.materials.append(mat3) mynode5 = collada.scene.Node('mynode5', children=[], transforms=[]) loaded_mesh.nodes.pop(0) loaded_mesh.nodes.append(mynode5) mynode6 = collada.scene.Node('mynode6', children=[], transforms=[]) scene3 = collada.scene.Scene('myscene3', [mynode6]) loaded_mesh.scenes.pop(0) loaded_mesh.scenes.append(scene3) loaded_mesh.scene = scene3 loaded_mesh.save() strdata = tostring(loaded_mesh.xmlnode.getroot()) indata = BytesIO(strdata) loaded_mesh2 = collada.Collada(indata, validate_output=True) self.assertEqual(loaded_mesh2.scene.id, scene3.id) self.assertIn('geometry3', loaded_mesh2.geometries) self.assertIn('geometry2', loaded_mesh2.geometries) self.assertIn('mydirlight', loaded_mesh2.lights) self.assertIn('mypointlight', loaded_mesh2.lights) self.assertIn('mycam3', loaded_mesh2.cameras) self.assertIn('mycam2', loaded_mesh2.cameras) self.assertIn('mycimage3', loaded_mesh2.images) self.assertIn('mycimage2', loaded_mesh2.images) self.assertIn('myeffect3', loaded_mesh2.effects) self.assertIn('myeffect2', loaded_mesh2.effects) self.assertIn('mymaterial3', loaded_mesh2.materials) self.assertIn('mymaterial2', loaded_mesh2.materials) self.assertIn('mynode5', loaded_mesh2.nodes) self.assertIn('mynode2', loaded_mesh2.nodes) self.assertIn('myscene3', loaded_mesh2.scenes) self.assertIn('myscene2', loaded_mesh2.scenes)