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
pull/1/head
sueastside 2009-04-25 21:12:53 +00:00
parent 01f558bcfe
commit 55a3d845c9
5 changed files with 307 additions and 568 deletions

View File

@ -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

View File

@ -12,479 +12,156 @@ import os
import helper
from errors import AssimpError
class aiArray:
"""
A python class to 'safely' access C arrays.
For m<Name> and mNum<Name> assimp class members.
"""
def __init__(self, instance, dataName, sizeName, i=None):
self.instance = instance
self.dataName = dataName
self.sizeName = sizeName
self.i = i
self.count = 0
def _GetSize(self):
return getattr(self.instance, self.sizeName)
def _GetData(self, index):
if self.i != None:
if not bool(getattr(self.instance, self.dataName)[self.i]):
return None
item = getattr(self.instance, self.dataName)[self.i][index]
else:
item = getattr(self.instance, self.dataName)[index]
if hasattr(item, 'contents'):
return item.contents._init()
elif hasattr(item, '_init'):
return item._init()
else:
return item
def next(self):
if self.count >= self._GetSize():
self.count = 0
raise StopIteration
else:
c = self.count
self.count += 1
return self._GetData(c)
def __getitem__(self, index):
if isinstance(index, slice):
indices = index.indices(len(self))
return [self.__getitem__(i) for i in range(*indices)]
if index < 0 or index >= self._GetSize():
raise IndexError("aiArray index out of range")
return self._GetData(index)
def __iter__(self):
return self
def __len__(self):
return int(self._GetSize())
def __str__(self):
return str([x for x in self])
def __repr__(self):
return str([x for x in self])
class aiTuple:
"""
A python class to 'safely' access C structs in a python tuple fashion.
For C structs like vectors, matrices, colors, ...
"""
def __init__(self, instance):
self.instance = instance
self.count = 0
def _GetSize(self):
return len(self.instance._fields_)
def _GetData(self, index):
return getattr(self.instance, self.instance._fields_[index][0])
def next(self):
if self.count >= self._GetSize():
self.count = 0
raise StopIteration
else:
c = self.count
self.count += 1
return self._GetData(c)
def __getitem__(self, index):
if 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

View File

@ -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))),
]

View File

@ -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()

View File

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