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$', '')