Forráskód Böngészése

Merge pull request #327 from Gargaj/assbinintegrate

Integrate import/export for .ASSBIN format
Kim Kulling 11 éve
szülő
commit
63a110468f

+ 752 - 0
code/AssbinExporter.cpp

@@ -0,0 +1,752 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/** @file  AssbinExporter.cpp
+ *  ASSBIN exporter main code
+ */
+#include "AssimpPCH.h"
+#include "assbin_chunks.h"
+#include "./../include/assimp/version.h"
+#include "ProcessHelper.h"
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#	include <zlib.h>
+#else
+#	include "../contrib/zlib/zlib.h"
+#endif
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp	{
+
+template <typename T> 
+size_t Write(IOStream * stream, const T& v)
+{
+	return stream->Write( &v, sizeof(T), 1 );
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiString
+template <>
+inline size_t Write<aiString>(IOStream * stream, const aiString& s)
+{
+	const size_t s2 = (uint32_t)s.length;
+	stream->Write(&s,4,1);
+	stream->Write(s.data,s2,1);
+	return s2+4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint32_t
+template <>
+inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
+{
+	const uint32_t t = (uint32_t)w;
+	if (w > t) {
+		// this shouldn't happen, integers in Assimp data structures never exceed 2^32
+		throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
+	}
+
+	stream->Write(&t,4,1);
+	return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint16_t
+template <>
+inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
+{
+	BOOST_STATIC_ASSERT(sizeof(uint16_t)==2);
+	stream->Write(&w,2,1);
+	return 2;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a float
+template <>
+inline size_t Write<float>(IOStream * stream, const float& f)
+{
+	BOOST_STATIC_ASSERT(sizeof(float)==4);
+	stream->Write(&f,4,1);
+	return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a double
+template <>
+inline size_t Write<double>(IOStream * stream, const double& f)
+{
+	BOOST_STATIC_ASSERT(sizeof(double)==8);
+	stream->Write(&f,8,1);
+	return 8;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a vec3
+template <>
+inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
+{
+	size_t t = Write<float>(stream,v.x);
+	t += Write<float>(stream,v.y);
+	t += Write<float>(stream,v.z);
+	return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a color value
+template <>
+inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
+{
+	size_t t = Write<float>(stream,v.r);
+	t += Write<float>(stream,v.g);
+	t += Write<float>(stream,v.b);
+	t += Write<float>(stream,v.a);
+	return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a quaternion
+template <>
+inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
+{
+	size_t t = Write<float>(stream,v.w);
+	t += Write<float>(stream,v.x);
+	t += Write<float>(stream,v.y);
+	t += Write<float>(stream,v.z);
+	return 16;
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize a vertex weight
+template <>
+inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
+{
+	size_t t = Write<unsigned int>(stream,v.mVertexId);
+	return t+Write<float>(stream,v.mWeight);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a mat4x4
+template <>
+inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
+{
+	for (unsigned int i = 0; i < 4;++i) {
+		for (unsigned int i2 = 0; i2 < 4;++i2) {
+			Write<float>(stream,m[i][i2]);
+		}
+	}
+	return 64;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiVectorKey
+template <>
+inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
+{
+	const size_t t = Write<double>(stream,v.mTime);
+	return t + Write<aiVector3D>(stream,v.mValue);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiQuatKey
+template <>
+inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
+{
+	const size_t t = Write<double>(stream,v.mTime);
+	return t + Write<aiQuaternion>(stream,v.mValue);
+}
+
+template <typename T>
+inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
+{
+	T minc,maxc;
+	ArrayBounds(in,size,minc,maxc);
+
+	const size_t t = Write<T>(stream,minc);
+	return t + Write<T>(stream,maxc);
+}
+
+	// ----------------------------------------------------------------------------------
+	/**	@class	AssbinChunkWriter
+	 *	@brief	Chunk writer mechanism for the .assbin file structure
+	 *
+	 *  This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
+	 *  the difference being that this takes another IOStream as a "container" in the
+	 *  constructor, and when it is destroyed, it appends the magic number, the chunk size,
+	 *  and the chunk contents to the container stream. This allows relatively easy chunk
+	 *  chunk construction, even recursively.
+	 */
+	class AssbinChunkWriter : public IOStream
+	{
+	private:
+
+		uint8_t* buffer;
+		uint32_t magic;
+		IOStream * container;
+		size_t cur_size, cursor, initial;
+
+	private:
+		// -------------------------------------------------------------------
+		void Grow(size_t need = 0) 
+		{
+			size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+
+			const uint8_t* const old = buffer;
+			buffer = new uint8_t[new_size];
+
+			if (old) {
+				memcpy(buffer,old,cur_size);
+				delete[] old;
+			}
+
+			cur_size = new_size;
+		}
+
+	public:
+
+		AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) 
+			: buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
+		{
+		}
+
+		virtual ~AssbinChunkWriter() 
+		{
+			if (container) {
+				container->Write( &magic, sizeof(uint32_t), 1 );
+				container->Write( &cursor, sizeof(uint32_t), 1 );
+				container->Write( buffer, 1, cursor );
+			}
+			if (buffer) delete[] buffer;
+		}
+
+		void * GetBufferPointer() { return buffer; };
+
+		// -------------------------------------------------------------------
+		virtual size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { return 0; };
+		virtual aiReturn Seek(size_t pOffset, aiOrigin pOrigin) { return aiReturn_FAILURE; };
+		virtual size_t Tell() const { return cursor; };
+		virtual void Flush() { };
+
+		virtual size_t FileSize() const
+		{
+			return cursor;
+		}
+
+		// -------------------------------------------------------------------
+		virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) 
+		{
+			pSize *= pCount;
+			if (cursor + pSize > cur_size) {
+				Grow(cursor + pSize);
+			}
+
+			memcpy(buffer+cursor, pvBuffer, pSize);
+			cursor += pSize;
+
+			return pCount; 
+		}
+
+	};
+
+	// ----------------------------------------------------------------------------------
+	/**	@class	AssbinExport
+	 *	@brief	Assbin exporter class
+	 *
+	 *  This class performs the .assbin exporting, and is responsible for the file layout.
+	 */
+	class AssbinExport
+	{
+	private:
+		bool shortened;
+		bool compressed;
+
+	protected:
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryNode( IOStream * container, const aiNode* node)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
+
+			Write<aiString>(&chunk,node->mName);
+			Write<aiMatrix4x4>(&chunk,node->mTransformation);
+			Write<unsigned int>(&chunk,node->mNumChildren);
+			Write<unsigned int>(&chunk,node->mNumMeshes);
+
+			for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+				Write<unsigned int>(&chunk,node->mMeshes[i]);
+			}
+
+			for (unsigned int i = 0; i < node->mNumChildren;++i) {
+				WriteBinaryNode( &chunk, node->mChildren[i] );
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
+
+			Write<unsigned int>(&chunk,tex->mWidth);
+			Write<unsigned int>(&chunk,tex->mHeight);
+			chunk.Write( tex->achFormatHint, sizeof(char), 4 );
+
+			if(!shortened) {
+				if (!tex->mHeight) {
+					chunk.Write(tex->pcData,1,tex->mWidth);
+				}
+				else {
+					chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+				}
+			}
+
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryBone(IOStream * container, const aiBone* b)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
+
+			Write<aiString>(&chunk,b->mName);
+			Write<unsigned int>(&chunk,b->mNumWeights);
+			Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
+
+			// for the moment we write dumb min/max values for the bones, too.
+			// maybe I'll add a better, hash-like solution later
+			if (shortened) {
+				WriteBounds(&chunk,b->mWeights,b->mNumWeights);
+			} // else write as usual
+			else chunk.Write(b->mWeights,1,b->mNumWeights*sizeof(aiVertexWeight));
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
+
+			Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
+			Write<unsigned int>(&chunk,mesh->mNumVertices);
+			Write<unsigned int>(&chunk,mesh->mNumFaces);
+			Write<unsigned int>(&chunk,mesh->mNumBones);
+			Write<unsigned int>(&chunk,mesh->mMaterialIndex);
+
+			// first of all, write bits for all existent vertex components
+			unsigned int c = 0;
+			if (mesh->mVertices) {
+				c |= ASSBIN_MESH_HAS_POSITIONS;
+			}
+			if (mesh->mNormals) {
+				c |= ASSBIN_MESH_HAS_NORMALS;
+			}
+			if (mesh->mTangents && mesh->mBitangents) {
+				c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+				if (!mesh->mTextureCoords[n]) {
+					break;
+				}
+				c |= ASSBIN_MESH_HAS_TEXCOORD(n);
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+				if (!mesh->mColors[n]) {
+					break;
+				}
+				c |= ASSBIN_MESH_HAS_COLOR(n);
+			}
+			Write<unsigned int>(&chunk,c);
+
+			aiVector3D minVec, maxVec;
+			if (mesh->mVertices) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
+				} // else write as usual
+				else chunk.Write(mesh->mVertices,1,12*mesh->mNumVertices);
+			}
+			if (mesh->mNormals) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
+				} // else write as usual
+				else chunk.Write(mesh->mNormals,1,12*mesh->mNumVertices);
+			}
+			if (mesh->mTangents && mesh->mBitangents) {
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
+					WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
+				} // else write as usual
+				else {
+					chunk.Write(mesh->mTangents,1,12*mesh->mNumVertices);
+					chunk.Write(mesh->mBitangents,1,12*mesh->mNumVertices);
+				}
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+				if (!mesh->mColors[n])
+					break;
+
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
+				} // else write as usual
+				else chunk.Write(mesh->mColors[n],16*mesh->mNumVertices,1);
+			}
+			for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+				if (!mesh->mTextureCoords[n])
+					break;
+
+				// write number of UV components
+				Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
+
+				if (shortened) {
+					WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+				} // else write as usual
+				else chunk.Write(mesh->mTextureCoords[n],12*mesh->mNumVertices,1);
+			}
+
+			// write faces. There are no floating-point calculations involved
+			// in these, so we can write a simple hash over the face data
+			// to the dump file. We generate a single 32 Bit hash for 512 faces
+			// using Assimp's standard hashing function.
+			if (shortened) {
+				unsigned int processed = 0;
+				for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
+
+					uint32_t hash = 0;
+					for (unsigned int a = 0; a < job;++a) {
+
+						const aiFace& f = mesh->mFaces[processed+a];
+						uint32_t tmp = f.mNumIndices;
+						hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+						for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+							BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff);
+							tmp = static_cast<uint32_t>( f.mIndices[i] );
+							hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+						}
+					}
+					Write<unsigned int>(&chunk,hash);
+				}
+			}
+			else // else write as usual
+			{
+				// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+				for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+					const aiFace& f = mesh->mFaces[i];
+
+					BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+					Write<uint16_t>(&chunk,f.mNumIndices);
+
+					for (unsigned int a = 0; a < f.mNumIndices;++a) {
+						if (mesh->mNumVertices < (1u<<16)) {
+							Write<uint16_t>(&chunk,f.mIndices[a]);
+						}
+						else Write<unsigned int>(&chunk,f.mIndices[a]);
+					}
+				}
+			}
+
+			// write bones
+			if (mesh->mNumBones) {
+				for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+					const aiBone* b = mesh->mBones[a];
+					WriteBinaryBone(&chunk,b);
+				}
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
+
+			Write<aiString>(&chunk,prop->mKey);
+			Write<unsigned int>(&chunk,prop->mSemantic);
+			Write<unsigned int>(&chunk,prop->mIndex);
+
+			Write<unsigned int>(&chunk,prop->mDataLength);
+			Write<unsigned int>(&chunk,(unsigned int)prop->mType);
+			chunk.Write(prop->mData,1,prop->mDataLength);
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
+
+			Write<unsigned int>(&chunk,mat->mNumProperties);
+			for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+				WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
+
+			Write<aiString>(&chunk,nd->mNodeName);
+			Write<unsigned int>(&chunk,nd->mNumPositionKeys);
+			Write<unsigned int>(&chunk,nd->mNumRotationKeys);
+			Write<unsigned int>(&chunk,nd->mNumScalingKeys);
+			Write<unsigned int>(&chunk,nd->mPreState);
+			Write<unsigned int>(&chunk,nd->mPostState);
+
+			if (nd->mPositionKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+
+				} // else write as usual
+				else chunk.Write(nd->mPositionKeys,1,nd->mNumPositionKeys*sizeof(aiVectorKey));
+			}
+			if (nd->mRotationKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+
+				} // else write as usual
+				else chunk.Write(nd->mRotationKeys,1,nd->mNumRotationKeys*sizeof(aiQuatKey));
+			}
+			if (nd->mScalingKeys) {
+				if (shortened) {
+					WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+
+				} // else write as usual
+				else chunk.Write(nd->mScalingKeys,1,nd->mNumScalingKeys*sizeof(aiVectorKey));
+			}
+		}
+
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
+
+			Write<aiString>(&chunk,anim->mName);
+			Write<double>(&chunk,anim->mDuration);
+			Write<double>(&chunk,anim->mTicksPerSecond);
+			Write<unsigned int>(&chunk,anim->mNumChannels);
+
+			for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+				const aiNodeAnim* nd = anim->mChannels[a];
+				WriteBinaryNodeAnim(&chunk,nd);	
+			}
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryLight( IOStream * container, const aiLight* l )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
+
+			Write<aiString>(&chunk,l->mName);
+			Write<unsigned int>(&chunk,l->mType);
+
+			if (l->mType != aiLightSource_DIRECTIONAL) { 
+				Write<float>(&chunk,l->mAttenuationConstant);
+				Write<float>(&chunk,l->mAttenuationLinear);
+				Write<float>(&chunk,l->mAttenuationQuadratic);
+			}
+
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
+			Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
+
+			if (l->mType == aiLightSource_SPOT) {
+				Write<float>(&chunk,l->mAngleInnerCone);
+				Write<float>(&chunk,l->mAngleOuterCone);
+			}
+
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
+
+			Write<aiString>(&chunk,cam->mName);
+			Write<aiVector3D>(&chunk,cam->mPosition);
+			Write<aiVector3D>(&chunk,cam->mLookAt);
+			Write<aiVector3D>(&chunk,cam->mUp);
+			Write<float>(&chunk,cam->mHorizontalFOV);
+			Write<float>(&chunk,cam->mClipPlaneNear);
+			Write<float>(&chunk,cam->mClipPlaneFar);
+			Write<float>(&chunk,cam->mAspect);
+		}
+
+		// -----------------------------------------------------------------------------------
+		void WriteBinaryScene( IOStream * container, const aiScene* scene)
+		{
+			AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
+
+			// basic scene information
+			Write<unsigned int>(&chunk,scene->mFlags);
+			Write<unsigned int>(&chunk,scene->mNumMeshes);
+			Write<unsigned int>(&chunk,scene->mNumMaterials);
+			Write<unsigned int>(&chunk,scene->mNumAnimations);
+			Write<unsigned int>(&chunk,scene->mNumTextures);
+			Write<unsigned int>(&chunk,scene->mNumLights);
+			Write<unsigned int>(&chunk,scene->mNumCameras);
+
+			// write node graph
+			WriteBinaryNode( &chunk, scene->mRootNode );
+
+			// write all meshes
+			for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+				const aiMesh* mesh = scene->mMeshes[i];
+				WriteBinaryMesh( &chunk,mesh);
+			}
+
+			// write materials
+			for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+				const aiMaterial* mat = scene->mMaterials[i];
+				WriteBinaryMaterial(&chunk,mat);
+			}
+
+			// write all animations
+			for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+				const aiAnimation* anim = scene->mAnimations[i];
+				WriteBinaryAnim(&chunk,anim);
+			}
+
+
+			// write all textures
+			for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+				const aiTexture* mesh = scene->mTextures[i];
+				WriteBinaryTexture(&chunk,mesh);
+			}
+
+			// write lights
+			for (unsigned int i = 0; i < scene->mNumLights;++i) {
+				const aiLight* l = scene->mLights[i];
+				WriteBinaryLight(&chunk,l);
+			}
+
+			// write cameras
+			for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+				const aiCamera* cam = scene->mCameras[i];
+				WriteBinaryCamera(&chunk,cam);
+			}
+
+		}
+
+	public:
+		AssbinExport() 
+			: shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
+		{
+		}
+
+		// -----------------------------------------------------------------------------------
+		// Write a binary model dump
+		void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+		{
+			IOStream * out = pIOSystem->Open( pFile, "wb" );
+			if (!out) return;
+
+			time_t tt = time(NULL);
+			tm* p     = gmtime(&tt);
+
+			// header
+			char s[64];
+			memset( s, 0, 64 );
+#if _MSC_VER >= 1400
+			sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
+#else
+			snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
+#endif
+			out->Write( s, 44, 1 );
+			// == 44 bytes
+
+			Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
+			Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
+			Write<unsigned int>( out, aiGetVersionRevision() );
+			Write<unsigned int>( out, aiGetCompileFlags() );
+			Write<uint16_t>( out, shortened );
+			Write<uint16_t>( out, compressed );
+			// ==  20 bytes
+
+			char buff[256]; 
+			strncpy(buff,pFile,256);
+			out->Write(buff,sizeof(char),256);
+
+			char cmd[] = "\0";
+			strncpy(buff,cmd,128);
+			out->Write(buff,sizeof(char),128);
+
+			// leave 64 bytes free for future extensions
+			memset(buff,0xcd,64);
+			out->Write(buff,sizeof(char),64);
+			// == 435 bytes
+
+			// ==== total header size: 512 bytes
+			ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
+
+			// Up to here the data is uncompressed. For compressed files, the rest
+			// is compressed using standard DEFLATE from zlib.
+			if (compressed)
+			{
+				AssbinChunkWriter uncompressedStream( NULL, NULL );
+				WriteBinaryScene( &uncompressedStream, pScene );
+
+				uLongf uncompressedSize = uncompressedStream.Tell();
+				uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
+				uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
+
+				compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
+
+				out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
+				out->Write( compressedBuffer, sizeof(char), compressedSize );
+
+				delete[] compressedBuffer;
+			}
+			else
+			{
+				WriteBinaryScene( out, pScene );
+			}
+
+			pIOSystem->Close( out );
+		}
+	};
+
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+{
+	AssbinExport exporter;
+	exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
+}
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 49 - 0
code/AssbinExporter.h

@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file AssbinExporter.h
+ * ASSBIN Exporter Main Header
+ */
+#ifndef AI_ASSBINEXPORTER_H_INC
+#define AI_ASSBINEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif

+ 606 - 0
code/AssbinLoader.cpp

@@ -0,0 +1,606 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file  AssbinLoader.cpp
+ *  @brief Implementation of the .assbin importer class
+ *
+ *  see assbin_chunks.h
+ */
+
+#include "AssimpPCH.h"
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+// internal headers
+#include "AssbinLoader.h"
+#include "assbin_chunks.h"
+#include "MemoryIOWrapper.h"
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#	include <zlib.h>
+#else
+#	include "../contrib/zlib/zlib.h"
+#endif
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+	".assbin Importer",
+	"Gargaj / Conspiracy",
+	"",
+	"",
+	aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+	0,
+	0,
+	0,
+	0,
+	"assbin" 
+};
+
+const aiImporterDesc* AssbinImporter::GetInfo() const
+{
+	return &desc;
+}
+
+bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const
+{
+	IOStream * in = pIOHandler->Open(pFile);
+	if (!in)
+		return false;
+
+	char s[32];
+	in->Read( s, sizeof(char), 32 );
+
+	pIOHandler->Close(in);
+
+	return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
+}
+
+template <typename T>
+T Read(IOStream * stream)
+{
+	T t;
+	stream->Read( &t, sizeof(T), 1 );
+	return t;
+}
+
+template <>
+aiString Read<aiString>(IOStream * stream)
+{
+	aiString s;
+	stream->Read(&s.length,4,1);
+	stream->Read(s.data,s.length,1);
+	return s;
+}
+
+template <>
+aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
+{
+	aiMatrix4x4 m;
+	for (unsigned int i = 0; i < 4;++i) {
+		for (unsigned int i2 = 0; i2 < 4;++i2) {
+			m[i][i2] = Read<float>(stream);
+		}
+	}
+	return m;
+}
+
+template <typename T> void ReadBounds( IOStream * stream, T* p, unsigned int n )
+{
+	// not sure what to do here, the data isn't really useful.
+	stream->Seek( sizeof(T) * n, aiOrigin_CUR );
+}
+
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODE);
+	uint32_t size = Read<uint32_t>(stream);
+
+	*node = new aiNode();
+
+	(*node)->mName = Read<aiString>(stream);
+	(*node)->mTransformation = Read<aiMatrix4x4>(stream);
+	(*node)->mNumChildren = Read<unsigned int>(stream);
+	(*node)->mNumMeshes = Read<unsigned int>(stream);
+
+	if ((*node)->mNumMeshes)
+	{
+		(*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
+		for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
+			(*node)->mMeshes[i] = Read<unsigned int>(stream);
+		}
+	}
+
+	if ((*node)->mNumChildren)
+	{
+		(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
+		for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
+			ReadBinaryNode( stream, &(*node)->mChildren[i] );
+		}
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIBONE );
+	uint32_t size = Read<uint32_t>(stream);
+
+	b->mName = Read<aiString>(stream);
+	b->mNumWeights = Read<unsigned int>(stream);
+	b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
+
+	// for the moment we write dumb min/max values for the bones, too.
+	// maybe I'll add a better, hash-like solution later
+	if (shortened) 
+	{
+		ReadBounds(stream,b->mWeights,b->mNumWeights);
+	} // else write as usual
+	else 
+	{
+		b->mWeights = new aiVertexWeight[b->mNumWeights];
+		stream->Read(b->mWeights,1,b->mNumWeights*sizeof(aiVertexWeight));
+	}
+}
+
+
+void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMESH);
+	uint32_t size = Read<uint32_t>(stream);
+
+	mesh->mPrimitiveTypes = Read<unsigned int>(stream);
+	mesh->mNumVertices = Read<unsigned int>(stream);
+	mesh->mNumFaces = Read<unsigned int>(stream);
+	mesh->mNumBones = Read<unsigned int>(stream);
+	mesh->mMaterialIndex = Read<unsigned int>(stream);
+
+	// first of all, write bits for all existent vertex components
+	unsigned int c = Read<unsigned int>(stream);
+
+	if (c & ASSBIN_MESH_HAS_POSITIONS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+			stream->Read(mesh->mVertices,1,12*mesh->mNumVertices);
+		}
+	}
+	if (c & ASSBIN_MESH_HAS_NORMALS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+			stream->Read(mesh->mNormals,1,12*mesh->mNumVertices);
+		}
+	}
+	if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) 
+	{
+		if (shortened) {
+			ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
+			ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mTangents = new aiVector3D[mesh->mNumVertices];
+			stream->Read(mesh->mTangents,1,12*mesh->mNumVertices);
+			mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
+			stream->Read(mesh->mBitangents,1,12*mesh->mNumVertices);
+		}
+	}
+	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) 
+	{
+		if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
+			break;
+
+		if (shortened) 
+		{
+			ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
+			stream->Read(mesh->mColors[n],16*mesh->mNumVertices,1);
+		}
+	}
+	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) 
+	{
+		if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
+			break;
+
+		// write number of UV components
+		mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
+
+		if (shortened) {
+			ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+		} // else write as usual
+		else 
+		{
+			mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+			stream->Read(mesh->mTextureCoords[n],12*mesh->mNumVertices,1);
+		}
+	}
+
+	// write faces. There are no floating-point calculations involved
+	// in these, so we can write a simple hash over the face data
+	// to the dump file. We generate a single 32 Bit hash for 512 faces
+	// using Assimp's standard hashing function.
+	if (shortened) {
+		Read<unsigned int>(stream);
+	}
+	else // else write as usual
+	{
+		// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+		mesh->mFaces = new aiFace[mesh->mNumFaces];
+		for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+			aiFace& f = mesh->mFaces[i];
+
+			BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+			f.mNumIndices = Read<uint16_t>(stream);
+			f.mIndices = new unsigned int[f.mNumIndices];
+
+			for (unsigned int a = 0; a < f.mNumIndices;++a) {
+				if (mesh->mNumVertices < (1u<<16)) 
+				{
+					f.mIndices[a] = Read<uint16_t>(stream);
+				}
+				else 
+				{
+					f.mIndices[a] = Read<unsigned int>(stream);
+				}
+			}
+		}
+	}
+
+	// write bones
+	if (mesh->mNumBones) {
+		mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
+		for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+			mesh->mBones[a] = new aiBone();
+			ReadBinaryBone(stream,mesh->mBones[a]);
+		}
+	}
+}
+
+void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIALPROPERTY);
+	uint32_t size = Read<uint32_t>(stream);
+
+	prop->mKey = Read<aiString>(stream);
+	prop->mSemantic = Read<unsigned int>(stream);
+	prop->mIndex = Read<unsigned int>(stream);
+
+	prop->mDataLength = Read<unsigned int>(stream);
+	prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
+	prop->mData = new char [ prop->mDataLength ];
+	stream->Read(prop->mData,1,prop->mDataLength);
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIAL);
+	uint32_t size = Read<uint32_t>(stream);
+
+	mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
+	if (mat->mNumProperties)
+	{
+		if (mat->mProperties) 
+		{
+			delete[] mat->mProperties;
+		}
+		mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
+		for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+			mat->mProperties[i] = new aiMaterialProperty();
+			ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
+		}
+	}
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODEANIM);
+	uint32_t size = Read<uint32_t>(stream);
+
+	nd->mNodeName = Read<aiString>(stream);
+	nd->mNumPositionKeys = Read<unsigned int>(stream);
+	nd->mNumRotationKeys = Read<unsigned int>(stream);
+	nd->mNumScalingKeys = Read<unsigned int>(stream);
+	nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
+	nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
+
+	if (nd->mNumPositionKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+
+		} // else write as usual
+		else {
+			nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+			stream->Read(nd->mPositionKeys,1,nd->mNumPositionKeys*sizeof(aiVectorKey));
+		}
+	}
+	if (nd->mNumRotationKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+
+		} // else write as usual
+		else 
+		{
+			nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+			stream->Read(nd->mRotationKeys,1,nd->mNumRotationKeys*sizeof(aiQuatKey));
+		}
+	}
+	if (nd->mNumScalingKeys) {
+		if (shortened) {
+			ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+
+		} // else write as usual
+		else 
+		{
+			nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+			stream->Read(nd->mScalingKeys,1,nd->mNumScalingKeys*sizeof(aiVectorKey));
+		}
+	}
+}
+
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIANIMATION);
+	uint32_t size = Read<uint32_t>(stream);
+
+	anim->mName = Read<aiString> (stream);
+	anim->mDuration = Read<double> (stream);
+	anim->mTicksPerSecond = Read<double> (stream);
+	anim->mNumChannels = Read<unsigned int>(stream);
+
+	if (anim->mNumChannels)
+	{
+		anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
+		for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+			anim->mChannels[a] = new aiNodeAnim();
+			ReadBinaryNodeAnim(stream,anim->mChannels[a]);
+		}
+	}
+}
+
+void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AITEXTURE);
+	uint32_t size = Read<uint32_t>(stream);
+
+	tex->mWidth = Read<unsigned int>(stream);
+	tex->mHeight = Read<unsigned int>(stream);
+	stream->Read( tex->achFormatHint, sizeof(char), 4 );
+
+	if(!shortened) {
+		if (!tex->mHeight) {
+			tex->pcData = new aiTexel[ tex->mWidth ];
+			stream->Read(tex->pcData,1,tex->mWidth);
+		}
+		else {
+			tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
+			stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+		}
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AILIGHT);
+	uint32_t size = Read<uint32_t>(stream);
+
+	l->mName = Read<aiString>(stream);
+	l->mType = (aiLightSourceType)Read<unsigned int>(stream);
+
+	if (l->mType != aiLightSource_DIRECTIONAL) { 
+		l->mAttenuationConstant = Read<float>(stream);
+		l->mAttenuationLinear = Read<float>(stream);
+		l->mAttenuationQuadratic = Read<float>(stream);
+	}
+
+	l->mColorDiffuse = Read<aiColor3D>(stream);
+	l->mColorSpecular = Read<aiColor3D>(stream);
+	l->mColorAmbient = Read<aiColor3D>(stream);
+
+	if (l->mType == aiLightSource_SPOT) {
+		l->mAngleInnerCone = Read<float>(stream);
+		l->mAngleOuterCone = Read<float>(stream);
+	}
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AICAMERA);
+	uint32_t size = Read<uint32_t>(stream);
+
+	cam->mName = Read<aiString>(stream);
+	cam->mPosition = Read<aiVector3D>(stream);
+	cam->mLookAt = Read<aiVector3D>(stream);
+	cam->mUp = Read<aiVector3D>(stream);
+	cam->mHorizontalFOV = Read<float>(stream);
+	cam->mClipPlaneNear = Read<float>(stream);
+	cam->mClipPlaneFar = Read<float>(stream);
+	cam->mAspect = Read<float>(stream);
+}
+
+void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
+{
+	ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AISCENE);
+	uint32_t size = Read<uint32_t>(stream);
+
+	scene->mFlags         = Read<unsigned int>(stream);
+	scene->mNumMeshes     = Read<unsigned int>(stream);
+	scene->mNumMaterials  = Read<unsigned int>(stream);
+	scene->mNumAnimations = Read<unsigned int>(stream);
+	scene->mNumTextures   = Read<unsigned int>(stream);
+	scene->mNumLights     = Read<unsigned int>(stream);
+	scene->mNumCameras    = Read<unsigned int>(stream);
+
+	// Read node graph
+	scene->mRootNode = new aiNode[1];
+	ReadBinaryNode( stream, &scene->mRootNode );
+
+	// Read all meshes
+	if (scene->mNumMeshes)
+	{
+		scene->mMeshes = new aiMesh*[scene->mNumMeshes];
+		for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+			scene->mMeshes[i] = new aiMesh();
+			ReadBinaryMesh( stream,scene->mMeshes[i]);
+		}
+	}
+
+	// Read materials
+	if (scene->mNumMaterials)
+	{
+		scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
+		for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+			scene->mMaterials[i] = new aiMaterial();
+			ReadBinaryMaterial(stream,scene->mMaterials[i]);
+		}
+	}
+
+	// Read all animations
+	if (scene->mNumAnimations)
+	{
+		scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
+		for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+			scene->mAnimations[i] = new aiAnimation();
+			ReadBinaryAnim(stream,scene->mAnimations[i]);
+		}
+	}
+
+	// Read all textures
+	if (scene->mNumTextures)
+	{
+		scene->mTextures = new aiTexture*[scene->mNumTextures];
+		for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+			scene->mTextures[i] = new aiTexture();
+			ReadBinaryTexture(stream,scene->mTextures[i]);
+		}
+	}
+
+	// Read lights
+	if (scene->mNumLights)
+	{
+		scene->mLights = new aiLight*[scene->mNumLights];
+		for (unsigned int i = 0; i < scene->mNumLights;++i) {
+			scene->mLights[i] = new aiLight();
+			ReadBinaryLight(stream,scene->mLights[i]);
+		}
+	}
+
+	// Read cameras
+	if (scene->mNumCameras)
+	{
+		scene->mCameras = new aiCamera*[scene->mNumCameras];
+		for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+			scene->mCameras[i] = new aiCamera();
+			ReadBinaryCamera(stream,scene->mCameras[i]);
+		}
+	}
+
+}
+
+void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
+{
+	IOStream * stream = pIOHandler->Open(pFile,"rb");
+	if (!stream)
+		return;
+
+	stream->Seek( 44, aiOrigin_CUR ); // signature
+
+	unsigned int versionMajor = Read<unsigned int>(stream);
+	unsigned int versionMinor = Read<unsigned int>(stream);
+	unsigned int versionRevision = Read<unsigned int>(stream);
+	unsigned int compileFlags = Read<unsigned int>(stream);
+
+	shortened = Read<uint16_t>(stream) > 0;
+	compressed = Read<uint16_t>(stream) > 0;
+
+	if (shortened)
+		throw DeadlyImportError( "Shortened binaries are not supported!" );
+
+	stream->Seek( 256, aiOrigin_CUR ); // original filename
+	stream->Seek( 128, aiOrigin_CUR ); // options
+	stream->Seek( 64, aiOrigin_CUR ); // padding
+
+	if (compressed)
+	{
+		uLongf uncompressedSize = Read<uint32_t>(stream);
+		uLongf compressedSize = stream->FileSize() - stream->Tell();
+
+		unsigned char * compressedData = new unsigned char[ compressedSize ];
+		stream->Read( compressedData, 1, compressedSize );
+
+		unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
+
+		uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
+
+		MemoryIOStream io( uncompressedData, uncompressedSize );
+
+		ReadBinaryScene(&io,pScene);
+
+		delete[] uncompressedData;
+		delete[] compressedData;
+	}
+	else
+	{
+		ReadBinaryScene(stream,pScene);
+	}
+	
+	pIOHandler->Close(stream);
+}
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER

+ 94 - 0
code/AssbinLoader.h

@@ -0,0 +1,94 @@
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the 
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file  AssbinLoader.h
+ *  @brief .assbin File format loader
+ */
+#ifndef AI_ASSBINIMPORTER_H_INC
+#define AI_ASSBINIMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include "../include/assimp/types.h"
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+namespace Assimp	{
+
+// ---------------------------------------------------------------------------------
+/** Importer class for 3D Studio r3 and r4 3DS files
+ */
+class AssbinImporter : public BaseImporter
+{
+private:
+  bool shortened;
+  bool compressed;
+protected:
+
+public:
+  virtual bool CanRead( 
+    const std::string& pFile, 
+    IOSystem* pIOHandler, 
+    bool checkSig
+    ) const;
+  virtual const aiImporterDesc* GetInfo() const;
+  virtual void InternReadFile( 
+    const std::string& pFile, 
+    aiScene* pScene, 
+    IOSystem* pIOHandler
+    );
+  void ReadBinaryScene( IOStream * stream, aiScene* pScene );
+  void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+  void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
+  void ReadBinaryBone( IOStream * stream, aiBone* bone );
+  void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
+  void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
+  void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
+  void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
+  void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
+  void ReadBinaryLight( IOStream * stream, aiLight* l );
+  void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
+};
+
+} // end of namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+#endif // AI_ASSBINIMPORTER_H_INC

+ 9 - 0
code/CMakeLists.txt

@@ -171,6 +171,14 @@ SET( ASE_SRCS
 )
 )
 SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 
 
+SET( ASSBIN_SRCS
+	AssbinExporter.h
+	AssbinExporter.cpp
+	AssbinLoader.h
+	AssbinLoader.cpp
+)
+SOURCE_GROUP( Assbin FILES ${ASSBIN_SRCS})
+
 SET( B3D_SRCS
 SET( B3D_SRCS
 	B3DImporter.cpp
 	B3DImporter.cpp
 	B3DImporter.h
 	B3DImporter.h
@@ -646,6 +654,7 @@ SET( assimp_src
 	${3DS_SRCS}
 	${3DS_SRCS}
 	${AC_SRCS}
 	${AC_SRCS}
 	${ASE_SRCS}
 	${ASE_SRCS}
+	${ASSBIN_SRCS}
 	${B3D_SRCS}
 	${B3D_SRCS}
 	${BVH_SRCS}
 	${BVH_SRCS}
 	${Collada_SRCS}
 	${Collada_SRCS}

+ 5 - 0
code/Exporter.cpp

@@ -79,6 +79,7 @@ void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // global array of all export formats which Assimp supports in its current build
 // global array of all export formats which Assimp supports in its current build
@@ -117,6 +118,10 @@ Exporter::ExportFormatEntry gExporters[] =
 	Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
 	Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
 		aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
 		aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
 #endif
 #endif
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+	Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, NULL),
+#endif
 };
 };
 
 
 #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
 #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))

+ 6 - 0
code/ImporterRegistry.cpp

@@ -166,6 +166,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 #   include "FBXImporter.h"
 #   include "FBXImporter.h"
 #endif 
 #endif 
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+#   include "AssbinLoader.h"
+#endif 
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
 #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
 	out.push_back( new FBXImporter() );
 	out.push_back( new FBXImporter() );
 #endif
 #endif
+#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
+	out.push_back( new AssbinImporter() );
+#endif
 }
 }
 
 
 }
 }