From 55a3d845c9fdeea5ae3409527bfe7b101839852c Mon Sep 17 00:00:00 2001 From: sueastside Date: Sat, 25 Apr 2009 21:12:53 +0000 Subject: [PATCH] Changed structs.py to export the original names of the C structs, not uppercase. Totally rewrote pyassimp, removing all pyassimp classes, instead using python's dynamic nature to expand the ctypes structures to include safe array access and python style tuple access. Updated helper.py and sample.py. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@406 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- port/PyAssimp/pyassimp/helper.py | 4 +- port/PyAssimp/pyassimp/pyassimp.py | 682 +++++++++-------------------- port/PyAssimp/pyassimp/structs.py | 150 +++---- port/PyAssimp/sample.py | 29 +- scripts/structsgen.py | 10 +- 5 files changed, 307 insertions(+), 568 deletions(-) diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index 7afeae273..c8173e680 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -54,9 +54,9 @@ def search_library(): pass else: #Library found! - load.restype = POINTER(structs.SCENE) + load.restype = POINTER(structs.Scene) - candidates.append((library, load, release)) + candidates.append((library, load, release, dll)) if not candidates: #no library found diff --git a/port/PyAssimp/pyassimp/pyassimp.py b/port/PyAssimp/pyassimp/pyassimp.py index 56d6b12a6..b7033b69b 100644 --- a/port/PyAssimp/pyassimp/pyassimp.py +++ b/port/PyAssimp/pyassimp/pyassimp.py @@ -12,479 +12,156 @@ 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 index < 0 or index >= self._GetSize(): + raise IndexError("aiTuple index out of range") + return self._GetData(index) + + def __iter__(self): + return self + + 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"): + setattr(getattr(structs, struct), '_init', _init) class AssimpLib(object): """ Assimp-Singleton """ - load, release = helper.search_library() - - - -class AssimpBase(object): - """ - Base class for all Assimp-classes. - """ - - @staticmethod - def _load_array(data, count, cons): - """ - Loads a whole array out of data, and constructs a new object. If data - is NULL, an empty list will be returned. - - data - pointer to array - count - size of the array - cons - constructor - - result array data - """ - if data: - return [cons(data[i]) for i in range(count)] - else: - return [] - - - @staticmethod - def make_loader(function): - """ - Creates a loader function for "_load_array". - - function - function to be applied to the content of an element - """ - def loader(x): - return function(x.contents) - - return loader - - -class Material(object): - """ - A Material. - """ - - def __init__(self, material): - """ - Converts the raw material data to a material. - """ - self.properties = self._load_properties(material.mProperties, - material.mNumProperties) - - - def _load_properties(self, data, size): - """ - Loads all properties of this mateiral. - - data - properties - size - elements in properties - """ - result = {} - - #read all properties - for i in range(size): - p = data[i].contents - - #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] = str(value) - - return result - - - def __repr__(self): - return repr(self.properties) - - - def __str__(self): - return str(self.properties) - - -class Matrix(AssimpBase): - """ - Assimp 4x4-matrix - """ - def __init__(self, matrix): - """ - Copies matrix data to this structure. - - matrix - raw matrix data - """ - m = matrix - - self.data = [ - [m.a1, m.a2, m.a3, m.a4], - [m.b1, m.b2, m.b3, m.b4], - [m.c1, m.c2, m.c3, m.c4], - [m.d1, m.d2, m.d3, m.d4], - ] - - - def __getitem__(self, index): - """ - Returns an item out of the matrix data. Use (row, column) to access - data directly or an natural number n to access the n-th row. - - index - matrix index - - result element or row - """ - try: - #tuple as index? - x, y = index - return data[x][y] - except TypeError: - #index as index - return data[index] - - - def __setitem__(self, index, value): - """ - Sets an item of the matrix data. Use (row, column) to access - data directly or an natural number n to access the n-th row. - - index - matrix index - value - new value - """ - try: - #tuple as index? - x, y = index - data[x][y] = value - except TypeError: - #index as index - data[index] = value - - -class VertexWeight(AssimpBase): - """ - Weight for vertices. - """ - - def __init__(self, weight): - """ - Copies vertex weights to this structure. - - weight - new weight - """ - #corresponding vertex id - self.vertex = weight.mVertexId - - #my weight - self.weight = weight.mWeight - - -class Bone(AssimpBase): - """ - Single bone of a mesh. A bone has a name by which it can be found - in the frame hierarchy and by which it can be addressed by animations. - """ - - def __init__(self, bone): - """ - Converts an ASSIMP-bone to a PyAssimp-bone. - """ - #the name is easy - self.name = str(bone.mName) - - #matrix that transforms from mesh space to bone space in bind pose - self.matrix = Matrix(bone.mOffsetMatrix) - - #and of course the weights! - Bone._load_array(bone.mWeights, - bone.mNumWeights, - VertexWeight) - - -class Texture(AssimpBase): - """ - Texture included in the model. - """ - - def __init__(self, texture): - """ - Convertes the raw data to a texture. - - texture - raw data - """ - #dimensions - self.width = texture.mWidth - self.height = texture.mHeight - - #format hint - self.hint = texture.achFormatHint - - #load data - self.data = self._load_data(texture) - - - def _load_data(self, texture): - """ - Loads the texture data. - - texture - the texture - - result texture data in (red, green, blue, alpha) - """ - if self.height == 0: - #compressed data - size = self.width - else: - size = self.width * self.height - - #load! - return Texture._load_array(texture.pcData, - size, - lambda x: (x.r, x.g, x.b, x.a)) - - -class Scene(AssimpBase): - """ - The root structure of the imported data. - Everything that was imported from the given file can be accessed from here. - """ - - #possible flags - FLAGS = {} - for key in structs.SCENE.__dict__: - if key.startswith("AI_SCENE_FLAGS_"): - FLAGS[structs.SCENE.__dict__[key]] = key - - def __init__(self, model): - """ - Converts the model-data to a real scene - - model - the raw model-data - """ - #process data - self._load(model) - - - def _load(self, model): - """ - Converts model from raw-data to fancy data! - - model - pointer to data - """ - #store scene flags - self.flags = model.mFlags - - #load mesh-data - self.meshes = Scene._load_array(model.mMeshes, - model.mNumMeshes, - Scene.make_loader(Mesh)) - - #load materials - self.materials = Scene._load_array(model.mMaterials, - model.mNumMaterials, - Scene.make_loader(Material)) - - #load textures - self.textures = Scene._load_array(model.mTextures, - model.mNumTextures, - Scene.make_loader(Texture)) - - - def list_flags(self): - """ - Returns a list of all used flags. - - result list of flags - """ - return [name for (key, value) in Scene.FLAGS.iteritems() - if (key & self.flags)>0] - - -class Face(AssimpBase): - """ - A single face in a mesh, referring to multiple vertices. - If the number of indices is 3, the face is a triangle, - for more than 3 it is a polygon. - - Point and line primitives are rarely used and are NOT supported. However, - a load could pass them as degenerated triangles. - """ - - def __init__(self, face): - """ - Loads a face from raw-data. - """ - self.indices = [face.mIndices[i] for i in range(face.mNumIndices)] - - - def __repr__(self): - return str(self.indices) - - -class Mesh(AssimpBase): - """ - A mesh represents a geometry or model with a single material. - It usually consists of a number of vertices and a series of primitives/faces - referencing the vertices. In addition there might be a series of bones, each - of them addressing a number of vertices with a certain weight. Vertex data - is presented in channels with each channel containing a single per-vertex - information such as a set of texture coords or a normal vector. - If a data pointer is non-null, the corresponding data stream is present. - - A Mesh uses only a single material which is referenced by a material ID. - """ - - def __init__(self, mesh): - """ - Loads mesh from raw-data. - """ - #process data - self._load(mesh) - - - def _load(self, mesh): - """ - Loads mesh-data from raw data - - mesh - raw mesh-data - """ - #load vertices - self.vertices = Mesh._load_array(mesh.mVertices, - mesh.mNumVertices, - helper.vec2tuple) - - #load normals - self.normals = Mesh._load_array(mesh.mNormals, - mesh.mNumVertices, - helper.vec2tuple) - - #load tangents - self.tangents = Mesh._load_array(mesh.mTangents, - mesh.mNumVertices, - helper.vec2tuple) - - #load bitangents - self.bitangents = Mesh._load_array(mesh.mBitangents, - mesh.mNumVertices, - helper.vec2tuple) - - #vertex color sets - self.colors = self._load_colors(mesh) - - #number of coordinates per uv-channel - self.uvsize = self._load_uv_component_count(mesh) - - #number of uv channels - self.texcoords = self._load_texture_coords(mesh) - - #the used material - self.material_index = int(mesh.mMaterialIndex) - - #faces - self.faces = self._load_faces(mesh) - - #bones - self.bones = self._load_bones(mesh) - - - def _load_bones(self, mesh): - """ - Loads bones of this mesh. - - mesh - mesh-data - - result bones - """ - count = mesh.mNumBones - - if count==0: - #no bones - return [] - - #read bones - bones = mesh.mBones.contents - return Mesh._load_array(bones, - count, - Bone) - - - def _load_faces(self, mesh): - """ - Loads all faces. - - mesh - mesh-data - - result faces - """ - return [Face(mesh.mFaces[i]) for i in range(mesh.mNumFaces)] - - - def _load_uv_component_count(self, mesh): - """ - Loads the number of components for a given UV channel. - - mesh - mesh-data - - result (count channel 1, count channel 2, ...) - """ - return tuple(mesh.mNumUVComponents[i] - for i in range(structs.MESH.AI_MAX_NUMBER_OF_TEXTURECOORDS)) - - - def _load_texture_coords(self, mesh): - """ - Loads texture coordinates. - - mesh - mesh-data - - result texture coordinates - """ - result = [] - - for i in range(structs.MESH.AI_MAX_NUMBER_OF_TEXTURECOORDS): - result.append(Mesh._load_array(mesh.mTextureCoords[i], - mesh.mNumVertices, - helper.vec2tuple)) - - return result - - - def _load_colors(self, mesh): - """ - Loads color sets. - - mesh - mesh with color sets - - result all color sets - """ - result = [] - - #for all possible sets - for i in range(structs.MESH.AI_MAX_NUMBER_OF_COLOR_SETS): - #try this set - x = mesh.mColors[i] - - if x: - channel = [] - - #read data for al vertices! - for j in range(mesh.mNumVertices): - c = x[j] - channel.append((c.r, c.g, c.b, c.a)) - - result.append(channel) - - - return result - - + load, release, dll = helper.search_library() #the loader as singleton _assimp_lib = AssimpLib() @@ -506,10 +183,69 @@ def load(filename, processing=0): if not model: #Uhhh, something went wrong! raise AssimpError, ("could not import file: %s" % filename) + + return model.contents._init() + +def release(scene): + _assimp_lib.release(scene) - try: - #create scene - return Scene(model.contents) - finally: - #forget raw data - _assimp_lib.release(model) +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("aiGetMaterialFloatArray 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 \ No newline at end of file diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 97fd5608a..665a87467 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -3,7 +3,7 @@ from ctypes import POINTER, c_int, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte -class MATRIX3X3(Structure): +class Matrix3x3(Structure): """ See 'aiMatrix3x3.h' for details. """ @@ -15,7 +15,7 @@ class MATRIX3X3(Structure): ("c1", c_float),("c2", c_float),("c3", c_float), ] -class MATRIX4X4(Structure): +class Matrix4x4(Structure): """ See 'aiMatrix4x4.h' for details. """ @@ -28,7 +28,7 @@ class MATRIX4X4(Structure): ("d1", c_float),("d2", c_float),("d3", c_float),("d4", c_float), ] -class FACE(Structure): +class Face(Structure): """ See 'aiMesh.h' for details. """ @@ -41,7 +41,7 @@ class FACE(Structure): ("mIndices", POINTER(c_uint)), ] -class VERTEXWEIGHT(Structure): +class VertexWeight(Structure): """ See 'aiMesh.h' for details. """ @@ -55,7 +55,7 @@ class VERTEXWEIGHT(Structure): ("mWeight", c_float), ] -class QUATERNION(Structure): +class Quaternion(Structure): """ See 'aiQuaternion.h' for details. """ @@ -66,7 +66,7 @@ class QUATERNION(Structure): ("w", c_float),("x", c_float),("y", c_float),("z", c_float), ] -class TEXEL(Structure): +class Texel(Structure): """ See 'aiTexture.h' for details. """ @@ -75,7 +75,7 @@ class TEXEL(Structure): ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte), ] -class PLANE(Structure): +class Plane(Structure): """ See 'aiTypes.h' for details. """ @@ -85,7 +85,7 @@ class PLANE(Structure): ("a", c_float),("b", c_float),("c", c_float),("d", c_float), ] -class COLOR3D(Structure): +class Color3D(Structure): """ See 'aiTypes.h' for details. """ @@ -95,7 +95,7 @@ class COLOR3D(Structure): ("r", c_float),("g", c_float),("b", c_float), ] -class COLOR4D(Structure): +class Color4D(Structure): """ See 'aiTypes.h' for details. """ @@ -105,7 +105,7 @@ class COLOR4D(Structure): ("r", c_float),("g", c_float),("b", c_float),("a", c_float), ] -class STRING(Structure): +class String(Structure): """ See 'aiTypes.h' for details. """ @@ -120,7 +120,7 @@ class STRING(Structure): ("data", c_char*MAXLEN), ] -class MEMORYINFO(Structure): +class MemoryInfo(Structure): """ See 'aiTypes.h' for details. """ @@ -151,7 +151,7 @@ class MEMORYINFO(Structure): ("total", c_uint), ] -class VECTOR2D(Structure): +class Vector2D(Structure): """ See 'aiVector2D.h' for details. """ @@ -161,7 +161,7 @@ class VECTOR2D(Structure): ("x", c_float),("y", c_float), ] -class VECTOR3D(Structure): +class Vector3D(Structure): """ See 'aiVector3D.h' for details. """ @@ -171,13 +171,13 @@ class VECTOR3D(Structure): ("x", c_float),("y", c_float),("z", c_float), ] -class NODE(Structure): +class Node(Structure): """ See 'aiScene.h' for details. """ -NODE._fields_ = [ +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. @@ -191,19 +191,19 @@ NODE._fields_ = [ #this text. You should be able to handle stuff like whitespace, tabs, #linefeeds, quotation marks, ampersands, ... . # - ("mName", STRING), + ("mName", String), #The transformation relative to the node's parent.# - ("mTransformation", MATRIX4X4), + ("mTransformation", Matrix4x4), #Parent node. NULL if this node is the root node.# - ("mParent", POINTER(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))), + ("mChildren", POINTER(POINTER(Node))), #The number of meshes of this node.# ("mNumMeshes", c_uint), @@ -212,7 +212,7 @@ NODE._fields_ = [ ("mMeshes", POINTER(c_uint)), ] -class VECTORKEY(Structure): +class VectorKey(Structure): """ See 'aiAnim.h' for details. """ @@ -221,10 +221,10 @@ class VECTORKEY(Structure): # The time of this key ("mTime", c_double), # The value of this key - ("mValue", VECTOR3D), + ("mValue", Vector3D), ] -class QUATKEY(Structure): +class QuatKey(Structure): """ See 'aiAnim.h' for details. """ @@ -233,10 +233,10 @@ class QUATKEY(Structure): # The time of this key ("mTime", c_double), # The value of this key - ("mValue", QUATERNION), + ("mValue", Quaternion), ] -class NODEANIM(Structure): +class NodeAnim(Structure): """ See 'aiAnim.h' for details. """ @@ -245,7 +245,7 @@ class NODEANIM(Structure): #The name of the node affected by this animation. The node # must exist and it must be unique. # - ("mNodeName", STRING), + ("mNodeName", String), #The number of position keys# ("mNumPositionKeys", c_uint), @@ -255,7 +255,7 @@ class NODEANIM(Structure): # #If there are position keys, there will also be at least one #scaling and one rotation key. # - ("mPositionKeys", POINTER(VECTORKEY)), + ("mPositionKeys", POINTER(VectorKey)), #The number of rotation keys# ("mNumRotationKeys", c_uint), @@ -266,7 +266,7 @@ class NODEANIM(Structure): # #If there are rotation keys, there will also be at least one #scaling and one position key. # - ("mRotationKeys", POINTER(QUATKEY)), + ("mRotationKeys", POINTER(QuatKey)), #The number of scaling keys# @@ -277,7 +277,7 @@ class NODEANIM(Structure): # #If there are scaling keys, there will also be at least one #position and one rotation key. # - ("mScalingKeys", POINTER(VECTORKEY)), + ("mScalingKeys", POINTER(VectorKey)), #Defines how the animation behaves before the first @@ -295,7 +295,7 @@ class NODEANIM(Structure): ("mPostState", c_uint), ] -class ANIMATION(Structure): +class Animation(Structure): """ See 'aiAnim.h' for details. """ @@ -305,7 +305,7 @@ class ANIMATION(Structure): # exported from does support only a single animation channel, this # name is usually empty (length is zero). # - ("mName", STRING), + ("mName", String), #Duration of the animation in ticks. # @@ -323,10 +323,10 @@ class ANIMATION(Structure): #The node animation channels. Each channel affects a single node. # The array is mNumChannels in size. # - ("mChannels", POINTER(POINTER(NODEANIM))), + ("mChannels", POINTER(POINTER(NodeAnim))), ] -class CAMERA(Structure): +class Camera(Structure): """ See 'aiCamera.h' for details. """ @@ -338,13 +338,13 @@ class CAMERA(Structure): # This node specifies the position of the camera in the scene # hierarchy and can be animated. # - ("mName", STRING), + ("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), + ("mPosition", Vector3D), #'Up' - vector of the camera coordinate system relative to @@ -354,7 +354,7 @@ class CAMERA(Structure): # The default value is 0|1|0. The vector # may be normalized, but it needn't. # - ("mUp", VECTOR3D), + ("mUp", Vector3D), #'LookAt' - vector of the camera coordinate system relative to @@ -363,7 +363,7 @@ class CAMERA(Structure): # The default value is 0|0|1. The vector # may be normalized, but it needn't. # - ("mLookAt", VECTOR3D), + ("mLookAt", Vector3D), #Half horizontal field of view angle, in radians. @@ -398,7 +398,7 @@ class CAMERA(Structure): ("mAspect", c_float), ] -class LIGHT(Structure): +class Light(Structure): """ See 'aiLight.h' for details. """ @@ -410,7 +410,7 @@ class LIGHT(Structure): # This node specifies the position of the light in the scene # hierarchy and can be animated. # - ("mName", STRING), + ("mName", String), #The type of the light source. # #aiLightSource_UNDEFINED is not a valid value for this member. @@ -421,14 +421,14 @@ class LIGHT(Structure): # transformation of the node corresponding to the light. # # The position is undefined for directional lights. # - ("mPosition", VECTOR3D), + ("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), + ("mDirection", Vector3D), #Constant light attenuation factor. # # The intensity of the light source at a given distance 'd' from @@ -469,14 +469,14 @@ class LIGHT(Structure): # material color to obtain the final color that contributes # to the diffuse shading term. # - ("mColorDiffuse", COLOR3D), + ("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), + ("mColorSpecular", Color3D), #Ambient color of the light source # # The ambient light color is multiplied with the ambient @@ -485,7 +485,7 @@ class LIGHT(Structure): # this value it, is just a remaining of the fixed-function pipeline # that is still supported by quite many file formats. # - ("mColorAmbient", COLOR3D), + ("mColorAmbient", Color3D), #Inner angle of a spot light's light cone. # # The spot light has maximum influence on objects inside this @@ -506,7 +506,7 @@ class LIGHT(Structure): ("mAngleOuterCone", c_float), ] -class UVTRANSFORM(Structure): +class UVTransform(Structure): """ See 'aiMaterial.h' for details. """ @@ -515,12 +515,12 @@ class UVTRANSFORM(Structure): #Translation on the u and v axes. # # The default value is (0|0). # - ("mTranslation", VECTOR2D), + ("mTranslation", Vector2D), #Scaling on the u and v axes. # # The default value is (1|1). # - ("mScaling", VECTOR2D), + ("mScaling", Vector2D), #Rotation - in counter-clockwise direction. # # The rotation angle is specified in radians. The @@ -530,7 +530,7 @@ class UVTRANSFORM(Structure): ("mRotation", c_float), ] -class MATERIALPROPERTY(Structure): +class MaterialProperty(Structure): """ See 'aiMaterial.h' for details. """ @@ -539,7 +539,7 @@ class MATERIALPROPERTY(Structure): #Specifies the name of the property (key) ## Keys are case insensitive. # - ("mKey", STRING), + ("mKey", String), #Textures: Specifies the exact usage semantic. # @@ -572,14 +572,14 @@ class MATERIALPROPERTY(Structure): ("mData", POINTER(c_char)), ] -class MATERIAL(Structure): +class Material(Structure): """ See 'aiMaterial.h' for details. """ _fields_ = [ #List of all material properties loaded.# - ("mProperties", POINTER(POINTER(MATERIALPROPERTY))), + ("mProperties", POINTER(POINTER(MaterialProperty))), #Number of properties in the data base# ("mNumProperties", c_uint), @@ -588,26 +588,26 @@ class MATERIAL(Structure): ("mNumAllocated", c_uint), ] -class BONE(Structure): +class Bone(Structure): """ See 'aiMesh.h' for details. """ _fields_ = [ # The name of the bone. - ("mName", STRING), + ("mName", String), # The number of vertices affected by this bone ("mNumWeights", c_uint), # The vertices affected by this bone - ("mWeights", POINTER(VERTEXWEIGHT)), + ("mWeights", POINTER(VertexWeight)), # Matrix that transforms from mesh space to bone space in bind pose - ("mOffsetMatrix", MATRIX4X4), + ("mOffsetMatrix", Matrix4x4), ] -class MESH(Structure): +class Mesh(Structure): """ See 'aiMesh.h' for details. """ @@ -637,7 +637,7 @@ class MESH(Structure): #This array is always present in a mesh. The array is #mNumVertices in size. # - ("mVertices", POINTER(VECTOR3D)), + ("mVertices", POINTER(Vector3D)), #Vertex normals. #The array contains normalized vectors, NULL if not present. @@ -657,7 +657,7 @@ class MESH(Structure): #However, this needn't apply for normals that have been taken # directly from the model file. # - ("mNormals", POINTER(VECTOR3D)), + ("mNormals", POINTER(Vector3D)), #Vertex tangents. #The tangent of a vertex points in the direction of the positive @@ -671,7 +671,7 @@ class MESH(Structure): #contains bitangents (the bitangent is just the cross product of #tangent and normal vectors). # - ("mTangents", POINTER(VECTOR3D)), + ("mTangents", POINTER(Vector3D)), #Vertex bitangents. #The bitangent of a vertex points in the direction of the positive @@ -680,20 +680,20 @@ class MESH(Structure): #@note If the mesh contains tangents, it automatically also contains #bitangents. # - ("mBitangents", POINTER(VECTOR3D)), + ("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), + ("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), + ("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 @@ -710,7 +710,7 @@ class MESH(Structure): #in mNumFaces. If the AI_SCENE_FLAGS_NON_VERBOSE_FORMAT #is NOT set each face references an unique set of vertices. # - ("mFaces", POINTER(FACE)), + ("mFaces", POINTER(Face)), #The number of bones this mesh contains. #Can be 0, in which case the mBones array is NULL. @@ -721,7 +721,7 @@ class MESH(Structure): #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))), + ("mBones", POINTER(POINTER(Bone))), #The material used by this mesh. #A mesh does use only a single material. If an imported model uses @@ -731,7 +731,7 @@ class MESH(Structure): ("mMaterialIndex", c_uint), ] -class TEXTURE(Structure): +class Texture(Structure): """ See 'aiTexture.h' for details. """ @@ -772,20 +772,20 @@ class TEXTURE(Structure): #buffer of size mWidth containing the compressed texture #data. Good luck, have fun! # - ("pcData", POINTER(TEXEL)), + ("pcData", POINTER(Texel)), ] -class RAY(Structure): +class Ray(Structure): """ See 'aiTypes.h' for details. """ _fields_ = [ # Position and direction of the ray - ("pos", VECTOR3D),("dir", VECTOR3D), + ("pos", Vector3D),("dir", Vector3D), ] -class SCENE(Structure): +class Scene(Structure): """ See 'aiScene.h' for details. """ @@ -812,7 +812,7 @@ class SCENE(Structure): #Presence of further nodes depends on the format and content #of the imported file. # - ("mRootNode", POINTER(NODE)), + ("mRootNode", POINTER(Node)), @@ -825,7 +825,7 @@ class SCENE(Structure): #AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always #be at least ONE material. # - ("mMeshes", POINTER(POINTER(MESH))), + ("mMeshes", POINTER(POINTER(Mesh))), @@ -839,7 +839,7 @@ class SCENE(Structure): #AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always #be at least ONE material. # - ("mMaterials", POINTER(POINTER(MATERIAL))), + ("mMaterials", POINTER(POINTER(Material))), @@ -850,7 +850,7 @@ class SCENE(Structure): # #All animations imported from the given file are listed here. #The array is mNumAnimations in size. # - ("mAnimations", POINTER(POINTER(ANIMATION))), + ("mAnimations", POINTER(POINTER(Animation))), @@ -863,7 +863,7 @@ class SCENE(Structure): #An example is Quake's MDL format (which is also used by #some GameStudio versions) # - ("mTextures", POINTER(POINTER(TEXTURE))), + ("mTextures", POINTER(POINTER(Texture))), #The number of light sources in the scene. Light sources @@ -876,7 +876,7 @@ class SCENE(Structure): #All light sources imported from the given file are #listed here. The array is mNumLights in size. # - ("mLights", POINTER(POINTER(LIGHT))), + ("mLights", POINTER(POINTER(Light))), #The number of cameras in the scene. Cameras @@ -891,5 +891,5 @@ class SCENE(Structure): #array (if existing) is the default camera view into #the scene. # - ("mCameras", POINTER(POINTER(CAMERA))), + ("mCameras", POINTER(POINTER(Camera))), ] diff --git a/port/PyAssimp/sample.py b/port/PyAssimp/sample.py index 0a366b56d..a6e001db5 100644 --- a/port/PyAssimp/sample.py +++ b/port/PyAssimp/sample.py @@ -11,7 +11,7 @@ import os #get a model out of assimp's test-data MODEL = os.path.join(os.path.dirname(__file__), "..", "..", - "test", "MDLFiles", "MDL3 (3DGS A4)", "minigun.MDL") + "test", "models", "MDL", "MDL3 (3DGS A4)", "minigun.MDL") def main(): scene = pyassimp.load(MODEL) @@ -22,7 +22,6 @@ def main(): #write some statistics print "SCENE:" - print " flags:", ", ".join(scene.list_flags()) print " meshes:", len(scene.meshes) print " materials:", len(scene.materials) print " textures:", len(scene.textures) @@ -31,6 +30,7 @@ def main(): 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:", mesh.vertices[:3] print " colors:", len(mesh.colors) @@ -39,26 +39,29 @@ def main(): print " texture-coords 2:", len(tc[1]), "first:", tc[1][:3] print " texture-coords 3:", len(tc[2]), "first:", tc[2][:3] print " texture-coords 4:", len(tc[3]), "first:", tc[3][:3] - print " uv-counts:", mesh.uvsize - print " faces:", len(mesh.faces), "first:", mesh.faces[:3] - print " bones:", len(mesh.bones), "first:", mesh.bones[: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 - for key, value in material.properties.iteritems(): - print " %s: %s" % (key, value) + 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.width - print " height:", texture.height - print " hint:", texture.hint - print " data (size):", len(texture.data) - + 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() \ No newline at end of file diff --git a/scripts/structsgen.py b/scripts/structsgen.py index 127cf8957..9307256a8 100644 --- a/scripts/structsgen.py +++ b/scripts/structsgen.py @@ -59,7 +59,7 @@ def restructure( match ): elif match.group("struct") == "C_ENUM ": type = "c_uint" else: - type = GetType(type[2:].upper(), '') + type = GetType(type[2:], '') if match.group("index"): type = type + "*" + match.group("index") @@ -123,11 +123,11 @@ def Structify(fileName): fileName = os.path.basename(fileName) print fileName for r in rs: - name = r.group('name')[2:].upper() + name = r.group('name')[2:] desc = r.group('desc') # Skip some structs - if name == "FILEIO" or name == "FILE" or name == "LOCATEFROMASSIMPHEAP": + if name == "FileIO" or name == "File" or name == "locateFromAssimpHeap": continue text = r.group('code') @@ -152,7 +152,7 @@ def Structify(fileName): # Whether it's selfreferencing: ex. struct Node { Node* parent; }; selfreferencing = text.find('POINTER('+name+')') != -1 - complex = name == "SCENE" + complex = name == "Scene" # Create description description = "" @@ -176,7 +176,7 @@ def Structify(fileName): text = text.replace('$DESCRIPTION$', description) text = text.replace('$FIELDS$', fields) - if ((name == fileName.split('.')[0][2:].upper()) and (name != 'MATERIAL')) or name == "STRING": + if ((name.lower() == fileName.split('.')[0][2:].lower()) and (name != 'Material')) or name == "String": text = text.replace('$DEFINES$', defines) else: text = text.replace('$DEFINES$', '')