From 4286c72e6089f42df209c089fa347701373eaba2 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Fri, 9 Nov 2012 11:39:34 +0000 Subject: [PATCH] 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 --- port/PyAssimp/README | 66 - port/PyAssimp/gen/structsgen.py | 23 +- port/PyAssimp/pyassimp/__init__.py | 1 - port/PyAssimp/pyassimp/helper.py | 57 +- port/PyAssimp/pyassimp/pyassimp.py | 276 ----- port/PyAssimp/pyassimp/structs.py | 1279 +++++++++++++------- port/PyAssimp/quicktest.py | 45 - port/PyAssimp/sample.py | 52 +- port/PyAssimp3/README | 65 - port/PyAssimp3/pyassimp/__init__.py | 1 - port/PyAssimp3/pyassimp/errors.py | 11 - port/PyAssimp3/pyassimp/helper.py | 119 -- port/PyAssimp3/pyassimp/pyassimp.py | 314 ----- port/PyAssimp3/pyassimp/structs.py | 424 ------- port/PyAssimp3/quicktest.py | 45 - port/PyAssimp3/sample.py | 71 -- samples/SimpleOpenGL/Sample_SimpleOpenGL.c | 13 + 17 files changed, 976 insertions(+), 1886 deletions(-) delete mode 100644 port/PyAssimp/README delete mode 100644 port/PyAssimp/pyassimp/pyassimp.py delete mode 100755 port/PyAssimp/quicktest.py mode change 100644 => 100755 port/PyAssimp/sample.py delete mode 100644 port/PyAssimp3/README delete mode 100644 port/PyAssimp3/pyassimp/__init__.py delete mode 100644 port/PyAssimp3/pyassimp/errors.py delete mode 100644 port/PyAssimp3/pyassimp/helper.py delete mode 100644 port/PyAssimp3/pyassimp/pyassimp.py delete mode 100644 port/PyAssimp3/pyassimp/structs.py delete mode 100644 port/PyAssimp3/quicktest.py delete mode 100644 port/PyAssimp3/sample.py diff --git a/port/PyAssimp/README b/port/PyAssimp/README deleted file mode 100644 index 1d4a71487..000000000 --- a/port/PyAssimp/README +++ /dev/null @@ -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. - - - - - - - diff --git a/port/PyAssimp/gen/structsgen.py b/port/PyAssimp/gen/structsgen.py index 8c356b0ba..f2ee95eb5 100644 --- a/port/PyAssimp/gen/structsgen.py +++ b/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', text) + text = RErpcom.sub('# \g', 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.") diff --git a/port/PyAssimp/pyassimp/__init__.py b/port/PyAssimp/pyassimp/__init__.py index 229d2296c..e69de29bb 100644 --- a/port/PyAssimp/pyassimp/__init__.py +++ b/port/PyAssimp/pyassimp/__init__.py @@ -1 +0,0 @@ -#-*- coding: UTF-8 -*- diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index ca7bd5d99..a01da375c 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -6,17 +6,20 @@ Some fancy helper functions. import os import ctypes -import structs -import operator - -from errors import AssimpError from ctypes import POINTER +import operator +import numpy + +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 diff --git a/port/PyAssimp/pyassimp/pyassimp.py b/port/PyAssimp/pyassimp/pyassimp.py deleted file mode 100644 index 36ecf22c3..000000000 --- a/port/PyAssimp/pyassimp/pyassimp.py +++ /dev/null @@ -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 and mNum 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() diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 54c02a2b8..fb98ee53d 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/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.#
#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. + #
+ # 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))), + ] diff --git a/port/PyAssimp/quicktest.py b/port/PyAssimp/quicktest.py deleted file mode 100755 index e01a49fa5..000000000 --- a/port/PyAssimp/quicktest.py +++ /dev/null @@ -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() - - - - diff --git a/port/PyAssimp/sample.py b/port/PyAssimp/sample.py old mode 100644 new mode 100755 index 626b142f0..3788bd065 --- a/port/PyAssimp/sample.py +++ b/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) diff --git a/port/PyAssimp3/README b/port/PyAssimp3/README deleted file mode 100644 index bba16e4bb..000000000 --- a/port/PyAssimp3/README +++ /dev/null @@ -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. - - - - - - - diff --git a/port/PyAssimp3/pyassimp/__init__.py b/port/PyAssimp3/pyassimp/__init__.py deleted file mode 100644 index 229d2296c..000000000 --- a/port/PyAssimp3/pyassimp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#-*- coding: UTF-8 -*- diff --git a/port/PyAssimp3/pyassimp/errors.py b/port/PyAssimp3/pyassimp/errors.py deleted file mode 100644 index 37db3c08a..000000000 --- a/port/PyAssimp3/pyassimp/errors.py +++ /dev/null @@ -1,11 +0,0 @@ -#-*- coding: UTF-8 -*- - -""" -All possible errors. -""" - -class AssimpError(BaseException): - """ - If an internal error occures. - """ - pass \ No newline at end of file diff --git a/port/PyAssimp3/pyassimp/helper.py b/port/PyAssimp3/pyassimp/helper.py deleted file mode 100644 index 540aa210f..000000000 --- a/port/PyAssimp3/pyassimp/helper.py +++ /dev/null @@ -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:] - - - diff --git a/port/PyAssimp3/pyassimp/pyassimp.py b/port/PyAssimp3/pyassimp/pyassimp.py deleted file mode 100644 index 3c253764a..000000000 --- a/port/PyAssimp3/pyassimp/pyassimp.py +++ /dev/null @@ -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 and mNum 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() diff --git a/port/PyAssimp3/pyassimp/structs.py b/port/PyAssimp3/pyassimp/structs.py deleted file mode 100644 index 54c02a2b8..000000000 --- a/port/PyAssimp3/pyassimp/structs.py +++ /dev/null @@ -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.#
#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))), - ] diff --git a/port/PyAssimp3/quicktest.py b/port/PyAssimp3/quicktest.py deleted file mode 100644 index e8494493c..000000000 --- a/port/PyAssimp3/quicktest.py +++ /dev/null @@ -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() - - - - diff --git a/port/PyAssimp3/sample.py b/port/PyAssimp3/sample.py deleted file mode 100644 index 02332ecb5..000000000 --- a/port/PyAssimp3/sample.py +++ /dev/null @@ -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) diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index a2b4502e2..921046a44 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -11,6 +11,7 @@ // ---------------------------------------------------------------------------- #include +#include #include @@ -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 (); }