Преглед на файлове

merge severin-lemaignan:for-upstream from github. This is a full rewrite of pyassimp, rendering it much easier to use.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1332 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg преди 12 години
родител
ревизия
4286c72e60

+ 0 - 66
port/PyAssimp/README

@@ -1,66 +0,0 @@
-	PyAssimp Readme
-	---------------
-
-
--- a simple Python wrapper for Assimp using ctypes to access
-the library. Tested for Python 2.6. Known not to work with
-Python 2.4.
-
-
-Note that pyassimp is by no means considered mature. It works,
-but it is far away from wrapping Assimp perfectly.
-
-
-USAGE
-=====
-
-To get started with pyAssimp, examine the sample.py script, which
-illustrates the basic usage. All Assimp data structures are
-wrapped using ctypes. All the data+length fields in Assimp's
-data structures (such as 'aiMesh::mNumVertices','aiMesh::mVertices')
-are replaced by simple python lists, so you can call len() on
-them to get their respective size and access members using
-[].
-
-For example, to load a file named 'hello.3ds' and print the first
-vertex of the first mesh, you would do (proper error handling
-substituted by assertions ...):
-
-> from pyassimp import pyassimp, errors
-> 
-> try:
-> 	scene = pyassimp.load('hello.3ds')
-> except AssimpError, msg:
->     print(msg)
->     return
-
-> assert len(scene.meshes)
-> mesh = scene.meshes[0]
-
-> assert len(mesh.vertices)
-> print(mesh.vertices[0])
-
-> # don't forget this one, or you will leak!
-> pyassimp.release(scene)
-
-
-INSTALL
-=======
-
-PyAssimp requires a assimp dynamic library (DLL on windows,
-so on linux :-) in order to work. The default search directories 
-are:
-
-- the current directory
-- on linux additionally: /usr/local/lib
-
-To build that library, refer to the Assimp master INSTALL
-instructions. To look in more places, edit ./pyassimp/helper.py.
-There's an 'additional_dirs' list waiting for your entries.
-
-
-
-
-
-
-	

+ 16 - 7
port/PyAssimp/gen/structsgen.py

@@ -41,7 +41,11 @@
 # ---------------------------------------------------------------------------
 
 """Update PyAssimp's data structures to keep up with the
-C/C++ headers."""
+C/C++ headers.
+
+This script is meant to be executed in the source tree, directly from
+port/PyAssimp/gen
+"""
 
 import os
 import re
@@ -96,7 +100,7 @@ def GetType(type, prefix='c_'):
            return None
 
     t = t.strip()
-    types = {'unsigned int':'uint', 'unsigned char':'ubyte', 'size_t':'uint',}
+    types = {'unsigned int':'uint', 'unsigned char':'ubyte',}
     if t in types:
         t = types[t]
     t = prefix + t
@@ -210,9 +214,11 @@ def Structify(fileName):
 
         # Restructure
         text = RErestruc.sub(restructure, text)
-
         # Replace comments
-        text = RErpcom.sub('#\g<line>', text)
+        text = RErpcom.sub('# \g<line>', text)
+        text = text.replace("),#", "),\n#")
+        text = text.replace("#", "\n#")
+        text = "".join([l for l in text.splitlines(True) if not l.strip().endswith("#")]) # remove empty comment lines
         
         # Whether it's selfreferencing: ex. struct Node { Node* parent; };
         selfreferencing = text.find('POINTER('+name+')') != -1
@@ -245,20 +251,21 @@ def Structify(fileName):
             text = text.replace('$DEFINES$', defines)
         else:
             text = text.replace('$DEFINES$', '')
+
         
         result.append((primitive, selfreferencing, complex, text))
              
     return result   
 
 text = "#-*- coding: UTF-8 -*-\n\n"
-text += "from ctypes import POINTER, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte\n\n"
+text += "from ctypes import POINTER, c_int, c_uint, c_size_t, c_char, c_float, Structure, c_char_p, c_double, c_ubyte\n\n"
 
 structs1 = ""
 structs2 = ""
 structs3 = ""
 structs4 = ""
 
-path = '../include/'
+path = '../../../include/assimp'
 files = os.listdir (path)
 #files = ["aiScene.h", "aiTypes.h"]
 for fileName in files:
@@ -276,6 +283,8 @@ for fileName in files:
 
 text += structs1 + structs2 + structs3 + structs4
 
-file = open('structs.txt', 'w')
+file = open('structs.py', 'w')
 file.write(text)
 file.close()
+
+print("Generation done. You can now review the file 'structs.py' and merge it.")

+ 0 - 1
port/PyAssimp/pyassimp/__init__.py

@@ -1 +0,0 @@
-#-*- coding: UTF-8 -*-

+ 46 - 9
port/PyAssimp/pyassimp/helper.py

@@ -6,17 +6,20 @@ Some fancy helper functions.
 
 import os
 import ctypes
-import structs
+from ctypes import POINTER
 import operator
+import numpy
 
-from errors import AssimpError
-from ctypes import POINTER
+import logging;logger = logging.getLogger("pyassimp")
+
+from .errors import AssimpError
 
 additional_dirs, ext_whitelist = [],[]
 
 # populate search directories and lists of allowed file extensions
 # depending on the platform we're running on.
 if os.name=='posix':
+    additional_dirs.append('/usr/lib/')
     additional_dirs.append('/usr/local/lib/')
 
     # note - this won't catch libassimp.so.N.n, but 
@@ -27,11 +30,43 @@ if os.name=='posix':
 elif os.name=='nt':
     ext_whitelist.append('.dll')
 
-print(additional_dirs)
+#print(additional_dirs)
 def vec2tuple(x):
     """ Converts a VECTOR3D to a Tuple """
     return (x.x, x.y, x.z)
 
+def transform(vector3, matrix4x4):
+    """ Apply a transformation matrix on a 3D vector.
+
+    :param vector3: a numpy array with 3 elements
+    :param matrix4x4: a numpy 4x4 matrix
+    """
+    return numpy.dot(matrix4x4, numpy.append(vector3, 1.))
+
+   
+def get_bounding_box(scene):
+    bb_min = [1e10, 1e10, 1e10] # x,y,z
+    bb_max = [-1e10, -1e10, -1e10] # x,y,z
+    return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max)
+
+def get_bounding_box_for_node(node, bb_min, bb_max):
+    for mesh in node.meshes:
+        for v in mesh.vertices:
+            v = transform(v, node.transformation)
+            bb_min[0] = min(bb_min[0], v[0])
+            bb_min[1] = min(bb_min[1], v[1])
+            bb_min[2] = min(bb_min[2], v[2])
+            bb_max[0] = max(bb_max[0], v[0])
+            bb_max[1] = max(bb_max[1], v[1])
+            bb_max[2] = max(bb_max[2], v[2])
+
+
+    for child in node.children:
+        bb_min, bb_max = get_bounding_box_for_node(child, bb_min, bb_max)
+
+    return bb_min, bb_max
+
+
 
 def try_load_functions(library,dll,candidates):
     """try to  functbind to aiImportFile and aiReleaseImport
@@ -54,7 +89,8 @@ def try_load_functions(library,dll,candidates):
         pass
     else:
         #Library found!
-        load.restype = POINTER(structs.Scene)
+        from .structs import Scene
+        load.restype = POINTER(Scene)
         
         candidates.append((library, load, release, dll))
 
@@ -88,10 +124,11 @@ def search_library():
                 continue
 
             library = os.path.join(curfolder, filename)
-            print 'Try ',library
+            logger.debug('Try ' + library)
             try:
                 dll = ctypes.cdll.LoadLibrary(library)
-            except:
+            except Exception as e:
+                logger.warning(str(e))
                 # OK, this except is evil. But different OSs will throw different
                 # errors. So just ignore any errors.
                 continue
@@ -100,12 +137,12 @@ def search_library():
     
     if not candidates:
         # no library found
-        raise AssimpError, "assimp library not found"
+        raise AssimpError("assimp library not found")
     else:
         # get the newest library
         candidates = map(lambda x: (os.lstat(x[0])[-2], x), candidates)
         res = max(candidates, key=operator.itemgetter(0))[1]
-        print 'Taking ',res[0]
+        logger.debug('Using assimp library located at ' + res[0])
 
         # XXX: if there are 1000 dll/so files containing 'assimp'
         # in their name, do we have all of them in our address

+ 0 - 276
port/PyAssimp/pyassimp/pyassimp.py

@@ -1,276 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-PyAssimp
-
-This is the main-module of PyAssimp.
-"""
-
-import sys
-if sys.version_info < (2,5):
-	raise 'pyassimp: need python 2.5 or newer'
-
-import structs
-import ctypes
-import os
-import helper
-from errors import AssimpError
-
-class aiArray:
-    """
-    A python class to 'safely' access C arrays.
-    For m<Name> and mNum<Name> assimp class members.
-    """
-    def __init__(self, instance, dataName, sizeName, i=None):
-        self.instance = instance
-        self.dataName = dataName
-        self.sizeName = sizeName
-        self.i = i
-        self.count = 0
-    
-    def _GetSize(self):
-        return getattr(self.instance, self.sizeName)
-        
-    def _GetData(self, index):
-        if self.i != None:
-            if not bool(getattr(self.instance, self.dataName)[self.i]):
-                return None
-            item = getattr(self.instance, self.dataName)[self.i][index]
-        else:
-            item = getattr(self.instance, self.dataName)[index]
-        if hasattr(item, 'contents'):
-            return item.contents._init()
-        elif hasattr(item, '_init'):
-            return item._init()
-        else:
-            return item
-        
-    def next(self):
-        if self.count >= self._GetSize():
-            self.count = 0
-            raise StopIteration
-        else:
-            c = self.count
-            self.count += 1
-            return self._GetData(c)
-            
-    def __getitem__(self, index):
-        if isinstance(index, slice):
-            indices = index.indices(len(self))
-            return [self.__getitem__(i) for i in range(*indices)]
-
-        if index < 0 or index >= self._GetSize():
-            raise IndexError("aiArray index out of range")
-        return self._GetData(index)
-        
-    def __iter__(self):
-        return self
-        
-    def __len__(self):
-        return int(self._GetSize())
-    
-    def __str__(self):
-        return str([x for x in self])
-        
-    def __repr__(self):
-        return str([x for x in self])
-        
-class aiTuple:
-    """
-    A python class to 'safely' access C structs in a python tuple fashion.
-    For C structs like vectors, matrices, colors, ...
-    """
-    def __init__(self, instance):
-        self.instance = instance
-        self.count = 0
-    
-    def _GetSize(self):
-        return len(self.instance._fields_)
-     
-    def _GetData(self, index):
-        return getattr(self.instance, self.instance._fields_[index][0])
-        
-    def next(self):
-        if self.count >= self._GetSize():
-            self.count = 0
-            raise StopIteration
-        else:
-            c = self.count
-            self.count += 1
-            return self._GetData(c)
-            
-    def __getitem__(self, index):
-        if isinstance(index, slice):
-            indices = index.indices(len(self))
-            return [self.__getitem__(i) for i in range(*indices)]
-            
-        if index < 0 or index >= self._GetSize():
-            raise IndexError("aiTuple index out of range")
-        return self._GetData(index)
-        
-    def __iter__(self):
-        return self
-        
-    def __len__(self):
-        return int(self._GetSize())
-        
-    def __str__(self):
-        return str([x for x in self])
-            
-    def __repr__(self):
-        return str([x for x in self])
-        
-def _init(self):
-    """
-    Custom initialize() for C structs, adds safely accessable member functionality.
-    """
-    if hasattr(self, '_is_init'):
-        return self
-    self._is_init = True
-
-    if str(self.__class__.__name__) == "MaterialProperty":
-        self.mKey._init()
-        
-    for m in self.__class__.__dict__.keys():
-        if m.startswith('mNum'):
-            name = m.split('mNum')[1]
-            if 'm'+name in self.__class__.__dict__.keys():
-                setattr(self.__class__, name.lower(), aiArray(self, 'm'+name , m))
-                if name.lower() == "vertices":
-                    setattr(self.__class__, "normals", aiArray(self, 'mNormals' , m))
-                    setattr(self.__class__, "tangents", aiArray(self, 'mTangents' , m))
-                    setattr(self.__class__, "bitangets", aiArray(self, 'mBitangents' , m))
-                    setattr(self.__class__, "colors", [aiArray(self, 'mColors' , m, o) for o in xrange(len(self.mColors))])
-                    setattr(self.__class__, "texcoords", [aiArray(self, 'mTextureCoords' , m, o) for o in xrange(len(self.mColors))])
-                
-        elif m == "x" or m == "a1" or m == "b": # Vector, matrix, quat, color
-            self._tuple = aiTuple(self)
-            setattr(self.__class__, '__getitem__', lambda x, y: x._tuple.__getitem__(y))
-            setattr(self.__class__, '__iter__', lambda x: x._tuple)
-            setattr(self.__class__, 'next', lambda x: x._tuple.next)
-            setattr(self.__class__, '__repr__', lambda x: str([c for c in x]))
-            break
-        elif m == "data": #String
-            setattr(self.__class__, '__repr__', lambda x: str(x.data))
-            setattr(self.__class__, '__str__', lambda x: str(x.data))
-            break
-            
-        if hasattr(getattr(self, m), '_init'):
-            getattr(self, m)._init()
-        
-    return self
-
-"""
-Python magic to add the _init() function to all C struct classes.
-"""
-for struct in dir(structs):
-    if not (struct.startswith('_') or struct.startswith('c_') or struct == "Structure" or struct == "POINTER") and not isinstance(getattr(structs, struct),int):
-        setattr(getattr(structs, struct), '_init', _init)
-
-
-class AssimpLib(object):
-    """
-    Assimp-Singleton
-    """
-    load, release, dll = helper.search_library()
-
-#the loader as singleton
-_assimp_lib = AssimpLib()
-
-
-def load(filename, processing=0):
-    """
-    Loads the model with some specific processing parameters.
-    
-    filename - file to load model from
-    processing - processing parameters
-    
-    result Scene-object with model-data
-    
-    throws AssimpError - could not open file
-    """
-    #read pure data
-    model = _assimp_lib.load(filename, processing)
-    if not model:
-        #Uhhh, something went wrong!
-        raise AssimpError, ("could not import file: %s" % filename)
-
-    return model.contents._init()
-
-def release(scene):
-    from ctypes import pointer
-    _assimp_lib.release(pointer(scene))
-    
-def aiGetMaterialFloatArray(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.Color4D()
-    max = c_uint(sizeof(structs.Color4D))
-    r=_assimp_lib.dll.aiGetMaterialFloatArray(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out), 
-                                            byref(max))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialFloatArray failed!")
-      
-    out._init()
-    return [out[i] for i in xrange(max.value)]
-    
-def aiGetMaterialString(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.String()
-    r=_assimp_lib.dll.aiGetMaterialString(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialString failed!")
-        
-    return str(out.data)
- 
-def GetMaterialProperties(material): 
-    """
-    Convenience Function to get the material properties as a dict
-    and values in a python format.
-    """
-    result = {}
-    #read all properties
-    for p in material.properties:
-        #the name
-        key = p.mKey.data
-
-        #the data
-        from ctypes import POINTER, cast, c_int, c_float, sizeof
-        if p.mType == 1:
-            arr = cast(p.mData, POINTER(c_float*(p.mDataLength/sizeof(c_float)) )).contents
-            value = [x for x in arr]
-        elif p.mType == 3: #string can't be an array
-            value = cast(p.mData, POINTER(structs.String)).contents.data
-        elif p.mType == 4:
-            arr = cast(p.mData, POINTER(c_int*(p.mDataLength/sizeof(c_int)) )).contents
-            value = [x for x in arr]
-        else:
-            value = p.mData[:p.mDataLength]
-
-        result[key] = value
-
-    return result
-    
-    
-def aiDecomposeMatrix(matrix):
-    if not isinstance(matrix, structs.Matrix4x4):
-        raise AssimpError("aiDecomposeMatrix failed: Not a aiMatrix4x4!")
-    
-    scaling = structs.Vector3D()
-    rotation = structs.Quaternion()
-    position = structs.Vector3D()
-    
-    from ctypes import byref, pointer
-    _assimp_lib.dll.aiDecomposeMatrix(pointer(matrix), byref(scaling), byref(rotation), byref(position))
-    return scaling._init(), rotation._init(), position._init()

+ 867 - 412
port/PyAssimp/pyassimp/structs.py

@@ -1,424 +1,879 @@
-#-*- coding: UTF-8 -*-
-
-from ctypes import POINTER, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t
-
-
-class Vector2D(Structure):
-    """
-    See 'aiVector2D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("x", c_float),("y", c_float),
-        ]
-
-class Texel(Structure):
-    """
-    See 'aiTexture.h' for details.
-    """ 
-
-    _fields_ = [
-            ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte),
-        ]
-
-class Plane(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Plane equation
-            ("a", c_float),("b", c_float),("c", c_float),("d", c_float),
-        ]
-
-class Color3D(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Red, green and blue color values
-            ("r", c_float),("g", c_float),("b", c_float),
-        ]
-
-class String(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
+#-*- coding: UTF-8 -*-
+
+from ctypes import POINTER, c_void_p, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t
+
+
+class Vector2D(Structure):
+    """
+    See 'aiVector2D.h' for details.
+    """ 
+
+
+    _fields_ = [
+            ("x", c_float),("y", c_float),
+        ]
+
+class Matrix3x3(Structure):
+    """
+    See 'aiMatrix3x3.h' for details.
+    """ 
+
+
+    _fields_ = [
+            ("a1", c_float),("a2", c_float),("a3", c_float),
+            ("b1", c_float),("b2", c_float),("b3", c_float),
+            ("c1", c_float),("c2", c_float),("c3", c_float),
+        ]
+
+class Texel(Structure):
+    """
+    See 'aiTexture.h' for details.
+    """ 
+
+    _fields_ = [
+            ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte),
+        ]
+
+class Color4D(Structure):
+    """
+    See 'aiColor4D.h' for details.
+    """ 
+
+
+    _fields_ = [
+            #  Red, green, blue and alpha color values
+            ("r", c_float),("g", c_float),("b", c_float),("a", c_float),
+        ]
+
+class Plane(Structure):
+    """
+    See 'aiTypes.h' for details.
+    """ 
+
+    _fields_ = [
+            #  Plane equation
+            ("a", c_float),("b", c_float),("c", c_float),("d", c_float),
+        ]
+
+class Color3D(Structure):
+    """
+    See 'aiTypes.h' for details.
+    """ 
+
+    _fields_ = [
+            #  Red, green and blue color values
+            ("r", c_float),("g", c_float),("b", c_float),
+        ]
+
+class String(Structure):
+    """
+    See 'aiTypes.h' for details.
+    """ 
+
     MAXLEN = 1024
-
-    _fields_ = [
-            #Binary length of the string excluding the terminal 0. This is NOT the# logical length of strings containing UTF-8 multibyte sequences! It's# the number of bytes from the beginning of the string to its end.#
-            ("length", c_size_t),#String buffer. Size limit is MAXLEN#
-            ("data", c_char*MAXLEN),
-        ]
-
-class MemoryInfo(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            #Storage allocated for texture data#
-            ("textures", c_uint),#Storage allocated for material data#
-            ("materials", c_uint),#Storage allocated for mesh data#
-            ("meshes", c_uint),#Storage allocated for node data#
-            ("nodes", c_uint),#Storage allocated for animation data#
-            ("animations", c_uint),#Storage allocated for camera data#
-            ("cameras", c_uint),#Storage allocated for light data#
-            ("lights", c_uint),#Total storage allocated for the full import.#
-            ("total", c_uint),
-        ]
-
-class Matrix3x3(Structure):
-    """
-    See 'aiMatrix3x3.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("a1", c_float),("a2", c_float),("a3", c_float),
-            ("b1", c_float),("b2", c_float),("b3", c_float),
-            ("c1", c_float),("c2", c_float),("c3", c_float),
-        ]
-
-class Color4D(Structure):
-    """
-    See 'aiColor4D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            # Red, green, blue and alpha color values
-            ("r", c_float),("g", c_float),("b", c_float),("a", c_float),
-        ]
-
-class ExportFormatDesc(Structure):
-    """
-    See 'export.h' for details.
-    """ 
-
-    _fields_ = [
-            # a short string ID to uniquely identify the export format. Use this ID string to# specify which file format you want to export to when calling aiExportScene().# Example: "dae" or "obj"
-            ("id", POINTER(c_char)),# A short description of the file format to present to users. Useful if you want# to allow the user to select an export format.
-            ("description", POINTER(c_char)),# Recommended file extension for the exported file in lower case.
-            ("fileExtension", POINTER(c_char)),
-        ]
-
-class Quaternion(Structure):
-    """
-    See 'aiQuaternion.h' for details.
-    """ 
-
-
-    _fields_ = [
-            # w,x,y,z components of the quaternion
-            ("w", c_float),("x", c_float),("y", c_float),("z", c_float),
-        ]
-
-class Vector3D(Structure):
-    """
-    See 'aiVector3D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("x", c_float),("y", c_float),("z", c_float),
-        ]
-
-class Face(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # Number of indices defining this face.# The maximum value for this member is #AI_MAX_FACE_INDICES.
-            ("mNumIndices", c_uint),# Pointer to the indices array. Size of the array is given in numIndices.
-            ("mIndices", POINTER(c_uint)),
-        ]
-
-class VertexWeight(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # Index of the vertex which is influenced by the bone.
-            ("mVertexId", c_uint),# The strength of the influence in the range (0...1).# The influence from all bones at one vertex amounts to 1.
-            ("mWeight", c_float),
-        ]
-
-class MeshKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#Index into the aiMesh::mAnimMeshes array of the# mesh coresponding to the #aiMeshAnim hosting this# key frame. The referenced anim mesh is evaluated# according to the rules defined in the docs for #aiAnimMesh.#
-            ("mValue", c_uint),
-        ]
-
-class Matrix4x4(Structure):
-    """
-    See 'aiMatrix4x4.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("a1", c_float),("a2", c_float),("a3", c_float),("a4", c_float),
-            ("b1", c_float),("b2", c_float),("b3", c_float),("b4", c_float),
-            ("c1", c_float),("c2", c_float),("c3", c_float),("c4", c_float),
-            ("d1", c_float),("d2", c_float),("d3", c_float),("d4", c_float),
-        ]
-
-class Node(Structure):
-    """
-    See 'aiScene.h' for details.
-    """ 
-
-
-Node._fields_ = [
-            #The name of the node.##The name might be empty (length of zero) but all nodes which#need to be accessed afterwards by bones or anims are usually named.#Multiple nodes may have the same name, but nodes which are accessed#by bones (see #aiBone and #aiMesh::mBones) *must* be unique.##Cameras and lights are assigned to a specific node name - if there#are multiple nodes with this name, they're assigned to each of them.#<br>#There are no limitations regarding the characters contained in#this text. You should be able to handle stuff like whitespace, tabs,#linefeeds, quotation marks, ampersands, ... .#
-            ("mName", String),#The transformation relative to the node's parent.#
-            ("mTransformation", Matrix4x4),#Parent node. NULL if this node is the root node.#
-            ("mParent", POINTER(Node)),#The number of child nodes of this node.#
-            ("mNumChildren", c_uint),#The child nodes of this node. NULL if mNumChildren is 0.#
-            ("mChildren", POINTER(POINTER(Node))),#The number of meshes of this node.#
-            ("mNumMeshes", c_uint),#The meshes of this node. Each entry is an index into the mesh#
-            ("mMeshes", POINTER(c_uint)),
-        ]
-
-class Camera(Structure):
-    """
-    See 'aiCamera.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #The name of the camera.## There must be a node in the scenegraph with the same name.# This node specifies the position of the camera in the scene# hierarchy and can be animated.#
-            ("mName", String),#Position of the camera relative to the coordinate space# defined by the corresponding node.## The default value is 0|0|0.#
-            ("mPosition", Vector3D),#'Up' - vector of the camera coordinate system relative to# the coordinate space defined by the corresponding node.## The 'right' vector of the camera coordinate system is# the cross product of  the up and lookAt vectors.# The default value is 0|1|0. The vector# may be normalized, but it needn't.#
-            ("mUp", Vector3D),#'LookAt' - vector of the camera coordinate system relative to# the coordinate space defined by the corresponding node.## This is the viewing direction of the user.# The default value is 0|0|1. The vector# may be normalized, but it needn't.#
-            ("mLookAt", Vector3D),#Half horizontal field of view angle, in radians.## The field of view angle is the angle between the center# line of the screen and the left or right border.# The default value is 1/4PI.#
-            ("mHorizontalFOV", c_float),#Distance of the near clipping plane from the camera.##The value may not be 0.f (for arithmetic reasons to prevent#a division through zero). The default value is 0.1f.#
-            ("mClipPlaneNear", c_float),#Distance of the far clipping plane from the camera.##The far clipping plane must, of course, be further away than the#near clipping plane. The default value is 1000.f. The ratio#between the near and the far plane should not be too#large (between 1000-10000 should be ok) to avoid floating-point#inaccuracies which could lead to z-fighting.#
-            ("mClipPlaneFar", c_float),#Screen aspect ratio.##This is the ration between the width and the height of the#screen. Typical values are 4/3, 1/2 or 1/1. This value is#0 if the aspect ratio is not defined in the source file.#0 is also the default value.#
-            ("mAspect", c_float),
-        ]
-
-class Texture(Structure):
-    """
-    See 'aiTexture.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #Width of the texture, in pixels##If mHeight is zero the texture is compressed in a format#like JPEG. In this case mWidth specifies the size of the#memory area pcData is pointing to, in bytes.#
-            ("mWidth", c_uint),#Height of the texture, in pixels##If this value is zero, pcData points to an compressed texture#in any format (e.g. JPEG).#
-            ("mHeight", c_uint),#A hint from the loader to make it easier for applications# to determine the type of embedded compressed textures.##If mHeight != 0 this member is undefined. Otherwise it#is set set to '\\0\\0\\0\\0' if the loader has no additional#information about the texture file format used OR the#file extension of the format without a trailing dot. If there#are multiple file extensions for a format, the shortest#extension is chosen (JPEG maps to 'jpg', not to 'jpeg').#E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'.  All characters are lower-case.#The fourth character will always be '\\0'.#
-            ("achFormatHint", c_char*4),#Data of the texture.##Points to an array of mWidth#mHeight aiTexel's.#The format of the texture data is always ARGB8888 to#make the implementation for user of the library as easy#as possible. If mHeight = 0 this is a pointer to a memory#buffer of size mWidth containing the compressed texture#data. Good luck, have fun!#
-            ("pcData", POINTER(Texel)),
-        ]
-
-class Ray(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Position and direction of the ray
-            ("pos", Vector3D),("dir", Vector3D),
-        ]
-
-class Light(Structure):
-    """
-    See 'aiLight.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #The name of the light source.## There must be a node in the scenegraph with the same name.# This node specifies the position of the light in the scene# hierarchy and can be animated.#
-            ("mName", String),#The type of the light source.##aiLightSource_UNDEFINED is not a valid value for this member.#
-            ("mType", c_uint),#Position of the light source in space. Relative to the# transformation of the node corresponding to the light.## The position is undefined for directional lights.#
-            ("mPosition", Vector3D),#Direction of the light source in space. Relative to the# transformation of the node corresponding to the light.## The direction is undefined for point lights. The vector# may be normalized, but it needn't.#
-            ("mDirection", Vector3D),#Constant light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att0 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationConstant", c_float),#Linear light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att1 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationLinear", c_float),#Quadratic light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att2 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationQuadratic", c_float),#Diffuse color of the light source## The diffuse light color is multiplied with the diffuse# material color to obtain the final color that contributes# to the diffuse shading term.#
-            ("mColorDiffuse", Color3D),#Specular color of the light source## The specular light color is multiplied with the specular# material color to obtain the final color that contributes# to the specular shading term.#
-            ("mColorSpecular", Color3D),#Ambient color of the light source## The ambient light color is multiplied with the ambient# material color to obtain the final color that contributes# to the ambient shading term. Most renderers will ignore# this value it, is just a remaining of the fixed-function pipeline# that is still supported by quite many file formats.#
-            ("mColorAmbient", Color3D),#Inner angle of a spot light's light cone.## The spot light has maximum influence on objects inside this# angle. The angle is given in radians. It is 2PI for point# lights and undefined for directional lights.#
-            ("mAngleInnerCone", c_float),#Outer angle of a spot light's light cone.## The spot light does not affect objects outside this angle.# The angle is given in radians. It is 2PI for point lights and# undefined for directional lights. The outer angle must be# greater than or equal to the inner angle.# It is assumed that the application uses a smooth# interpolation between the inner and the outer cone of the# spot light.#
-            ("mAngleOuterCone", c_float),
-        ]
-
-class Bone(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # The name of the bone.
-            ("mName", String),# The number of vertices affected by this bone# The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
-            ("mNumWeights", c_uint),# The vertices affected by this bone
-            ("mWeights", POINTER(VertexWeight)),# Matrix that transforms from mesh space to bone space in bind pose
-            ("mOffsetMatrix", Matrix4x4),
-        ]
-
-class Mesh(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
+
+    _fields_ = [
+            # Binary length of the string excluding the terminal 0. This is NOT the
+            #  logical length of strings containing UTF-8 multibyte sequences! It's
+            #  the number of bytes from the beginning of the string to its end.
+            ("length", c_size_t),
+            
+            # String buffer. Size limit is MAXLEN
+            ("data", c_char*MAXLEN),
+        ]
+
+class MemoryInfo(Structure):
+    """
+    See 'aiTypes.h' for details.
+    """ 
+
+    _fields_ = [
+            # Storage allocated for texture data
+            ("textures", c_uint),
+            
+            # Storage allocated for material data
+            ("materials", c_uint),
+            
+            # Storage allocated for mesh data
+            ("meshes", c_uint),
+            
+            # Storage allocated for node data
+            ("nodes", c_uint),
+            
+            # Storage allocated for animation data
+            ("animations", c_uint),
+            
+            # Storage allocated for camera data
+            ("cameras", c_uint),
+            
+            # Storage allocated for light data
+            ("lights", c_uint),
+            
+            # Total storage allocated for the full import.
+            ("total", c_uint),
+        ]
+
+class Quaternion(Structure):
+    """
+    See 'aiQuaternion.h' for details.
+    """ 
+
+
+    _fields_ = [
+            #  w,x,y,z components of the quaternion
+            ("w", c_float),("x", c_float),("y", c_float),("z", c_float),
+        ]
+
+class Face(Structure):
+    """
+    See 'aiMesh.h' for details.
+    """ 
+
+    _fields_ = [
+            #  Number of indices defining this face.
+            #  The maximum value for this member is
+            #AI_MAX_FACE_INDICES.
+            ("mNumIndices", c_uint),
+            
+            #  Pointer to the indices array. Size of the array is given in numIndices.
+            ("mIndices", POINTER(c_uint)),
+        ]
+
+class VertexWeight(Structure):
+    """
+    See 'aiMesh.h' for details.
+    """ 
+
+    _fields_ = [
+            #  Index of the vertex which is influenced by the bone.
+            ("mVertexId", c_uint),
+            
+            #  The strength of the influence in the range (0...1).
+            #  The influence from all bones at one vertex amounts to 1.
+            ("mWeight", c_float),
+        ]
+
+class Matrix4x4(Structure):
+    """
+    See 'aiMatrix4x4.h' for details.
+    """ 
+
+
+    _fields_ = [
+            ("a1", c_float),("a2", c_float),("a3", c_float),("a4", c_float),
+            ("b1", c_float),("b2", c_float),("b3", c_float),("b4", c_float),
+            ("c1", c_float),("c2", c_float),("c3", c_float),("c4", c_float),
+            ("d1", c_float),("d2", c_float),("d3", c_float),("d4", c_float),
+        ]
+
+class Vector3D(Structure):
+    """
+    See 'aiVector3D.h' for details.
+    """ 
+
+
+    _fields_ = [
+            ("x", c_float),("y", c_float),("z", c_float),
+        ]
+
+class MeshKey(Structure):
+    """
+    See 'aiAnim.h' for details.
+    """ 
+
+    _fields_ = [
+            # The time of this key
+            ("mTime", c_double),
+            
+            # Index into the aiMesh::mAnimMeshes array of the
+            #  mesh coresponding to the
+            #aiMeshAnim hosting this
+            #  key frame. The referenced anim mesh is evaluated
+            #  according to the rules defined in the docs for
+            #aiAnimMesh.
+            ("mValue", c_uint),
+        ]
+
+class Node(Structure):
+    """
+    See 'aiScene.h' for details.
+    """ 
+
+
+Node._fields_ = [
+            # The name of the node.
+            # The name might be empty (length of zero) but all nodes which
+            # need to be accessed afterwards by bones or anims are usually named.
+            # Multiple nodes may have the same name, but nodes which are accessed
+            # by bones (see
+            #aiBone and
+            #aiMesh::mBones) *must* be unique.
+            # Cameras and lights are assigned to a specific node name - if there
+            # are multiple nodes with this name, they're assigned to each of them.
+            # <br>
+            # There are no limitations regarding the characters contained in
+            # this text. You should be able to handle stuff like whitespace, tabs,
+            # linefeeds, quotation marks, ampersands, ... .
+            ("mName", String),
+            
+            # The transformation relative to the node's parent.
+            ("mTransformation", Matrix4x4),
+            
+            # Parent node. NULL if this node is the root node.
+            ("mParent", POINTER(Node)),
+            
+            # The number of child nodes of this node.
+            ("mNumChildren", c_uint),
+            
+            # The child nodes of this node. NULL if mNumChildren is 0.
+            ("mChildren", POINTER(POINTER(Node))),
+            
+            # The number of meshes of this node.
+            ("mNumMeshes", c_uint),
+            
+            # The meshes of this node. Each entry is an index into the mesh
+            ("mMeshes", POINTER(c_uint)),
+        ]
+
+class Light(Structure):
+    """
+    See 'aiLight.h' for details.
+    """ 
+
+
+    _fields_ = [
+            # The name of the light source.
+            #  There must be a node in the scenegraph with the same name.
+            #  This node specifies the position of the light in the scene
+            #  hierarchy and can be animated.
+            ("mName", String),
+            
+            # The type of the light source.
+            # aiLightSource_UNDEFINED is not a valid value for this member.
+            ("mType", c_uint),
+            
+            # Position of the light source in space. Relative to the
+            #  transformation of the node corresponding to the light.
+            #  The position is undefined for directional lights.
+            ("mPosition", Vector3D),
+            
+            # Direction of the light source in space. Relative to the
+            #  transformation of the node corresponding to the light.
+            #  The direction is undefined for point lights. The vector
+            #  may be normalized, but it needn't.
+            ("mDirection", Vector3D),
+            
+            # Constant light attenuation factor.
+            #  The intensity of the light source at a given distance 'd' from
+            #  the light's position is
+            #  @code
+            #  Atten = 1/( att0 + att1
+            # d + att2
+            # d*d)
+            #  @endcode
+            #  This member corresponds to the att0 variable in the equation.
+            #  Naturally undefined for directional lights.
+            ("mAttenuationConstant", c_float),
+            
+            # Linear light attenuation factor.
+            #  The intensity of the light source at a given distance 'd' from
+            #  the light's position is
+            #  @code
+            #  Atten = 1/( att0 + att1
+            # d + att2
+            # d*d)
+            #  @endcode
+            #  This member corresponds to the att1 variable in the equation.
+            #  Naturally undefined for directional lights.
+            ("mAttenuationLinear", c_float),
+            
+            # Quadratic light attenuation factor.
+            #  The intensity of the light source at a given distance 'd' from
+            #  the light's position is
+            #  @code
+            #  Atten = 1/( att0 + att1
+            # d + att2
+            # d*d)
+            #  @endcode
+            #  This member corresponds to the att2 variable in the equation.
+            #  Naturally undefined for directional lights.
+            ("mAttenuationQuadratic", c_float),
+            
+            # Diffuse color of the light source
+            #  The diffuse light color is multiplied with the diffuse
+            #  material color to obtain the final color that contributes
+            #  to the diffuse shading term.
+            ("mColorDiffuse", Color3D),
+            
+            # Specular color of the light source
+            #  The specular light color is multiplied with the specular
+            #  material color to obtain the final color that contributes
+            #  to the specular shading term.
+            ("mColorSpecular", Color3D),
+            
+            # Ambient color of the light source
+            #  The ambient light color is multiplied with the ambient
+            #  material color to obtain the final color that contributes
+            #  to the ambient shading term. Most renderers will ignore
+            #  this value it, is just a remaining of the fixed-function pipeline
+            #  that is still supported by quite many file formats.
+            ("mColorAmbient", Color3D),
+            
+            # Inner angle of a spot light's light cone.
+            #  The spot light has maximum influence on objects inside this
+            #  angle. The angle is given in radians. It is 2PI for point
+            #  lights and undefined for directional lights.
+            ("mAngleInnerCone", c_float),
+            
+            # Outer angle of a spot light's light cone.
+            #  The spot light does not affect objects outside this angle.
+            #  The angle is given in radians. It is 2PI for point lights and
+            #  undefined for directional lights. The outer angle must be
+            #  greater than or equal to the inner angle.
+            #  It is assumed that the application uses a smooth
+            #  interpolation between the inner and the outer cone of the
+            #  spot light.
+            ("mAngleOuterCone", c_float),
+        ]
+
+class Texture(Structure):
+    """
+    See 'aiTexture.h' for details.
+    """ 
+
+
+    _fields_ = [
+            # Width of the texture, in pixels
+            # If mHeight is zero the texture is compressed in a format
+            # like JPEG. In this case mWidth specifies the size of the
+            # memory area pcData is pointing to, in bytes.
+            ("mWidth", c_uint),
+            
+            # Height of the texture, in pixels
+            # If this value is zero, pcData points to an compressed texture
+            # in any format (e.g. JPEG).
+            ("mHeight", c_uint),
+            
+            # A hint from the loader to make it easier for applications
+            #  to determine the type of embedded compressed textures.
+            # If mHeight != 0 this member is undefined. Otherwise it
+            # is set set to '\\0\\0\\0\\0' if the loader has no additional
+            # information about the texture file format used OR the
+            # file extension of the format without a trailing dot. If there
+            # are multiple file extensions for a format, the shortest
+            # extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
+            # E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'.  All characters are lower-case.
+            # The fourth character will always be '\\0'.
+            ("achFormatHint", c_char*4),
+            
+            # Data of the texture.
+            # Points to an array of mWidth
+            # mHeight aiTexel's.
+            # The format of the texture data is always ARGB8888 to
+            # make the implementation for user of the library as easy
+            # as possible. If mHeight = 0 this is a pointer to a memory
+            # buffer of size mWidth containing the compressed texture
+            # data. Good luck, have fun!
+            ("pcData", POINTER(Texel)),
+        ]
+
+class Ray(Structure):
+    """
+    See 'aiTypes.h' for details.
+    """ 
+
+    _fields_ = [
+            #  Position and direction of the ray
+            ("pos", Vector3D),("dir", Vector3D),
+        ]
+
+class UVTransform(Structure):
+    """
+    See 'aiMaterial.h' for details.
+    """ 
+
+    _fields_ = [
+            # Translation on the u and v axes.
+            #  The default value is (0|0).
+            ("mTranslation", Vector2D),
+            
+            # Scaling on the u and v axes.
+            #  The default value is (1|1).
+            ("mScaling", Vector2D),
+            
+            # Rotation - in counter-clockwise direction.
+            #  The rotation angle is specified in radians. The
+            #  rotation center is 0.5f|0.5f. The default value
+            #  0.f.
+            ("mRotation", c_float),
+        ]
+
+class MaterialProperty(Structure):
+    """
+    See 'aiMaterial.h' for details.
+    """ 
+
+    _fields_ = [
+            # Specifies the name of the property (key)
+            #  Keys are generally case insensitive.
+            ("mKey", String),
+            
+            # Textures: Specifies their exact usage semantic.
+            # For non-texture properties, this member is always 0
+            # (or, better-said,
+            #aiTextureType_NONE).
+            ("mSemantic", c_uint),
+            
+            # Textures: Specifies the index of the texture.
+            #  For non-texture properties, this member is always 0.
+            ("mIndex", c_uint),
+            
+            # Size of the buffer mData is pointing to, in bytes.
+            #  This value may not be 0.
+            ("mDataLength", c_uint),
+            
+            # Type information for the property.
+            # Defines the data layout inside the data buffer. This is used
+            # by the library internally to perform debug checks and to
+            # utilize proper type conversions.
+            # (It's probably a hacky solution, but it works.)
+            ("mType", c_uint),
+            
+            # Binary buffer to hold the property's value.
+            # The size of the buffer is always mDataLength.
+            ("mData", POINTER(c_char)),
+        ]
+
+class Material(Structure):
+    """
+    See 'aiMaterial.h' for details.
+    """ 
+
+    _fields_ = [
+            # List of all material properties loaded.
+            ("mProperties", POINTER(POINTER(MaterialProperty))),
+            
+            # Number of properties in the data base
+            ("mNumProperties", c_uint),
+            
+            # Storage allocated
+            ("mNumAllocated", c_uint),
+        ]
+
+class Bone(Structure):
+    """
+    See 'aiMesh.h' for details.
+    """ 
+
+    _fields_ = [
+            #  The name of the bone.
+            ("mName", String),
+            
+            #  The number of vertices affected by this bone
+            #  The maximum value for this member is
+            #AI_MAX_BONE_WEIGHTS.
+            ("mNumWeights", c_uint),
+            
+            #  The vertices affected by this bone
+            ("mWeights", POINTER(VertexWeight)),
+            
+            #  Matrix that transforms from mesh space to bone space in bind pose
+            ("mOffsetMatrix", Matrix4x4),
+        ]
+
+class Mesh(Structure):
+    """
+    See 'aiMesh.h' for details.
+    """ 
+
     AI_MAX_FACE_INDICES = 0x7fff
     AI_MAX_BONE_WEIGHTS = 0x7fffffff
     AI_MAX_VERTICES = 0x7fffffff
     AI_MAX_FACES = 0x7fffffff
     AI_MAX_NUMBER_OF_COLOR_SETS = 0x8
     AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8
-
-    _fields_ = [
-            #Bitwise combination of the members of the #aiPrimitiveType enum.#This specifies which types of primitives are present in the mesh.#The "SortByPrimitiveType"-Step can be used to make sure the#output meshes consist of one primitive type each.#
-            ("mPrimitiveTypes", c_uint),#The number of vertices in this mesh.#This is also the size of all of the per-vertex data arrays.#The maximum value for this member is #AI_MAX_VERTICES.#
-            ("mNumVertices", c_uint),#The number of primitives (triangles, polygons, lines) in this  mesh.#This is also the size of the mFaces array.#The maximum value for this member is #AI_MAX_FACES.#
-            ("mNumFaces", c_uint),#Vertex positions.#This array is always present in a mesh. The array is#mNumVertices in size.#
-            ("mVertices", POINTER(Vector3D)),#Vertex normals.#The array contains normalized vectors, NULL if not present.#The array is mNumVertices in size. Normals are undefined for#point and line primitives. A mesh consisting of points and#lines only may not have normal vectors. Meshes with mixed#primitive types (i.e. lines and triangles) may have normals,#but the normals for vertices that are only referenced by#point or line primitives are undefined and set to QNaN (WARN:#qNaN compares to inequal to *everything*, even to qNaN itself.#Using code like this to check whether a field is qnan is:#@code##define IS_QNAN(f) (f != f)#@endcode#still dangerous because even 1.f == 1.f could evaluate to false! (#remember the subtleties of IEEE754 artithmetics). Use stuff like#@c fpclassify instead.#@note Normal vectors computed by Assimp are always unit-length.#However, this needn't apply for normals that have been taken#  directly from the model file.#
-            ("mNormals", POINTER(Vector3D)),#Vertex tangents.#The tangent of a vertex points in the direction of the positive#X texture axis. The array contains normalized vectors, NULL if#not present. The array is mNumVertices in size. A mesh consisting#of points and lines only may not have normal vectors. Meshes with#mixed primitive types (i.e. lines and triangles) may have#normals, but the normals for vertices that are only referenced by#point or line primitives are undefined and set to qNaN.  See#the #mNormals member for a detailled discussion of qNaNs.#@note If the mesh contains tangents, it automatically also#contains bitangents.#
-            ("mTangents", POINTER(Vector3D)),#Vertex bitangents.#The bitangent of a vertex points in the direction of the positive#Y texture axis. The array contains normalized vectors, NULL if not#present. The array is mNumVertices in size.#@note If the mesh contains tangents, it automatically also contains#bitangents.#
-            ("mBitangents", POINTER(Vector3D)),#Vertex color sets.#A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex#colors per vertex. NULL if not present. Each array is#mNumVertices in size if present.#
-            ("mColors", POINTER(Color4D)*AI_MAX_NUMBER_OF_COLOR_SETS),#Vertex texture coords, also known as UV channels.#A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per#vertex. NULL if not present. The array is mNumVertices in size.#
-            ("mTextureCoords", POINTER(Vector3D)*AI_MAX_NUMBER_OF_TEXTURECOORDS),#Specifies the number of components for a given UV channel.#Up to three channels are supported (UVW, for accessing volume#or cube maps). If the value is 2 for a given channel n, the#component p.z of mTextureCoords[n][p] is set to 0.0f.#If the value is 1 for a given channel, p.y is set to 0.0f, too.#@note 4D coords are not supported#
-            ("mNumUVComponents", c_uint*AI_MAX_NUMBER_OF_TEXTURECOORDS),#The faces the mesh is constructed from.#Each face refers to a number of vertices by their indices.#This array is always present in a mesh, its size is given#in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT#is NOT set each face references an unique set of vertices.#
-            ("mFaces", POINTER(Face)),#The number of bones this mesh contains.#Can be 0, in which case the mBones array is NULL.#
-            ("mNumBones", c_uint),#The bones of this mesh.#A bone consists of a name by which it can be found in the#frame hierarchy and a set of vertex weights.#
-            ("mBones", POINTER(POINTER(Bone))),#The material used by this mesh.#A mesh does use only a single material. If an imported model uses#multiple materials, the import splits up the mesh. Use this value#as index into the scene's material list.#
-            ("mMaterialIndex", c_uint),#Name of the mesh. Meshes can be named, but this is not a# requirement and leaving this field empty is totally fine.# There are mainly three uses for mesh names:#  - some formats name nodes and meshes independently.#  - importers tend to split meshes up to meet the#     one-material-per-mesh requirement. Assigning#     the same (dummy) name to each of the result meshes#     aids the caller at recovering the original mesh#     partitioning.#  - Vertex animations refer to meshes by their names.#
-            ("mName", String),#NOT CURRENTLY IN USE. The number of attachment meshes#
-            ("mNumAnimMeshes", c_uint),#NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-based animation.# Attachment meshes carry replacement data for some of the# mesh'es vertex components (usually positions, normals).#
-        ]
-
-class VectorKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#The value of this key#
-            ("mValue", Vector3D),
-        ]
-
-class QuatKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#The value of this key#
-            ("mValue", Quaternion),
-        ]
-
-class NodeAnim(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The name of the node affected by this animation. The node# must exist and it must be unique.#
-            ("mNodeName", String),#The number of position keys#
-            ("mNumPositionKeys", c_uint),#The position keys of this animation channel. Positions are#specified as 3D vector. The array is mNumPositionKeys in size.##If there are position keys, there will also be at least one#scaling and one rotation key.#
-            ("mPositionKeys", POINTER(VectorKey)),#The number of rotation keys#
-            ("mNumRotationKeys", c_uint),#The rotation keys of this animation channel. Rotations are# given as quaternions,  which are 4D vectors. The array is# mNumRotationKeys in size.##If there are rotation keys, there will also be at least one#scaling and one position key.#
-            ("mRotationKeys", POINTER(QuatKey)),#The number of scaling keys#
-            ("mNumScalingKeys", c_uint),#The scaling keys of this animation channel. Scalings are# specified as 3D vector. The array is mNumScalingKeys in size.##If there are scaling keys, there will also be at least one#position and one rotation key.#
-            ("mScalingKeys", POINTER(VectorKey)),#Defines how the animation behaves before the first# key is encountered.## The default value is aiAnimBehaviour_DEFAULT (the original# transformation matrix of the affected node is used).#
-            ("mPreState", c_uint),#Defines how the animation behaves after the last# key was processed.## The default value is aiAnimBehaviour_DEFAULT (the original# transformation matrix of the affected node is taken).#
-            ("mPostState", c_uint),
-        ]
-
-class Animation(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The name of the animation. If the modeling package this data was# exported from does support only a single animation channel, this# name is usually empty (length is zero).#
-            ("mName", String),#Duration of the animation in ticks.#
-            ("mDuration", c_double),#Ticks per second. 0 if not specified in the imported file#
-            ("mTicksPerSecond", c_double),#The number of bone animation channels. Each channel affects# a single node.#
-            ("mNumChannels", c_uint),#The node animation channels. Each channel affects a single node.# The array is mNumChannels in size.#
-            ("mChannels", POINTER(POINTER(NodeAnim))),#The number of mesh animation channels. Each channel affects# a single mesh and defines vertex-based animation.#
-            ("mNumMeshChannels", c_uint),#The mesh animation channels. Each channel affects a single mesh.# The array is mNumMeshChannels in size.#
-        ]
-
-class UVTransform(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #Translation on the u and v axes.## The default value is (0|0).#
-            ("mTranslation", Vector2D),#Scaling on the u and v axes.## The default value is (1|1).#
-            ("mScaling", Vector2D),#Rotation - in counter-clockwise direction.## The rotation angle is specified in radians. The# rotation center is 0.5f|0.5f. The default value# 0.f.#
-            ("mRotation", c_float),
-        ]
-
-class MaterialProperty(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #Specifies the name of the property (key)# Keys are generally case insensitive.#
-            ("mKey", String),#Textures: Specifies their exact usage semantic.#For non-texture properties, this member is always 0#(or, better-said, #aiTextureType_NONE).#
-            ("mSemantic", c_uint),#Textures: Specifies the index of the texture.# For non-texture properties, this member is always 0.#
-            ("mIndex", c_uint),#Size of the buffer mData is pointing to, in bytes.# This value may not be 0.#
-            ("mDataLength", c_uint),#Type information for the property.##Defines the data layout inside the data buffer. This is used#by the library internally to perform debug checks and to#utilize proper type conversions.#(It's probably a hacky solution, but it works.)#
-            ("mType", c_uint),#Binary buffer to hold the property's value.#The size of the buffer is always mDataLength.#
-            ("mData", POINTER(c_char)),
-        ]
-
-class Material(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #List of all material properties loaded.#
-            ("mProperties", POINTER(POINTER(MaterialProperty))),#Number of properties in the data base#
-            ("mNumProperties", c_uint),#Storage allocated#
-            ("mNumAllocated", c_uint),
-        ]
-
-class Scene(Structure):
-    """
-    See 'aiScene.h' for details.
-    """ 
-
+
+    _fields_ = [
+            # Bitwise combination of the members of the
+            #aiPrimitiveType enum.
+            # This specifies which types of primitives are present in the mesh.
+            # The "SortByPrimitiveType"-Step can be used to make sure the
+            # output meshes consist of one primitive type each.
+            ("mPrimitiveTypes", c_uint),
+            
+            # The number of vertices in this mesh.
+            # This is also the size of all of the per-vertex data arrays.
+            # The maximum value for this member is
+            #AI_MAX_VERTICES.
+            ("mNumVertices", c_uint),
+            
+            # The number of primitives (triangles, polygons, lines) in this  mesh.
+            # This is also the size of the mFaces array.
+            # The maximum value for this member is
+            #AI_MAX_FACES.
+            ("mNumFaces", c_uint),
+            
+            # Vertex positions.
+            # This array is always present in a mesh. The array is
+            # mNumVertices in size.
+            ("mVertices", POINTER(Vector3D)),
+            
+            # Vertex normals.
+            # The array contains normalized vectors, NULL if not present.
+            # The array is mNumVertices in size. Normals are undefined for
+            # point and line primitives. A mesh consisting of points and
+            # lines only may not have normal vectors. Meshes with mixed
+            # primitive types (i.e. lines and triangles) may have normals,
+            # but the normals for vertices that are only referenced by
+            # point or line primitives are undefined and set to QNaN (WARN:
+            # qNaN compares to inequal to *everything*, even to qNaN itself.
+            # Using code like this to check whether a field is qnan is:
+            # @code
+            #define IS_QNAN(f) (f != f)
+            # @endcode
+            # still dangerous because even 1.f == 1.f could evaluate to false! (
+            # remember the subtleties of IEEE754 artithmetics). Use stuff like
+            # @c fpclassify instead.
+            # @note Normal vectors computed by Assimp are always unit-length.
+            # However, this needn't apply for normals that have been taken
+            #   directly from the model file.
+            ("mNormals", POINTER(Vector3D)),
+            
+            # Vertex tangents.
+            # The tangent of a vertex points in the direction of the positive
+            # X texture axis. The array contains normalized vectors, NULL if
+            # not present. The array is mNumVertices in size. A mesh consisting
+            # of points and lines only may not have normal vectors. Meshes with
+            # mixed primitive types (i.e. lines and triangles) may have
+            # normals, but the normals for vertices that are only referenced by
+            # point or line primitives are undefined and set to qNaN.  See
+            # the
+            #mNormals member for a detailled discussion of qNaNs.
+            # @note If the mesh contains tangents, it automatically also
+            # contains bitangents (the bitangent is just the cross product of
+            # tangent and normal vectors).
+            ("mTangents", POINTER(Vector3D)),
+            
+            # Vertex bitangents.
+            # The bitangent of a vertex points in the direction of the positive
+            # Y texture axis. The array contains normalized vectors, NULL if not
+            # present. The array is mNumVertices in size.
+            # @note If the mesh contains tangents, it automatically also contains
+            # bitangents.
+            ("mBitangents", POINTER(Vector3D)),
+            
+            # Vertex color sets.
+            # A mesh may contain 0 to
+            #AI_MAX_NUMBER_OF_COLOR_SETS vertex
+            # colors per vertex. NULL if not present. Each array is
+            # mNumVertices in size if present.
+            ("mColors", POINTER(Color4D)*AI_MAX_NUMBER_OF_COLOR_SETS),
+            
+            # Vertex texture coords, also known as UV channels.
+            # A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
+            # vertex. NULL if not present. The array is mNumVertices in size.
+            ("mTextureCoords", POINTER(Vector3D)*AI_MAX_NUMBER_OF_TEXTURECOORDS),
+            
+            # Specifies the number of components for a given UV channel.
+            # Up to three channels are supported (UVW, for accessing volume
+            # or cube maps). If the value is 2 for a given channel n, the
+            # component p.z of mTextureCoords[n][p] is set to 0.0f.
+            # If the value is 1 for a given channel, p.y is set to 0.0f, too.
+            # @note 4D coords are not supported
+            ("mNumUVComponents", c_uint*AI_MAX_NUMBER_OF_TEXTURECOORDS),
+            
+            # The faces the mesh is constructed from.
+            # Each face refers to a number of vertices by their indices.
+            # This array is always present in a mesh, its size is given
+            # in mNumFaces. If the
+            #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
+            # is NOT set each face references an unique set of vertices.
+            ("mFaces", POINTER(Face)),
+            
+            # The number of bones this mesh contains.
+            # Can be 0, in which case the mBones array is NULL.
+            ("mNumBones", c_uint),
+            
+            # The bones of this mesh.
+            # A bone consists of a name by which it can be found in the
+            # frame hierarchy and a set of vertex weights.
+            ("mBones", POINTER(POINTER(Bone))),
+            
+            # The material used by this mesh.
+            # A mesh does use only a single material. If an imported model uses
+            # multiple materials, the import splits up the mesh. Use this value
+            # as index into the scene's material list.
+            ("mMaterialIndex", c_uint),
+            
+            # Name of the mesh. Meshes can be named, but this is not a
+            #  requirement and leaving this field empty is totally fine.
+            #  There are mainly three uses for mesh names:
+            #   - some formats name nodes and meshes independently.
+            #   - importers tend to split meshes up to meet the
+            #      one-material-per-mesh requirement. Assigning
+            #      the same (dummy) name to each of the result meshes
+            #      aids the caller at recovering the original mesh
+            #      partitioning.
+            #   - Vertex animations refer to meshes by their names.
+            ("mName", String),
+            
+            # NOT CURRENTLY IN USE. The number of attachment meshes
+            ("mNumAnimMeshes", c_uint),
+            
+            # NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-based animation.
+            #  Attachment meshes carry replacement data for some of the
+            #  mesh'es vertex components (usually positions, normals).
+        ]
+
+class Camera(Structure):
+    """
+    See 'aiCamera.h' for details.
+    """ 
+
+
+    _fields_ = [
+            # The name of the camera.
+            #  There must be a node in the scenegraph with the same name.
+            #  This node specifies the position of the camera in the scene
+            #  hierarchy and can be animated.
+            ("mName", String),
+            
+            # Position of the camera relative to the coordinate space
+            #  defined by the corresponding node.
+            #  The default value is 0|0|0.
+            ("mPosition", Vector3D),
+            
+            # 'Up' - vector of the camera coordinate system relative to
+            #  the coordinate space defined by the corresponding node.
+            #  The 'right' vector of the camera coordinate system is
+            #  the cross product of  the up and lookAt vectors.
+            #  The default value is 0|1|0. The vector
+            #  may be normalized, but it needn't.
+            ("mUp", Vector3D),
+            
+            # 'LookAt' - vector of the camera coordinate system relative to
+            #  the coordinate space defined by the corresponding node.
+            #  This is the viewing direction of the user.
+            #  The default value is 0|0|1. The vector
+            #  may be normalized, but it needn't.
+            ("mLookAt", Vector3D),
+            
+            # Half horizontal field of view angle, in radians.
+            #  The field of view angle is the angle between the center
+            #  line of the screen and the left or right border.
+            #  The default value is 1/4PI.
+            ("mHorizontalFOV", c_float),
+            
+            # Distance of the near clipping plane from the camera.
+            # The value may not be 0.f (for arithmetic reasons to prevent
+            # a division through zero). The default value is 0.1f.
+            ("mClipPlaneNear", c_float),
+            
+            # Distance of the far clipping plane from the camera.
+            # The far clipping plane must, of course, be further away than the
+            # near clipping plane. The default value is 1000.f. The ratio
+            # between the near and the far plane should not be too
+            # large (between 1000-10000 should be ok) to avoid floating-point
+            # inaccuracies which could lead to z-fighting.
+            ("mClipPlaneFar", c_float),
+            
+            # Screen aspect ratio.
+            # This is the ration between the width and the height of the
+            # screen. Typical values are 4/3, 1/2 or 1/1. This value is
+            # 0 if the aspect ratio is not defined in the source file.
+            # 0 is also the default value.
+            ("mAspect", c_float),
+        ]
+
+class VectorKey(Structure):
+    """
+    See 'aiAnim.h' for details.
+    """ 
+
+    _fields_ = [
+            # The time of this key
+            ("mTime", c_double),
+            
+            # The value of this key
+            ("mValue", Vector3D),
+        ]
+
+class QuatKey(Structure):
+    """
+    See 'aiAnim.h' for details.
+    """ 
+
+    _fields_ = [
+            # The time of this key
+            ("mTime", c_double),
+            
+            # The value of this key
+            ("mValue", Quaternion),
+        ]
+
+class NodeAnim(Structure):
+    """
+    See 'aiAnim.h' for details.
+    """ 
+
+    _fields_ = [
+            # The name of the node affected by this animation. The node
+            #  must exist and it must be unique.
+            ("mNodeName", String),
+            
+            # The number of position keys
+            ("mNumPositionKeys", c_uint),
+            
+            # The position keys of this animation channel. Positions are
+            # specified as 3D vector. The array is mNumPositionKeys in size.
+            # If there are position keys, there will also be at least one
+            # scaling and one rotation key.
+            ("mPositionKeys", POINTER(VectorKey)),
+            
+            # The number of rotation keys
+            ("mNumRotationKeys", c_uint),
+            
+            # The rotation keys of this animation channel. Rotations are
+            #  given as quaternions,  which are 4D vectors. The array is
+            #  mNumRotationKeys in size.
+            # If there are rotation keys, there will also be at least one
+            # scaling and one position key.
+            ("mRotationKeys", POINTER(QuatKey)),
+            
+            # The number of scaling keys
+            ("mNumScalingKeys", c_uint),
+            
+            # The scaling keys of this animation channel. Scalings are
+            #  specified as 3D vector. The array is mNumScalingKeys in size.
+            # If there are scaling keys, there will also be at least one
+            # position and one rotation key.
+            ("mScalingKeys", POINTER(VectorKey)),
+            
+            # Defines how the animation behaves before the first
+            #  key is encountered.
+            #  The default value is aiAnimBehaviour_DEFAULT (the original
+            #  transformation matrix of the affected node is used).
+            ("mPreState", c_uint),
+            
+            # Defines how the animation behaves after the last
+            #  key was processed.
+            #  The default value is aiAnimBehaviour_DEFAULT (the original
+            #  transformation matrix of the affected node is taken).
+            ("mPostState", c_uint),
+        ]
+
+class Animation(Structure):
+    """
+    See 'aiAnim.h' for details.
+    """ 
+
+    _fields_ = [
+            # The name of the animation. If the modeling package this data was
+            #  exported from does support only a single animation channel, this
+            #  name is usually empty (length is zero).
+            ("mName", String),
+            
+            # Duration of the animation in ticks.
+            ("mDuration", c_double),
+            
+            # Ticks per second. 0 if not specified in the imported file
+            ("mTicksPerSecond", c_double),
+            
+            # The number of bone animation channels. Each channel affects
+            #  a single node.
+            ("mNumChannels", c_uint),
+            
+            # The node animation channels. Each channel affects a single node.
+            #  The array is mNumChannels in size.
+            ("mChannels", POINTER(POINTER(NodeAnim))),
+            
+            # The number of mesh animation channels. Each channel affects
+            #  a single mesh and defines vertex-based animation.
+            ("mNumMeshChannels", c_uint),
+            
+            # The mesh animation channels. Each channel affects a single mesh.
+            #  The array is mNumMeshChannels in size.
+        ]
+
+class Scene(Structure):
+    """
+    See 'aiScene.h' for details.
+    """ 
+
     AI_SCENE_FLAGS_INCOMPLETE = 0x1
     AI_SCENE_FLAGS_VALIDATED = 0x2
     AI_SCENE_FLAGS_VALIDATION_WARNING =  	0x4
     AI_SCENE_FLAGS_NON_VERBOSE_FORMAT =  	0x8
     AI_SCENE_FLAGS_TERRAIN = 0x10
-
-    _fields_ = [
-            #Any combination of the AI_SCENE_FLAGS_XXX flags. By default#this value is 0, no flags are set. Most applications will#want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE#bit set.#
-            ("mFlags", c_uint),#The root node of the hierarchy.##There will always be at least the root node if the import#was successful (and no special flags have been set).#Presence of further nodes depends on the format and content#of the imported file.#
-            ("mRootNode", POINTER(Node)),#The number of meshes in the scene.#
-            ("mNumMeshes", c_uint),#The array of meshes.##Use the indices given in the aiNode structure to access#this array. The array is mNumMeshes in size. If the#AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always#be at least ONE material.#
-            ("mMeshes", POINTER(POINTER(Mesh))),#The number of materials in the scene.#
-            ("mNumMaterials", c_uint),#The array of materials.##Use the index given in each aiMesh structure to access this#array. The array is mNumMaterials in size. If the#AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always#be at least ONE material.#
-            ("mMaterials", POINTER(POINTER(Material))),#The number of animations in the scene.#
-            ("mNumAnimations", c_uint),#The array of animations.##All animations imported from the given file are listed here.#The array is mNumAnimations in size.#
-            ("mAnimations", POINTER(POINTER(Animation))),#The number of textures embedded into the file#
-            ("mNumTextures", c_uint),#The array of embedded textures.##Not many file formats embed their textures into the file.#An example is Quake's MDL format (which is also used by#some GameStudio versions)#
-            ("mTextures", POINTER(POINTER(Texture))),#The number of light sources in the scene. Light sources#are fully optional, in most cases this attribute will be 0#
-            ("mNumLights", c_uint),#The array of light sources.##All light sources imported from the given file are#listed here. The array is mNumLights in size.#
-            ("mLights", POINTER(POINTER(Light))),#The number of cameras in the scene. Cameras#are fully optional, in most cases this attribute will be 0#
-            ("mNumCameras", c_uint),#The array of cameras.##All cameras imported from the given file are listed here.#The array is mNumCameras in size. The first camera in the#array (if existing) is the default camera view into#the scene.#
-            ("mCameras", POINTER(POINTER(Camera))),
-        ]
+
+    _fields_ = [
+            # Any combination of the AI_SCENE_FLAGS_XXX flags. By default
+            # this value is 0, no flags are set. Most applications will
+            # want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
+            # bit set.
+            ("mFlags", c_uint),
+            
+            # The root node of the hierarchy.
+            # There will always be at least the root node if the import
+            # was successful (and no special flags have been set).
+            # Presence of further nodes depends on the format and content
+            # of the imported file.
+            ("mRootNode", POINTER(Node)),
+            
+            # The number of meshes in the scene.
+            ("mNumMeshes", c_uint),
+            
+            # The array of meshes.
+            # Use the indices given in the aiNode structure to access
+            # this array. The array is mNumMeshes in size. If the
+            # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+            # be at least ONE material.
+            ("mMeshes", POINTER(POINTER(Mesh))),
+            
+            # The number of materials in the scene.
+            ("mNumMaterials", c_uint),
+            
+            # The array of materials.
+            # Use the index given in each aiMesh structure to access this
+            # array. The array is mNumMaterials in size. If the
+            # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+            # be at least ONE material.
+            ("mMaterials", POINTER(POINTER(Material))),
+            
+            # The number of animations in the scene.
+            ("mNumAnimations", c_uint),
+            
+            # The array of animations.
+            # All animations imported from the given file are listed here.
+            # The array is mNumAnimations in size.
+            ("mAnimations", POINTER(POINTER(Animation))),
+            
+            # The number of textures embedded into the file
+            ("mNumTextures", c_uint),
+            
+            # The array of embedded textures.
+            # Not many file formats embed their textures into the file.
+            # An example is Quake's MDL format (which is also used by
+            # some GameStudio versions)
+            ("mTextures", POINTER(POINTER(Texture))),
+            
+            # The number of light sources in the scene. Light sources
+            # are fully optional, in most cases this attribute will be 0
+            ("mNumLights", c_uint),
+            
+            # The array of light sources.
+            # All light sources imported from the given file are
+            # listed here. The array is mNumLights in size.
+            ("mLights", POINTER(POINTER(Light))),
+            
+            # The number of cameras in the scene. Cameras
+            # are fully optional, in most cases this attribute will be 0
+            ("mNumCameras", c_uint),
+            
+            # The array of cameras.
+            # All cameras imported from the given file are listed here.
+            # The array is mNumCameras in size. The first camera in the
+            # array (if existing) is the default camera view into
+            # the scene.
+            ("mCameras", POINTER(POINTER(Camera))),
+        ]

+ 0 - 45
port/PyAssimp/quicktest.py

@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-#-*- coding: UTF-8 -*-
-
-"""
-This module uses the sample.py script to load all test models it finds.
-
-Note: this is not an exhaustive test suite, it does not check the
-data structures in detail. It just verifies whether basic
-loading and querying of 3d models using pyassimp works.
-"""
-
-
-import sys,os
-import sample
-from pyassimp import pyassimp,errors
-
-# paths to be walkd recursively
-basepaths = [os.path.join('..','..','test','models'), os.path.join('..','..','test','models-nonbsd')]
-
-# file extensions to be considered
-extensions = ['.3ds','.x','.lwo','.obj','.md5mesh','.dxf','.ply','.stl','.dae','.md5anim','.lws','.irrmesh','.nff','.off','.blend']
-
-def run_tests():
-	ok,err = 0,0
-	for path in basepaths:
-		for root, dirs, files in os.walk(path):
-			for afile in files:
-				base,ext = os.path.splitext(afile)	
-				if ext in extensions:		
-					try:
-						sample.main(os.path.join(root,afile))
-						ok += 1
-					except errors.AssimpError as error:
-						# assimp error is fine, this is a controlled case
-						print error
-						err += 1
-	print '** Loaded %s models, got controlled errors for %s files' % (ok,err)
-
-
-if __name__ == '__main__':
-	run_tests()
-
-
-
-

+ 33 - 19
port/PyAssimp/sample.py

@@ -6,7 +6,7 @@ This module demonstrates the functionality of PyAssimp.
 """
 
 
-from pyassimp import pyassimp
+import pyassimp
 import os, sys
 
 #get a model out of assimp's test-data if none is provided on the command line
@@ -14,6 +14,12 @@ DEFAULT_MODEL = os.path.join(os.path.dirname(__file__),
                      "..", "..",
                      "test", "models", "MDL", "MDL3 (3DGS A4)", "minigun.MDL")
 
+def recur_node(node,level = 0):
+    print("  " + "\t" * level + "- " + str(node))
+    for child in node.children:
+        recur_node(child, level + 1)
+
+
 def main(filename=None):
     filename = filename or DEFAULT_MODEL
     scene = pyassimp.load(filename)
@@ -29,40 +35,48 @@ def main(filename=None):
     print "  textures:", len(scene.textures)
     print
     
+    print "NODES:"
+    recur_node(scene.rootnode)
+
+    print
     print "MESHES:"
     for index, mesh in enumerate(scene.meshes):
         print "  MESH", index+1
-        print "    material:", mesh.mMaterialIndex+1
+        print "    material id:", mesh.materialindex+1
         print "    vertices:", len(mesh.vertices)
         print "    first 3 verts:", mesh.vertices[:3]
-        #if len(mesh.normals):
-        #        print "    first 3 normals:", mesh.normals[:3]
+        if mesh.normals:
+                print "    first 3 normals:", mesh.normals[:3]
+        else:
+                print "    no normals"
         print "    colors:", len(mesh.colors)
-        tc = mesh.texcoords
-        print "    texture-coords 1:", len(tc[0]), "first3:", tc[0][:3]
-        print "    texture-coords 2:", len(tc[1]), "first3:", tc[1][:3]
-        print "    texture-coords 3:", len(tc[2]), "first3:", tc[2][:3]
-        print "    texture-coords 4:", len(tc[3]), "first3:", tc[3][:3]
-        print "    uv-component-count:", len(mesh.mNumUVComponents)
+        tc = mesh.texturecoords
+        if tc:
+            print "    texture-coords 1:", len(tc[0]), "first3:", tc[0][:3]
+            print "    texture-coords 2:", len(tc[1]), "first3:", tc[1][:3]
+            print "    texture-coords 3:", len(tc[2]), "first3:", tc[2][:3]
+            print "    texture-coords 4:", len(tc[3]), "first3:", tc[3][:3]
+        else:
+            print "    no texture coordinates"
+        print "    uv-component-count:", len(mesh.numuvcomponents)
         print "    faces:", len(mesh.faces), "first:", [f.indices for f in mesh.faces[:3]]
-        print "    bones:", len(mesh.bones), "first:", [b.mName for b in mesh.bones[:3]]
+        print "    bones:", len(mesh.bones), "first:", [str(b) for b in mesh.bones[:3]]
         print
 
     print "MATERIALS:"
     for index, material in enumerate(scene.materials):
-        print "  MATERIAL", index+1
-        properties = pyassimp.GetMaterialProperties(material)
-        for key in properties:
-            print "    %s: %s" % (key, properties[key])
+        print("  MATERIAL (id:" + str(index+1) + ")")
+        for key, value in material.properties.items():
+            print "    %s: %s" % (key, value)
     print
     
     print "TEXTURES:"
     for index, texture in enumerate(scene.textures):
         print "  TEXTURE", index+1
-        print "    width:", texture.mWidth
-        print "    height:", texture.mHeight
-        print "    hint:", texture.achFormatHint
-        print "    data (size):", texture.mWidth*texture.mHeight
+        print "    width:", texture.width
+        print "    height:", texture.height
+        print "    hint:", texture.achformathint
+        print "    data (size):", len(texture.data)
    
     # Finally release the model
     pyassimp.release(scene)

+ 0 - 65
port/PyAssimp3/README

@@ -1,65 +0,0 @@
-	PyAssimp3 Readme
-	---------------
-
-
--- a simple Python3 wrapper for Assimp using ctypes to access
-the library. Works with Python 3 upwards.
-
-
-Note that pyassimp is by no means considered mature. It works,
-but it is far away from wrapping Assimp perfectly.
-
-
-USAGE
-=====
-
-To get started with pyAssimp, examine the sample.py script, which
-illustrates the basic usage. All Assimp data structures are
-wrapped using ctypes. All the data+length fields in Assimp's
-data structures (such as 'aiMesh::mNumVertices','aiMesh::mVertices')
-are replaced by simple python lists, so you can call len() on
-them to get their respective size and access members using
-[].
-
-For example, to load a file named 'hello.3ds' and print the first
-vertex of the first mesh, you would do (proper error handling
-substituted by assertions ...):
-
-> from pyassimp import pyassimp, errors
-> 
-> try:
-> 	scene = pyassimp.load('hello.3ds')
-> except AssimpError, msg:
->     print(msg)
->     return
-
-> assert len(scene.meshes)
-> mesh = scene.meshes[0]
-
-> assert len(mesh.vertices)
-> print(mesh.vertices[0])
-
-> # don't forget this one, or you will leak!
-> pyassimp.release(scene)
-
-
-INSTALL
-=======
-
-PyAssimp requires a assimp dynamic library (DLL on windows,
-so on linux :-) in order to work. The default search directories 
-are:
-
-- the current directory
-- on linux additionally: /usr/local/lib
-
-To build that library, refer to the Assimp master INSTALL
-instructions. To look in more places, edit ./pyassimp/helper.py.
-There's an 'additional_dirs' list waiting for your entries.
-
-
-
-
-
-
-	

+ 0 - 1
port/PyAssimp3/pyassimp/__init__.py

@@ -1 +0,0 @@
-#-*- coding: UTF-8 -*-

+ 0 - 11
port/PyAssimp3/pyassimp/errors.py

@@ -1,11 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-All possible errors.
-"""
-
-class AssimpError(BaseException):
-    """
-    If an internal error occures.
-    """
-    pass

+ 0 - 119
port/PyAssimp3/pyassimp/helper.py

@@ -1,119 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-Some fancy helper functions.
-"""
-
-import os, sys
-import ctypes
-from . import structs
-import operator
-
-from .errors import AssimpError
-from ctypes import POINTER
-
-additional_dirs, ext_whitelist = [],[]
-
-# populate search directories and lists of allowed file extensions
-# depending on the platform we're running on.
-if os.name=='posix':
-    additional_dirs.append('/usr/local/lib/')
-
-    if sys.platform.lower() == 'darwin':
-        ext_whitelist.append('.dylib')
-    
-    # note - this won't catch libassimp.so.N.n, but 
-    # currently there's always a symlink called
-    # libassimp.so in /usr/local/lib.
-    ext_whitelist.append('.so')
-
-elif os.name=='nt':
-    ext_whitelist.append('.dll')
-
-def vec2tuple(x):
-    """ Converts a VECTOR3D to a Tuple """
-    return (x.x, x.y, x.z)
-
-
-def try_load_functions(library,dll,candidates):
-    """try to  functbind to aiImportFile and aiReleaseImport
-    
-    library - path to current lib
-    dll - ctypes handle to it
-    candidates - receives matching candidates
-
-    They serve as signal functions to detect assimp,
-    also they're currently the only functions we need.
-    insert (library,aiImportFile,aiReleaseImport,dll) 
-    into 'candidates' if successful.
-
-    """
-    try:
-        load = dll.aiImportFile
-        release = dll.aiReleaseImport
-    except AttributeError:
-        #OK, this is a library, but it has not the functions we need
-        pass
-    else:
-        #Library found!
-        load.restype = POINTER(structs.Scene)
-        candidates.append((library, load, release, dll))
-
-
-def search_library():
-    """Loads the assimp-Library.
-    
-    result (load-function, release-function)    
-    exception AssimpError if no library is found
-    
-        """
-    #this path
-    folder = os.path.dirname(__file__)
-
-    # silence 'DLL not found' message boxes on win
-    try:
-        ctypes.windll.kernel32.SetErrorMode(0x8007)
-    except AttributeError:
-        pass    
-
-    candidates = []
-    
-    # test every file
-    for curfolder in [folder]+additional_dirs:
-        for filename in os.listdir(curfolder):
-            # our minimum requirement for candidates is that
-            # they should contain 'assimp' somewhere in 
-            # their name
-            if filename.lower().find('assimp')==-1 or\
-                os.path.splitext(filename)[-1].lower() not in ext_whitelist:
-                continue
-
-            library = os.path.join(curfolder, filename)
-            print('PyAssimp3: trying ',library)
-            try:
-                dll = ctypes.cdll.LoadLibrary(library)
-            except:
-                # OK, this except is evil. But different OSs will throw different
-                # errors. So just ignore any errors.
-                continue
-
-            try_load_functions(library,dll,candidates)
-    
-    if not candidates:
-        # no library found
-        raise AssimpError("assimp library not found")
-    else:
-        # get the newest library
-        candidates = [(os.lstat(x[0])[-2], x) for x in candidates]
-        res = max(candidates, key=operator.itemgetter(0))[1]
-        print('PyAssimp3: taking ',res[0])
-
-        # XXX: if there are 1000 dll/so files containing 'assimp'
-        # in their name, do we have all of them in our address
-        # space now until gc kicks in?
-
-        # XXX: take version postfix of the .so on linux?
-        return res[1:]
-
-
-

+ 0 - 314
port/PyAssimp3/pyassimp/pyassimp.py

@@ -1,314 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-"""
-PyAssimp
-
-This is the main-module of PyAssimp.
-"""
-
-import sys
-if sys.version_info < (3,0):
-	raise Exception('pyassimp: need python 3.0 or newer')
-
-from . import structs
-import ctypes
-import os
-from . import helper
-from .errors import AssimpError
-
-class aiArray:
-    """
-    A python class to 'safely' access C arrays.
-    For m<Name> and mNum<Name> assimp class members.
-    """
-    def __init__(self, instance, dataName, sizeName, i=None):
-        self.instance = instance
-        self.dataName = dataName
-        self.sizeName = sizeName
-        self.i = i
-        self.count = 0
-    
-    def _GetSize(self):
-        return getattr(self.instance, self.sizeName)
-        
-    def _GetData(self, index):
-        if self.i != None:
-            if not bool(getattr(self.instance, self.dataName)[self.i]):
-                return None
-            item = getattr(self.instance, self.dataName)[self.i][index]
-        else:
-            item = getattr(self.instance, self.dataName)[index]
-        if hasattr(item, 'contents'):
-            return item.contents._init()
-        elif hasattr(item, '_init'):
-            return item._init()
-        else:
-            return item
-        
-    def __next__(self):
-        if self.count >= self._GetSize():
-            self.count = 0
-            raise StopIteration
-        else:
-            c = self.count
-            self.count += 1
-            return self._GetData(c)
-            
-    def __getitem__(self, index):
-        if isinstance(index, slice):
-            indices = index.indices(len(self))
-            return [self.__getitem__(i) for i in range(*indices)]
-
-        if index < 0 or index >= self._GetSize():
-            raise IndexError("aiArray index out of range")
-        return self._GetData(index)
-        
-    def __iter__(self):
-        return self
-        
-    def __len__(self):
-        return int(self._GetSize())
-    
-    def __str__(self):
-        return str([x for x in self])
-        
-    def __repr__(self):
-        return str([x for x in self])
-        
-class aiTuple:
-    """
-    A python class to 'safely' access C structs in a python tuple fashion.
-    For C structs like vectors, matrices, colors, ...
-    """
-    def __init__(self, instance):
-        self.instance = instance
-        self.count = 0
-    
-    def _GetSize(self):
-        return len(self.instance._fields_)
-     
-    def _GetData(self, index):
-        return getattr(self.instance, self.instance._fields_[index][0])
-        
-    def __next__(self):
-        if self.count >= self._GetSize():
-            self.count = 0
-            raise StopIteration
-        else:
-            c = self.count
-            self.count += 1
-            return self._GetData(c)
-            
-    def __getitem__(self, index):
-        if isinstance(index, slice):
-            indices = index.indices(len(self))
-            return [self.__getitem__(i) for i in range(*indices)]
-            
-        if index < 0 or index >= self._GetSize():
-            raise IndexError("aiTuple index out of range")
-        return self._GetData(index)
-        
-    def __iter__(self):
-        return self
-        
-    def __len__(self):
-        return int(self._GetSize())
-        
-    def __str__(self):
-        return str([x for x in self])
-            
-    def __repr__(self):
-        return str([x for x in self])
-
-class StringUInt32(ctypes.Structure):
-    """
-    A ctypes structure used for material strings.
-    This is a workaround for a type mismatch for the length field between strings used for materials and elsewhere.
-    """
-    
-    MAXLEN = 1024
-    
-    _fields_ = [
-            ("length", ctypes.c_uint32),
-            ("data", ctypes.c_char*MAXLEN),
-        ]
-
-def _init(self):
-    """
-    Custom initialize() for C structs, adds safely accessable member functionality.
-    """
-    if hasattr(self, '_is_init'):
-        return self
-    self._is_init = True
-
-    if str(self.__class__.__name__) == "MaterialProperty":
-        self.mKey._init()
-        
-    for m in list(self.__class__.__dict__.keys()):
-        if m.startswith('mNum'):
-            name = m.split('mNum')[1]
-            if 'm'+name in list(self.__class__.__dict__.keys()):
-                setattr(self.__class__, name.lower(), aiArray(self, 'm'+name , m))
-                if name.lower() == "vertices":
-                    setattr(self.__class__, "normals", aiArray(self, 'mNormals' , m))
-                    setattr(self.__class__, "tangents", aiArray(self, 'mTangents' , m))
-                    setattr(self.__class__, "bitangets", aiArray(self, 'mBitangents' , m))
-                    setattr(self.__class__, "colors", [aiArray(self, 'mColors' , m, o) for o in range(len(self.mColors))])
-                    setattr(self.__class__, "texcoords", [aiArray(self, 'mTextureCoords' , m, o) for o in range(len(self.mColors))])
-                
-        elif m == "x" or m == "a1" or m == "b": # Vector, matrix, quat, color
-            self._tuple = aiTuple(self)
-            setattr(self.__class__, '__getitem__', lambda x, y: x._tuple.__getitem__(y))
-            setattr(self.__class__, '__iter__', lambda x: x._tuple)
-            setattr(self.__class__, 'next', lambda x: x._tuple.__next__)
-            setattr(self.__class__, '__repr__', lambda x: str([c for c in x]))
-            break
-        elif m == "data": #String
-            setattr(self.__class__, '__repr__', lambda x: str(x.data))
-            setattr(self.__class__, '__str__', lambda x: str(x.data))
-            break
-            
-        if hasattr(getattr(self, m), '_init'):
-            getattr(self, m)._init()
-        
-    return self
-
-"""
-Python magic to add the _init() function to all C struct classes.
-"""
-for struct in dir(structs):
-    if not (struct.startswith('_') or struct.startswith('c_') or struct == "Structure" or struct == "POINTER") and not isinstance(getattr(structs, struct),int):
-        setattr(getattr(structs, struct), '_init', _init)
-
-
-class AssimpLib(object):
-    """
-    Assimp-Singleton
-    """
-    load, release, dll = helper.search_library()
-
-#the loader as singleton
-_assimp_lib = AssimpLib()
-
-
-def load(filename, processing=0):
-    """
-    Loads the model with some specific processing parameters.
-    
-    filename - file to load model from
-    processing - processing parameters
-    
-    result Scene-object with model-data
-    
-    throws AssimpError - could not open file
-    """
-    #read pure data
-    from ctypes import c_char_p, c_uint
-    model = _assimp_lib.load(c_char_p(filename), c_uint(processing))
-    if not model:
-        #Uhhh, something went wrong!
-        raise AssimpError("could not import file: %s" % filename)
-
-    return model.contents._init()
-
-def release(scene):
-    from ctypes import pointer
-    _assimp_lib.release(pointer(scene))
-    
-def aiGetMaterialFloatArray(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.Color4D()
-    max = c_uint(sizeof(structs.Color4D))
-    r=_assimp_lib.dll.aiGetMaterialFloatArray(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out), 
-                                            byref(max))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialFloatArray failed!")
-      
-    out._init()
-    return [out[i] for i in range(max.value)]
-    
-def aiGetMaterialString(material, key):
-    AI_SUCCESS = 0
-    from ctypes import byref, pointer, cast, c_float, POINTER, sizeof, c_uint
-    out = structs.String()
-    r=_assimp_lib.dll.aiGetMaterialString(pointer(material), 
-                                            key[0], 
-                                            key[1], 
-                                            key[2], 
-                                            byref(out))
-                                            
-    if (r != AI_SUCCESS):    
-        raise AssimpError("aiGetMaterialString failed!")
-        
-    return str(out.data)
- 
-def GetMaterialProperties(material): 
-    """
-    Convenience Function to get the material properties.
-    This function returns the following tuple: (name, clr, mat, tex) where:
-    name: is the name of the material
-    clr: is a dictionary of color parameters
-    mat: is a dictionary of material parameters
-    tex: is a triply nested dictionary than can be indexed by index, semantic, and then key:
-            tex[index][semantic][key]
-    """
-    name = ""
-    clr = {}
-    mat = {}
-    tex = {}
-    #read all properties
-    for p in material.properties:
-        #the name
-        key = p.mKey.data
-
-        #the data
-        from ctypes import POINTER, cast, c_int, c_float, sizeof
-        if p.mType == 1:
-            arr = cast(p.mData, POINTER(c_float*(p.mDataLength//sizeof(c_float)) )).contents
-            value = [x for x in arr]
-        elif p.mType == 3: #string can't be an array
-            try:
-                value = cast(p.mData, POINTER(StringUInt32)).contents.data
-            except UnicodeDecodeError:
-                print('UnicodeDecodeError reading material property, ignoring.')
-                continue
-        elif p.mType == 4:
-            arr = cast(p.mData, POINTER(c_int*(p.mDataLength//sizeof(c_int)) )).contents
-            value = [x for x in arr]
-        else:
-            value = p.mData[:p.mDataLength]
-
-        #store in the appropriate dict
-        if key == b'?mat.name':
-            name = value
-        elif key[:5] == b'$mat.':
-            mat[key[5:]] = value
-        elif key[:5] == b'$clr.':
-            clr[key[5:]] = value
-        elif key[:5] == b'$tex.':
-            if p.mIndex not in tex:
-                tex[p.mIndex] = {}
-            if p.mSemantic not in tex[p.mIndex]:
-                tex[p.mIndex][p.mSemantic] = {}
-            tex[p.mIndex][p.mSemantic][key[5:]] = value
-
-    return (name, clr, mat, tex)
-    
-    
-def aiDecomposeMatrix(matrix):
-    if not isinstance(matrix, structs.Matrix4x4):
-        raise AssimpError("aiDecomposeMatrix failed: Not a aiMatrix4x4!")
-    
-    scaling = structs.Vector3D()
-    rotation = structs.Quaternion()
-    position = structs.Vector3D()
-    
-    from ctypes import byref, pointer
-    _assimp_lib.dll.aiDecomposeMatrix(pointer(matrix), byref(scaling), byref(rotation), byref(position))
-    return scaling._init(), rotation._init(), position._init()

+ 0 - 424
port/PyAssimp3/pyassimp/structs.py

@@ -1,424 +0,0 @@
-#-*- coding: UTF-8 -*-
-
-from ctypes import POINTER, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t
-
-
-class Vector2D(Structure):
-    """
-    See 'aiVector2D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("x", c_float),("y", c_float),
-        ]
-
-class Texel(Structure):
-    """
-    See 'aiTexture.h' for details.
-    """ 
-
-    _fields_ = [
-            ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte),
-        ]
-
-class Plane(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Plane equation
-            ("a", c_float),("b", c_float),("c", c_float),("d", c_float),
-        ]
-
-class Color3D(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Red, green and blue color values
-            ("r", c_float),("g", c_float),("b", c_float),
-        ]
-
-class String(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    MAXLEN = 1024
-
-    _fields_ = [
-            #Binary length of the string excluding the terminal 0. This is NOT the# logical length of strings containing UTF-8 multibyte sequences! It's# the number of bytes from the beginning of the string to its end.#
-            ("length", c_size_t),#String buffer. Size limit is MAXLEN#
-            ("data", c_char*MAXLEN),
-        ]
-
-class MemoryInfo(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            #Storage allocated for texture data#
-            ("textures", c_uint),#Storage allocated for material data#
-            ("materials", c_uint),#Storage allocated for mesh data#
-            ("meshes", c_uint),#Storage allocated for node data#
-            ("nodes", c_uint),#Storage allocated for animation data#
-            ("animations", c_uint),#Storage allocated for camera data#
-            ("cameras", c_uint),#Storage allocated for light data#
-            ("lights", c_uint),#Total storage allocated for the full import.#
-            ("total", c_uint),
-        ]
-
-class Matrix3x3(Structure):
-    """
-    See 'aiMatrix3x3.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("a1", c_float),("a2", c_float),("a3", c_float),
-            ("b1", c_float),("b2", c_float),("b3", c_float),
-            ("c1", c_float),("c2", c_float),("c3", c_float),
-        ]
-
-class Color4D(Structure):
-    """
-    See 'aiColor4D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            # Red, green, blue and alpha color values
-            ("r", c_float),("g", c_float),("b", c_float),("a", c_float),
-        ]
-
-class ExportFormatDesc(Structure):
-    """
-    See 'export.h' for details.
-    """ 
-
-    _fields_ = [
-            # a short string ID to uniquely identify the export format. Use this ID string to# specify which file format you want to export to when calling aiExportScene().# Example: "dae" or "obj"
-            ("id", POINTER(c_char)),# A short description of the file format to present to users. Useful if you want# to allow the user to select an export format.
-            ("description", POINTER(c_char)),# Recommended file extension for the exported file in lower case.
-            ("fileExtension", POINTER(c_char)),
-        ]
-
-class Quaternion(Structure):
-    """
-    See 'aiQuaternion.h' for details.
-    """ 
-
-
-    _fields_ = [
-            # w,x,y,z components of the quaternion
-            ("w", c_float),("x", c_float),("y", c_float),("z", c_float),
-        ]
-
-class Vector3D(Structure):
-    """
-    See 'aiVector3D.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("x", c_float),("y", c_float),("z", c_float),
-        ]
-
-class Face(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # Number of indices defining this face.# The maximum value for this member is #AI_MAX_FACE_INDICES.
-            ("mNumIndices", c_uint),# Pointer to the indices array. Size of the array is given in numIndices.
-            ("mIndices", POINTER(c_uint)),
-        ]
-
-class VertexWeight(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # Index of the vertex which is influenced by the bone.
-            ("mVertexId", c_uint),# The strength of the influence in the range (0...1).# The influence from all bones at one vertex amounts to 1.
-            ("mWeight", c_float),
-        ]
-
-class MeshKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#Index into the aiMesh::mAnimMeshes array of the# mesh coresponding to the #aiMeshAnim hosting this# key frame. The referenced anim mesh is evaluated# according to the rules defined in the docs for #aiAnimMesh.#
-            ("mValue", c_uint),
-        ]
-
-class Matrix4x4(Structure):
-    """
-    See 'aiMatrix4x4.h' for details.
-    """ 
-
-
-    _fields_ = [
-            ("a1", c_float),("a2", c_float),("a3", c_float),("a4", c_float),
-            ("b1", c_float),("b2", c_float),("b3", c_float),("b4", c_float),
-            ("c1", c_float),("c2", c_float),("c3", c_float),("c4", c_float),
-            ("d1", c_float),("d2", c_float),("d3", c_float),("d4", c_float),
-        ]
-
-class Node(Structure):
-    """
-    See 'aiScene.h' for details.
-    """ 
-
-
-Node._fields_ = [
-            #The name of the node.##The name might be empty (length of zero) but all nodes which#need to be accessed afterwards by bones or anims are usually named.#Multiple nodes may have the same name, but nodes which are accessed#by bones (see #aiBone and #aiMesh::mBones) *must* be unique.##Cameras and lights are assigned to a specific node name - if there#are multiple nodes with this name, they're assigned to each of them.#<br>#There are no limitations regarding the characters contained in#this text. You should be able to handle stuff like whitespace, tabs,#linefeeds, quotation marks, ampersands, ... .#
-            ("mName", String),#The transformation relative to the node's parent.#
-            ("mTransformation", Matrix4x4),#Parent node. NULL if this node is the root node.#
-            ("mParent", POINTER(Node)),#The number of child nodes of this node.#
-            ("mNumChildren", c_uint),#The child nodes of this node. NULL if mNumChildren is 0.#
-            ("mChildren", POINTER(POINTER(Node))),#The number of meshes of this node.#
-            ("mNumMeshes", c_uint),#The meshes of this node. Each entry is an index into the mesh#
-            ("mMeshes", POINTER(c_uint)),
-        ]
-
-class Camera(Structure):
-    """
-    See 'aiCamera.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #The name of the camera.## There must be a node in the scenegraph with the same name.# This node specifies the position of the camera in the scene# hierarchy and can be animated.#
-            ("mName", String),#Position of the camera relative to the coordinate space# defined by the corresponding node.## The default value is 0|0|0.#
-            ("mPosition", Vector3D),#'Up' - vector of the camera coordinate system relative to# the coordinate space defined by the corresponding node.## The 'right' vector of the camera coordinate system is# the cross product of  the up and lookAt vectors.# The default value is 0|1|0. The vector# may be normalized, but it needn't.#
-            ("mUp", Vector3D),#'LookAt' - vector of the camera coordinate system relative to# the coordinate space defined by the corresponding node.## This is the viewing direction of the user.# The default value is 0|0|1. The vector# may be normalized, but it needn't.#
-            ("mLookAt", Vector3D),#Half horizontal field of view angle, in radians.## The field of view angle is the angle between the center# line of the screen and the left or right border.# The default value is 1/4PI.#
-            ("mHorizontalFOV", c_float),#Distance of the near clipping plane from the camera.##The value may not be 0.f (for arithmetic reasons to prevent#a division through zero). The default value is 0.1f.#
-            ("mClipPlaneNear", c_float),#Distance of the far clipping plane from the camera.##The far clipping plane must, of course, be further away than the#near clipping plane. The default value is 1000.f. The ratio#between the near and the far plane should not be too#large (between 1000-10000 should be ok) to avoid floating-point#inaccuracies which could lead to z-fighting.#
-            ("mClipPlaneFar", c_float),#Screen aspect ratio.##This is the ration between the width and the height of the#screen. Typical values are 4/3, 1/2 or 1/1. This value is#0 if the aspect ratio is not defined in the source file.#0 is also the default value.#
-            ("mAspect", c_float),
-        ]
-
-class Texture(Structure):
-    """
-    See 'aiTexture.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #Width of the texture, in pixels##If mHeight is zero the texture is compressed in a format#like JPEG. In this case mWidth specifies the size of the#memory area pcData is pointing to, in bytes.#
-            ("mWidth", c_uint),#Height of the texture, in pixels##If this value is zero, pcData points to an compressed texture#in any format (e.g. JPEG).#
-            ("mHeight", c_uint),#A hint from the loader to make it easier for applications# to determine the type of embedded compressed textures.##If mHeight != 0 this member is undefined. Otherwise it#is set set to '\\0\\0\\0\\0' if the loader has no additional#information about the texture file format used OR the#file extension of the format without a trailing dot. If there#are multiple file extensions for a format, the shortest#extension is chosen (JPEG maps to 'jpg', not to 'jpeg').#E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'.  All characters are lower-case.#The fourth character will always be '\\0'.#
-            ("achFormatHint", c_char*4),#Data of the texture.##Points to an array of mWidth#mHeight aiTexel's.#The format of the texture data is always ARGB8888 to#make the implementation for user of the library as easy#as possible. If mHeight = 0 this is a pointer to a memory#buffer of size mWidth containing the compressed texture#data. Good luck, have fun!#
-            ("pcData", POINTER(Texel)),
-        ]
-
-class Ray(Structure):
-    """
-    See 'aiTypes.h' for details.
-    """ 
-
-    _fields_ = [
-            # Position and direction of the ray
-            ("pos", Vector3D),("dir", Vector3D),
-        ]
-
-class Light(Structure):
-    """
-    See 'aiLight.h' for details.
-    """ 
-
-
-    _fields_ = [
-            #The name of the light source.## There must be a node in the scenegraph with the same name.# This node specifies the position of the light in the scene# hierarchy and can be animated.#
-            ("mName", String),#The type of the light source.##aiLightSource_UNDEFINED is not a valid value for this member.#
-            ("mType", c_uint),#Position of the light source in space. Relative to the# transformation of the node corresponding to the light.## The position is undefined for directional lights.#
-            ("mPosition", Vector3D),#Direction of the light source in space. Relative to the# transformation of the node corresponding to the light.## The direction is undefined for point lights. The vector# may be normalized, but it needn't.#
-            ("mDirection", Vector3D),#Constant light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att0 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationConstant", c_float),#Linear light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att1 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationLinear", c_float),#Quadratic light attenuation factor.## The intensity of the light source at a given distance 'd' from# the light's position is# @code# Atten = 1/( att0 + att1#d + att2#d*d)# @endcode# This member corresponds to the att2 variable in the equation.# Naturally undefined for directional lights.#
-            ("mAttenuationQuadratic", c_float),#Diffuse color of the light source## The diffuse light color is multiplied with the diffuse# material color to obtain the final color that contributes# to the diffuse shading term.#
-            ("mColorDiffuse", Color3D),#Specular color of the light source## The specular light color is multiplied with the specular# material color to obtain the final color that contributes# to the specular shading term.#
-            ("mColorSpecular", Color3D),#Ambient color of the light source## The ambient light color is multiplied with the ambient# material color to obtain the final color that contributes# to the ambient shading term. Most renderers will ignore# this value it, is just a remaining of the fixed-function pipeline# that is still supported by quite many file formats.#
-            ("mColorAmbient", Color3D),#Inner angle of a spot light's light cone.## The spot light has maximum influence on objects inside this# angle. The angle is given in radians. It is 2PI for point# lights and undefined for directional lights.#
-            ("mAngleInnerCone", c_float),#Outer angle of a spot light's light cone.## The spot light does not affect objects outside this angle.# The angle is given in radians. It is 2PI for point lights and# undefined for directional lights. The outer angle must be# greater than or equal to the inner angle.# It is assumed that the application uses a smooth# interpolation between the inner and the outer cone of the# spot light.#
-            ("mAngleOuterCone", c_float),
-        ]
-
-class Bone(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    _fields_ = [
-            # The name of the bone.
-            ("mName", String),# The number of vertices affected by this bone# The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
-            ("mNumWeights", c_uint),# The vertices affected by this bone
-            ("mWeights", POINTER(VertexWeight)),# Matrix that transforms from mesh space to bone space in bind pose
-            ("mOffsetMatrix", Matrix4x4),
-        ]
-
-class Mesh(Structure):
-    """
-    See 'aiMesh.h' for details.
-    """ 
-
-    AI_MAX_FACE_INDICES = 0x7fff
-    AI_MAX_BONE_WEIGHTS = 0x7fffffff
-    AI_MAX_VERTICES = 0x7fffffff
-    AI_MAX_FACES = 0x7fffffff
-    AI_MAX_NUMBER_OF_COLOR_SETS = 0x8
-    AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8
-
-    _fields_ = [
-            #Bitwise combination of the members of the #aiPrimitiveType enum.#This specifies which types of primitives are present in the mesh.#The "SortByPrimitiveType"-Step can be used to make sure the#output meshes consist of one primitive type each.#
-            ("mPrimitiveTypes", c_uint),#The number of vertices in this mesh.#This is also the size of all of the per-vertex data arrays.#The maximum value for this member is #AI_MAX_VERTICES.#
-            ("mNumVertices", c_uint),#The number of primitives (triangles, polygons, lines) in this  mesh.#This is also the size of the mFaces array.#The maximum value for this member is #AI_MAX_FACES.#
-            ("mNumFaces", c_uint),#Vertex positions.#This array is always present in a mesh. The array is#mNumVertices in size.#
-            ("mVertices", POINTER(Vector3D)),#Vertex normals.#The array contains normalized vectors, NULL if not present.#The array is mNumVertices in size. Normals are undefined for#point and line primitives. A mesh consisting of points and#lines only may not have normal vectors. Meshes with mixed#primitive types (i.e. lines and triangles) may have normals,#but the normals for vertices that are only referenced by#point or line primitives are undefined and set to QNaN (WARN:#qNaN compares to inequal to *everything*, even to qNaN itself.#Using code like this to check whether a field is qnan is:#@code##define IS_QNAN(f) (f != f)#@endcode#still dangerous because even 1.f == 1.f could evaluate to false! (#remember the subtleties of IEEE754 artithmetics). Use stuff like#@c fpclassify instead.#@note Normal vectors computed by Assimp are always unit-length.#However, this needn't apply for normals that have been taken#  directly from the model file.#
-            ("mNormals", POINTER(Vector3D)),#Vertex tangents.#The tangent of a vertex points in the direction of the positive#X texture axis. The array contains normalized vectors, NULL if#not present. The array is mNumVertices in size. A mesh consisting#of points and lines only may not have normal vectors. Meshes with#mixed primitive types (i.e. lines and triangles) may have#normals, but the normals for vertices that are only referenced by#point or line primitives are undefined and set to qNaN.  See#the #mNormals member for a detailled discussion of qNaNs.#@note If the mesh contains tangents, it automatically also#contains bitangents.#
-            ("mTangents", POINTER(Vector3D)),#Vertex bitangents.#The bitangent of a vertex points in the direction of the positive#Y texture axis. The array contains normalized vectors, NULL if not#present. The array is mNumVertices in size.#@note If the mesh contains tangents, it automatically also contains#bitangents.#
-            ("mBitangents", POINTER(Vector3D)),#Vertex color sets.#A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex#colors per vertex. NULL if not present. Each array is#mNumVertices in size if present.#
-            ("mColors", POINTER(Color4D)*AI_MAX_NUMBER_OF_COLOR_SETS),#Vertex texture coords, also known as UV channels.#A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per#vertex. NULL if not present. The array is mNumVertices in size.#
-            ("mTextureCoords", POINTER(Vector3D)*AI_MAX_NUMBER_OF_TEXTURECOORDS),#Specifies the number of components for a given UV channel.#Up to three channels are supported (UVW, for accessing volume#or cube maps). If the value is 2 for a given channel n, the#component p.z of mTextureCoords[n][p] is set to 0.0f.#If the value is 1 for a given channel, p.y is set to 0.0f, too.#@note 4D coords are not supported#
-            ("mNumUVComponents", c_uint*AI_MAX_NUMBER_OF_TEXTURECOORDS),#The faces the mesh is constructed from.#Each face refers to a number of vertices by their indices.#This array is always present in a mesh, its size is given#in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT#is NOT set each face references an unique set of vertices.#
-            ("mFaces", POINTER(Face)),#The number of bones this mesh contains.#Can be 0, in which case the mBones array is NULL.#
-            ("mNumBones", c_uint),#The bones of this mesh.#A bone consists of a name by which it can be found in the#frame hierarchy and a set of vertex weights.#
-            ("mBones", POINTER(POINTER(Bone))),#The material used by this mesh.#A mesh does use only a single material. If an imported model uses#multiple materials, the import splits up the mesh. Use this value#as index into the scene's material list.#
-            ("mMaterialIndex", c_uint),#Name of the mesh. Meshes can be named, but this is not a# requirement and leaving this field empty is totally fine.# There are mainly three uses for mesh names:#  - some formats name nodes and meshes independently.#  - importers tend to split meshes up to meet the#     one-material-per-mesh requirement. Assigning#     the same (dummy) name to each of the result meshes#     aids the caller at recovering the original mesh#     partitioning.#  - Vertex animations refer to meshes by their names.#
-            ("mName", String),#NOT CURRENTLY IN USE. The number of attachment meshes#
-            ("mNumAnimMeshes", c_uint),#NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-based animation.# Attachment meshes carry replacement data for some of the# mesh'es vertex components (usually positions, normals).#
-        ]
-
-class VectorKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#The value of this key#
-            ("mValue", Vector3D),
-        ]
-
-class QuatKey(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The time of this key#
-            ("mTime", c_double),#The value of this key#
-            ("mValue", Quaternion),
-        ]
-
-class NodeAnim(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The name of the node affected by this animation. The node# must exist and it must be unique.#
-            ("mNodeName", String),#The number of position keys#
-            ("mNumPositionKeys", c_uint),#The position keys of this animation channel. Positions are#specified as 3D vector. The array is mNumPositionKeys in size.##If there are position keys, there will also be at least one#scaling and one rotation key.#
-            ("mPositionKeys", POINTER(VectorKey)),#The number of rotation keys#
-            ("mNumRotationKeys", c_uint),#The rotation keys of this animation channel. Rotations are# given as quaternions,  which are 4D vectors. The array is# mNumRotationKeys in size.##If there are rotation keys, there will also be at least one#scaling and one position key.#
-            ("mRotationKeys", POINTER(QuatKey)),#The number of scaling keys#
-            ("mNumScalingKeys", c_uint),#The scaling keys of this animation channel. Scalings are# specified as 3D vector. The array is mNumScalingKeys in size.##If there are scaling keys, there will also be at least one#position and one rotation key.#
-            ("mScalingKeys", POINTER(VectorKey)),#Defines how the animation behaves before the first# key is encountered.## The default value is aiAnimBehaviour_DEFAULT (the original# transformation matrix of the affected node is used).#
-            ("mPreState", c_uint),#Defines how the animation behaves after the last# key was processed.## The default value is aiAnimBehaviour_DEFAULT (the original# transformation matrix of the affected node is taken).#
-            ("mPostState", c_uint),
-        ]
-
-class Animation(Structure):
-    """
-    See 'aiAnim.h' for details.
-    """ 
-
-    _fields_ = [
-            #The name of the animation. If the modeling package this data was# exported from does support only a single animation channel, this# name is usually empty (length is zero).#
-            ("mName", String),#Duration of the animation in ticks.#
-            ("mDuration", c_double),#Ticks per second. 0 if not specified in the imported file#
-            ("mTicksPerSecond", c_double),#The number of bone animation channels. Each channel affects# a single node.#
-            ("mNumChannels", c_uint),#The node animation channels. Each channel affects a single node.# The array is mNumChannels in size.#
-            ("mChannels", POINTER(POINTER(NodeAnim))),#The number of mesh animation channels. Each channel affects# a single mesh and defines vertex-based animation.#
-            ("mNumMeshChannels", c_uint),#The mesh animation channels. Each channel affects a single mesh.# The array is mNumMeshChannels in size.#
-        ]
-
-class UVTransform(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #Translation on the u and v axes.## The default value is (0|0).#
-            ("mTranslation", Vector2D),#Scaling on the u and v axes.## The default value is (1|1).#
-            ("mScaling", Vector2D),#Rotation - in counter-clockwise direction.## The rotation angle is specified in radians. The# rotation center is 0.5f|0.5f. The default value# 0.f.#
-            ("mRotation", c_float),
-        ]
-
-class MaterialProperty(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #Specifies the name of the property (key)# Keys are generally case insensitive.#
-            ("mKey", String),#Textures: Specifies their exact usage semantic.#For non-texture properties, this member is always 0#(or, better-said, #aiTextureType_NONE).#
-            ("mSemantic", c_uint),#Textures: Specifies the index of the texture.# For non-texture properties, this member is always 0.#
-            ("mIndex", c_uint),#Size of the buffer mData is pointing to, in bytes.# This value may not be 0.#
-            ("mDataLength", c_uint),#Type information for the property.##Defines the data layout inside the data buffer. This is used#by the library internally to perform debug checks and to#utilize proper type conversions.#(It's probably a hacky solution, but it works.)#
-            ("mType", c_uint),#Binary buffer to hold the property's value.#The size of the buffer is always mDataLength.#
-            ("mData", POINTER(c_char)),
-        ]
-
-class Material(Structure):
-    """
-    See 'aiMaterial.h' for details.
-    """ 
-
-    _fields_ = [
-            #List of all material properties loaded.#
-            ("mProperties", POINTER(POINTER(MaterialProperty))),#Number of properties in the data base#
-            ("mNumProperties", c_uint),#Storage allocated#
-            ("mNumAllocated", c_uint),
-        ]
-
-class Scene(Structure):
-    """
-    See 'aiScene.h' for details.
-    """ 
-
-    AI_SCENE_FLAGS_INCOMPLETE = 0x1
-    AI_SCENE_FLAGS_VALIDATED = 0x2
-    AI_SCENE_FLAGS_VALIDATION_WARNING =  	0x4
-    AI_SCENE_FLAGS_NON_VERBOSE_FORMAT =  	0x8
-    AI_SCENE_FLAGS_TERRAIN = 0x10
-
-    _fields_ = [
-            #Any combination of the AI_SCENE_FLAGS_XXX flags. By default#this value is 0, no flags are set. Most applications will#want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE#bit set.#
-            ("mFlags", c_uint),#The root node of the hierarchy.##There will always be at least the root node if the import#was successful (and no special flags have been set).#Presence of further nodes depends on the format and content#of the imported file.#
-            ("mRootNode", POINTER(Node)),#The number of meshes in the scene.#
-            ("mNumMeshes", c_uint),#The array of meshes.##Use the indices given in the aiNode structure to access#this array. The array is mNumMeshes in size. If the#AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always#be at least ONE material.#
-            ("mMeshes", POINTER(POINTER(Mesh))),#The number of materials in the scene.#
-            ("mNumMaterials", c_uint),#The array of materials.##Use the index given in each aiMesh structure to access this#array. The array is mNumMaterials in size. If the#AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always#be at least ONE material.#
-            ("mMaterials", POINTER(POINTER(Material))),#The number of animations in the scene.#
-            ("mNumAnimations", c_uint),#The array of animations.##All animations imported from the given file are listed here.#The array is mNumAnimations in size.#
-            ("mAnimations", POINTER(POINTER(Animation))),#The number of textures embedded into the file#
-            ("mNumTextures", c_uint),#The array of embedded textures.##Not many file formats embed their textures into the file.#An example is Quake's MDL format (which is also used by#some GameStudio versions)#
-            ("mTextures", POINTER(POINTER(Texture))),#The number of light sources in the scene. Light sources#are fully optional, in most cases this attribute will be 0#
-            ("mNumLights", c_uint),#The array of light sources.##All light sources imported from the given file are#listed here. The array is mNumLights in size.#
-            ("mLights", POINTER(POINTER(Light))),#The number of cameras in the scene. Cameras#are fully optional, in most cases this attribute will be 0#
-            ("mNumCameras", c_uint),#The array of cameras.##All cameras imported from the given file are listed here.#The array is mNumCameras in size. The first camera in the#array (if existing) is the default camera view into#the scene.#
-            ("mCameras", POINTER(POINTER(Camera))),
-        ]

+ 0 - 45
port/PyAssimp3/quicktest.py

@@ -1,45 +0,0 @@
-#!/usr/bin/env python3
-#-*- coding: UTF-8 -*-
-
-"""
-This module uses the sample.py script to load all test models it finds.
-
-Note: this is not an exhaustive test suite, it does not check the
-data structures in detail. It just verifies whether basic
-loading and querying of 3d models using pyassimp works.
-"""
-
-
-import sys,os
-import sample
-from pyassimp import pyassimp,errors
-
-# paths to be walkd recursively
-basepaths = [os.path.join('..','..','test','models'), os.path.join('..','..','test','models-nonbsd')]
-
-# file extensions to be considered
-extensions = ['.3ds','.x','.lwo','.obj','.md5mesh','.dxf','.ply','.stl','.dae','.md5anim','.lws','.irrmesh','.nff','.off','.blend']
-
-def run_tests():
-	ok,err = 0,0
-	for path in basepaths:
-		for root, dirs, files in os.walk(path):
-			for afile in files:
-				base,ext = os.path.splitext(afile)	
-				if ext in extensions:		
-					try:
-						sample.main(os.path.join(root,afile))
-						ok += 1
-					except errors.AssimpError as error:
-						# assimp error is fine, this is a controlled case
-						print(error)
-						err += 1
-	print(('** Loaded %s models, got controlled errors for %s files' % (ok,err)))
-
-
-if __name__ == '__main__':
-	run_tests()
-
-
-
-

+ 0 - 71
port/PyAssimp3/sample.py

@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-#-*- coding: UTF-8 -*-
-
-"""
-This module demonstrates the functionality of PyAssimp.
-"""
-
-
-from pyassimp import pyassimp
-import os, sys
-
-#get a model out of assimp's test-data if none is provided on the command line
-DEFAULT_MODEL = os.path.join(os.path.dirname(__file__),
-                     "..", "..", 
-                     "test", "models", "Collada", "duck.dae")
-
-def main(filename=None):
-    filename = filename or DEFAULT_MODEL
-    scene = pyassimp.load(filename)
-    
-    #the model we load
-    print("MODEL:", filename)
-    print()
-    
-    #write some statistics
-    print("SCENE:")
-    print("  meshes:", len(scene.meshes))
-    print("  materials:", len(scene.materials))
-    print("  textures:", len(scene.textures))
-    print()
-    
-    print("MESHES:")
-    for index, mesh in enumerate(scene.meshes):
-        print("  MESH", index+1)
-        print("    material:", mesh.mMaterialIndex+1)
-        print("    vertices:", len(mesh.vertices))
-        print("    first 3 verts:", mesh.vertices[:3])
-        #if len(mesh.normals):
-        #        print "    first 3 normals:", mesh.normals[:3]
-        print("    colors:", len(mesh.colors))
-        tc = mesh.texcoords
-        print("    texture-coords 1:", len(tc[0]), "first3:", tc[0][:3])
-        print("    texture-coords 2:", len(tc[1]), "first3:", tc[1][:3])
-        print("    texture-coords 3:", len(tc[2]), "first3:", tc[2][:3])
-        print("    texture-coords 4:", len(tc[3]), "first3:", tc[3][:3])
-        print("    uv-component-count:", len(mesh.mNumUVComponents))
-        print("    faces:", len(mesh.faces), "first:", [f.indices for f in mesh.faces[:3]])
-        print("    bones:", len(mesh.bones), "first:", [b.mName for b in mesh.bones[:3]])
-        print()
-
-    print("MATERIALS:")
-    for index, material in enumerate(scene.materials):
-        print("  MATERIAL", index+1)
-        properties = pyassimp.GetMaterialProperties(material)
-        for key in properties:
-            print("    %s: %s" % (key, properties[key]))
-    print()
-    
-    print("TEXTURES:")
-    for index, texture in enumerate(scene.textures):
-        print("  TEXTURE", index+1)
-        print("    width:", texture.mWidth)
-        print("    height:", texture.mHeight)
-        print("    hint:", texture.achFormatHint)
-        print("    data (size):", texture.mWidth*texture.mHeight)
-   
-    # Finally release the model
-    pyassimp.release(scene)
-
-if __name__ == "__main__":
-    main(sys.argv[1] if len(sys.argv)>1 else None)

+ 13 - 0
samples/SimpleOpenGL/Sample_SimpleOpenGL.c

@@ -11,6 +11,7 @@
 // ----------------------------------------------------------------------------
 
 #include <stdlib.h>
+#include <stdio.h>
 
 #include <GL/glut.h>
 
@@ -235,11 +236,23 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
 void do_motion (void)
 {
 	static GLint prev_time = 0;
+	static GLint prev_fps_time = 0;
+	static int frames = 0;
 
 	int time = glutGet(GLUT_ELAPSED_TIME);
 	angle += (time-prev_time)*0.01;
 	prev_time = time;
 
+	frames += 1;
+	if ((time - prev_fps_time) > 1000) // update every seconds
+    {
+        int current_fps = frames * 1000 / (time - prev_fps_time);
+        printf("%d fps\n", current_fps);
+        frames = 0;
+        prev_fps_time = time;
+    }
+
+
 	glutPostRedisplay ();
 }