Beispiel #1
0
/*
 ===================
 idRestoreGame::WriteTraceModel
 ===================
 */
void idSaveGame::WriteTraceModel( const idTraceModel &trace ) {
	int j, k;

	WriteInt( (int&)trace.type );
	WriteInt( trace.numVerts );
	for ( j = 0; j < MAX_TRACEMODEL_VERTS; j++ ) {
		WriteVec3( trace.verts[j] );
	}
	WriteInt( trace.numEdges );
	for ( j = 0; j < (MAX_TRACEMODEL_EDGES+1); j++ ) {
		WriteInt( trace.edges[j].v[0] );
		WriteInt( trace.edges[j].v[1] );
		WriteVec3( trace.edges[j].normal );
	}
	WriteInt( trace.numPolys );
	for ( j = 0; j < MAX_TRACEMODEL_POLYS; j++ ) {
		WriteVec3( trace.polys[j].normal );
		WriteFloat( trace.polys[j].dist );
		WriteBounds( trace.polys[j].bounds );
		WriteInt( trace.polys[j].numEdges );
		for ( k = 0; k < MAX_TRACEMODEL_POLYEDGES; k++ ) {
			WriteInt( trace.polys[j].edges[k] );
		}
	}
	WriteVec3( trace.offset );
	WriteBounds( trace.bounds );
	WriteBool( trace.isConvex );
	// padding win32 native structs
	char tmp[3];
	memset( tmp, 0, sizeof( tmp ) );
	file->Write( tmp, 3 );
}
/*
================
idSaveGame::WriteRenderEntity
================
*/
void idSaveGame::WriteRenderEntity( const renderEntity_t &renderEntity ) {
	int i;
	WriteModel( renderEntity.hModel );
	WriteInt( renderEntity.entityNum );
	WriteInt( renderEntity.bodyId );
	WriteBounds( renderEntity.bounds );
	// callback is set by class's Restore function
	WriteInt( renderEntity.suppressSurfaceInViewID );
	WriteInt( renderEntity.suppressShadowInViewID );
	WriteInt( renderEntity.suppressShadowInLightID );
	WriteInt( renderEntity.allowSurfaceInViewID );
	WriteVec3( renderEntity.origin );
	WriteMat3( renderEntity.axis );
	WriteMaterial( renderEntity.customShader );
	WriteMaterial( renderEntity.referenceShader );
	WriteSkin( renderEntity.customSkin );
	if( renderEntity.referenceSound != NULL ) {
		WriteInt( renderEntity.referenceSound->Index() );
	} else {
		WriteInt( 0 );
	}
	for( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
		WriteFloat( renderEntity.shaderParms[ i ] );
	}
	for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
		WriteUserInterface( renderEntity.gui[ i ], renderEntity.gui[ i ] ? renderEntity.gui[ i ]->IsUniqued() : false );
	}
	WriteFloat( renderEntity.modelDepthHack );
	WriteBool( renderEntity.noSelfShadow );
	WriteBool( renderEntity.noShadow );
	WriteBool( renderEntity.noDynamicInteractions );
	WriteBool( renderEntity.weaponDepthHack );
	WriteInt( renderEntity.forceUpdate );
}
Beispiel #3
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryNodeAnim(const aiNodeAnim* nd)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AINODEANIM);

	len += Write<aiString>(nd->mNodeName);
	len += Write<unsigned int>(nd->mNumPositionKeys);
	len += Write<unsigned int>(nd->mNumRotationKeys);
	len += Write<unsigned int>(nd->mNumScalingKeys);
	len += Write<unsigned int>(nd->mPreState);
	len += Write<unsigned int>(nd->mPostState);

	if (nd->mPositionKeys) {
		if (shortened) {
			len += WriteBounds(nd->mPositionKeys,nd->mNumPositionKeys);

		} // else write as usual
		else len += fwrite(nd->mPositionKeys,1,nd->mNumPositionKeys*sizeof(aiVectorKey),out);
	}
	if (nd->mRotationKeys) {
		if (shortened) {
			len += WriteBounds(nd->mRotationKeys,nd->mNumRotationKeys);

		} // else write as usual
		else len += fwrite(nd->mRotationKeys,1,nd->mNumRotationKeys*sizeof(aiQuatKey),out);
	}
	if (nd->mScalingKeys) {
		if (shortened) {
			len += WriteBounds(nd->mScalingKeys,nd->mNumScalingKeys);

		} // else write as usual
		else len += fwrite(nd->mScalingKeys,1,nd->mNumScalingKeys*sizeof(aiVectorKey),out);
	}

	ChangeInteger(old,len);
	return len;
}
Beispiel #4
0
int FrechetBounds1(LPTable table, const char* sFileName)
{
	if(table == NULL)
	{
		printf("Error :: FrechetBounds1.\n");
		return 0;
	}
	
	int k = table->nDimens;
	LPTable UpperBound = CreateMin(1, table);
	if(UpperBound == NULL)
	{
		printf("Error :: FrechetBounds1.\n");
		return 0;
	}
	
	LPTable LowerBound = CreateS(1, table);
	if(LowerBound == NULL)
	{
		printf("Error :: FrechetBounds1.\n");
		UpperBound->Reset();
		delete UpperBound;
		return 0;
	}
	
	double n = table->GetGrandTotal();
	int i;
	
	for(i=0; i<table->Total; i++)
	{
		LowerBound->Data[i] -= n*(k-1);
		if(LowerBound->Data[i] < 0.0)
		{
			LowerBound->Data[i] = 0.0;
		}
	}
	
	int rez = WriteBounds(UpperBound, LowerBound, sFileName);
	
	UpperBound->Reset();
	LowerBound->Reset();
	delete UpperBound;
	delete LowerBound;
	
	return rez;
}
Beispiel #5
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryBone(const aiBone* b)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIBONE);

	len += Write<aiString>(b->mName);
	len += Write<unsigned int>(b->mNumWeights);
	len += Write<aiMatrix4x4>(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) {
		len += WriteBounds(b->mWeights,b->mNumWeights);
	} // else write as usual
	else len += fwrite(b->mWeights,1,b->mNumWeights*sizeof(aiVertexWeight),out);

	ChangeInteger(old,len);
	return len;
}
Beispiel #6
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryMesh(const aiMesh* mesh)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMESH);

	len += Write<unsigned int>(mesh->mPrimitiveTypes);
	len += Write<unsigned int>(mesh->mNumVertices);
	len += Write<unsigned int>(mesh->mNumFaces);
	len += Write<unsigned int>(mesh->mNumBones);
	len += Write<unsigned int>(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);
	}
	len += Write<unsigned int>(c);

	aiVector3D minVec, maxVec;
	if (mesh->mVertices) {
		if (shortened) {
			len += WriteBounds(mesh->mVertices,mesh->mNumVertices);
		} // else write as usual
		else len += fwrite(mesh->mVertices,1,12*mesh->mNumVertices,out);
	}
	if (mesh->mNormals) {
		if (shortened) {
			len += WriteBounds(mesh->mNormals,mesh->mNumVertices);
		} // else write as usual
		else len += fwrite(mesh->mNormals,1,12*mesh->mNumVertices,out);
	}
	if (mesh->mTangents && mesh->mBitangents) {
		if (shortened) {
			len += WriteBounds(mesh->mTangents,mesh->mNumVertices);
			len += WriteBounds(mesh->mBitangents,mesh->mNumVertices);
		} // else write as usual
		else {
			len += fwrite(mesh->mTangents,1,12*mesh->mNumVertices,out);
			len += fwrite(mesh->mBitangents,1,12*mesh->mNumVertices,out);
		}
	}
	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
		if (!mesh->mColors[n])
			break;

		if (shortened) {
			len += WriteBounds(mesh->mColors[n],mesh->mNumVertices);
		} // else write as usual
		else len += fwrite(mesh->mColors[n],16*mesh->mNumVertices,1,out);
	}
	for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
		if (!mesh->mTextureCoords[n])
			break;

		// write number of UV components
		len += Write<unsigned int>(mesh->mNumUVComponents[n]);

		if (shortened) {
			len += WriteBounds(mesh->mTextureCoords[n],mesh->mNumVertices);
		} // else write as usual
		else len += fwrite(mesh->mTextureCoords[n],12*mesh->mNumVertices,1,out);
	}

	// 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);
				}
			}
			len += Write<unsigned int>(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);
			len += Write<uint16_t>(f.mNumIndices);

			for (unsigned int a = 0; a < f.mNumIndices;++a) {
				if (mesh->mNumVertices < (1u<<16)) {
					len += Write<uint16_t>(f.mIndices[a]);
				}
				else len += Write<unsigned int>(f.mIndices[a]);
			}
		}
	}

	// write bones
	if (mesh->mNumBones) {
		for (unsigned int a = 0; a < mesh->mNumBones;++a) {
			const aiBone* b = mesh->mBones[a];
			len += WriteBinaryBone(b)+8;
		}
	}

	ChangeInteger(old,len);
	return len;
}
Beispiel #7
0
int ShuttleBounds(LPTable table, int nIterations, const char* sFileName)
{
	int k = table->nDimens;
	LPTable UpperBound = CreateMin(k-1, table);
	if(UpperBound == NULL)
	{
		printf("Error :: ShuttleBounds.\n");
		return 0;
	}
	LPTable LowerBound = new Table;
	if(LowerBound == NULL)
	{
		printf("Error :: ShuttleBounds.\n");
		UpperBound->Reset(); delete UpperBound;
		return 0;
	}
	if(!LowerBound->Alloc(table->Dimens, table->nDimens))
	{
		printf("Error :: ShuttleBounds.\n");
		UpperBound->Reset(); delete UpperBound;
		return 0;
	}
	int i;
	for(i=0; i<table->Total; i++)
	{
		LowerBound->Data[i] = 0;
	}
	
	int ind;
	int iteration;
	for(iteration=0; iteration<nIterations; iteration++)
	{
		LPTable OldUpperBound = UpperBound;
		LPTable OldLowerBound = LowerBound;
		
		UpperBound = ReduceOneShuttle(table, 0, OldLowerBound);
		if(UpperBound == NULL)
		{
			OldUpperBound->Reset(); delete OldUpperBound;
			OldLowerBound->Reset(); delete OldLowerBound;
			return 0;
		}
		for(ind=1; ind<k; ind++)
		{
			LPTable newtab = ReduceOneShuttle(table, ind, OldLowerBound);
			if(newtab == NULL)
			{
				UpperBound->Reset();    delete UpperBound;
				OldUpperBound->Reset(); delete OldUpperBound;
				OldLowerBound->Reset(); delete OldLowerBound;
				return 0;
			}
			for(i=0; i<table->Total; i++)
			{
				if(newtab->Data[i] < UpperBound->Data[i])
				{
					UpperBound->Data[i] = newtab->Data[i];
				}
			}
			newtab->Reset(); delete newtab;
		}
		
		LowerBound = ReduceOneShuttle(table, 0, OldUpperBound);
		if(LowerBound == NULL)
		{
			UpperBound->Reset(); delete UpperBound;
			OldUpperBound->Reset(); delete OldUpperBound;
			OldLowerBound->Reset(); delete OldLowerBound;
			return 0;
		}
		
		for(ind=1; ind<k; ind++)
		{
			LPTable newtab = ReduceOneShuttle(table, ind, OldUpperBound);
			if(newtab == NULL)
			{
				UpperBound->Reset(); delete UpperBound;
				LowerBound->Reset(); delete LowerBound;
				OldUpperBound->Reset(); delete OldUpperBound;
				OldLowerBound->Reset(); delete OldLowerBound;
				return 0;
			}
			for(i=0; i<table->Total; i++)
			{
				if(newtab->Data[i] > LowerBound->Data[i])
				{
					LowerBound->Data[i] = newtab->Data[i];
				}
			}
			newtab->Reset(); delete newtab;
		}
		OldUpperBound->Reset(); delete OldUpperBound;
		OldLowerBound->Reset(); delete OldLowerBound;
	}
	int rez = WriteBounds(UpperBound, LowerBound, sFileName);
	UpperBound->Reset();
	LowerBound->Reset();
	delete UpperBound;
	delete LowerBound;
	return rez;
}
Beispiel #8
0
int Bonferroni(int m, LPTable table, const char* sFileName)
{
	if(table == NULL)
	{
		printf("Error :: BonferroniBounds.\n");
		return 0;
	}
	
	int i;
	double nGrandTotal;
	nGrandTotal = table->GetGrandTotal();
	
	for(i=0; i<table->Total; i++)
	{
		table->Data[i] /= nGrandTotal;
	}  
	
	table->WriteTable("tabinit.dat");
	
	LPTable UpperBound;
	LPTable LowerBound = new Table;
	if(LowerBound == NULL)
	{
		printf("Error :: BonferroniBounds.\n");
		return 0;
	}
	
	if(!LowerBound->Alloc(table->Dimens, table->nDimens))
	{
		printf("Error :: BonferroniBounds.\n");
		return 0;
	}
	
	LPTable nBar = CreateNBar(table);
	if(nBar == NULL)
	{
		printf("Error :: Bonferroni.\n");
		return 0;
	}
	
	nBar->WriteTable("nbar.dat");
	
	double nBarGrandTotal;
	nBarGrandTotal = nBar->GetGrandTotal();
	int m1;
	int plus;
	
	UpperBound = CreateS(1, nBar);
	if(UpperBound == NULL)
	{
		printf("Error :: Bonferroni.\n");
		nBar->Reset(); delete nBar;
		LowerBound->Reset(); delete LowerBound;
		return 0;
	}
	
	UpperBound->WriteTable("s1bar.dat");
	
	for(i=0; i<table->Total; i++)
	{
		UpperBound->Data[i] = 1 - UpperBound->Data[i]; //nBarGrandTotal
	}
	
	plus = 1;
	
	for(m1=2; m1<=m-1; m1++)
	{
		LPTable sm1 = CreateS(m1, nBar);
		if(sm1 == NULL)
		{
			printf("Error :: Bonferroni.\n");
			nBar->Reset(); delete nBar;
			UpperBound->Reset(); delete UpperBound;
			LowerBound->Reset(); delete LowerBound;
			return 0;
		}
		
		if(plus == 1)
		{
			for(i=0; i<table->Total; i++)
			{
				UpperBound->Data[i] += sm1->Data[i];
			}
		}
		else //plus == -1
		{
			for(i=0; i<table->Total; i++)
			{
				UpperBound->Data[i] -= sm1->Data[i];
			}
		}
		
		sm1->Reset(); delete sm1;
		plus = - plus;
	}
	
	for(i=0; i<table->Total; i++)
	{
		LowerBound->Data[i] = UpperBound->Data[i];
	}
	
	if(m < table->nDimens)
	{
		LPTable sm = CreateS(m, nBar);
		if(sm == NULL)
		{
			printf("Error :: Bonferroni.\n");
			nBar->Reset(); delete nBar;
			UpperBound->Reset(); delete UpperBound;
			LowerBound->Reset(); delete LowerBound;
			return 0;
		}
		
		if(plus == 1) //m even
		{
			for(i=0; i<table->Total; i++)
			{
				UpperBound->Data[i] += sm->Data[i];
			}
		}
		else //m odd
		{
			for(i=0; i<table->Total; i++)
			{
				LowerBound->Data[i] -= sm->Data[i];
			}
		}
		sm->Reset();
		delete sm;
	}
	else
	{
		if(plus == 1) //m even
		{
			for(i=0; i<table->Total; i++)
			{
				UpperBound->Data[i] += nBar->Data[i];
			}
		}
		else //m odd
		{
			for(i=0; i<table->Total; i++)
			{
				LowerBound->Data[i] -= nBar->Data[i];
			}
		}
	}
	
	WriteBounds(UpperBound, LowerBound, "extra.dat");
	
	double ratio = nGrandTotal; // /nBarGrandTotal;
	printf("ratio = %lf\n", ratio);
	for(i=0; i<table->Total; i++)
	{
		UpperBound->Data[i] = ceil(UpperBound->Data[i]*ratio);
		LowerBound->Data[i] = floor(LowerBound->Data[i]*ratio);
		if(LowerBound->Data[i] < 0)
		{
			LowerBound->Data[i] = 0;
		}
	}
	
	int rez = WriteBounds(UpperBound, LowerBound, sFileName);
	
	nBar->Reset();
	UpperBound->Reset();
	LowerBound->Reset();
	delete nBar;
	delete UpperBound;
	delete LowerBound;
	
	return rez;
}
Beispiel #9
0
int FrechetBounds(LPTable table, const char* sFileName)
{
	if(table == NULL)
	{
		printf("Error :: FrechetBounds.\n");
		return 0;
	}
	
	int k = table->nDimens;
	LPTable UpperBound = CreateMin(k-1, table);
	if(UpperBound == NULL)
	{
		printf("Error :: FrechetBounds.\n");
		return 0;
	}
	
	LPTable LowerBound = new Table;
	if(LowerBound == NULL)
	{
		printf("Error :: FrechetBounds.\n");
		UpperBound->Reset();
		delete UpperBound;
		return 0;
	}
	
	if(!LowerBound->Alloc(table->Dimens, table->nDimens))
	{
		printf("Error :: FrechetBounds.\n");
		UpperBound->Reset();
		delete UpperBound;
		return 0;
	}
	
	double n = table->GetGrandTotal();
	int m;
	int plus;
	int first = 1; //first iteration?
	int i;
	
	if(k%2 == 0) //k even
	{
		plus = 1;
		
		for(m=1; m<k; m++)
		{
			LPTable smtab = CreateS(m, table);
			if(smtab == NULL)
			{
				printf("Error :: FrechetBounds.\n");
				UpperBound->Reset();
				LowerBound->Reset();
				delete UpperBound;
				delete LowerBound;
				
				return 0;
			}
			
			if(first)
			{
				for(i=0; i<table->Total; i++)
				{
					LowerBound->Data[i] = smtab->Data[i] - n;
				}
				
				first = 0;
			}
			else
			{
				if(plus == -1)
				{
					for(i=0; i<table->Total; i++)
					{
						LowerBound->Data[i] -= smtab->Data[i];
					}
				}
				else //plus == 1
				{
					for(i=0; i<table->Total; i++)
					{
						LowerBound->Data[i] += smtab->Data[i];
					}
				}
			}
			
			plus = - plus;
			smtab->Reset();
			delete smtab;
		}
	}
	else // k odd
	{
		LPTable nBar = CreateNBar(table);
		if(nBar == NULL)
		{
			printf("Error :: FrechetBounds.\n");
			UpperBound->Reset();
			LowerBound->Reset();
			delete UpperBound;
			delete LowerBound;
			return 0;
		}
		
		LPTable nMinBar = CreateMin(k-1, nBar);
		nBar->Reset();
		delete nBar;
		if(nMinBar == NULL)
		{
			printf("Error :: FrechetBounds.\n");
			UpperBound->Reset();
			LowerBound->Reset();
			delete UpperBound;
			delete LowerBound;
			return 0;
		}
		
		plus = -1;
		
		for(m=1; m<k; m++)
		{
			LPTable smtab = CreateS(m, table);
			if(smtab == NULL)
			{
				printf("Error :: FrechetBounds.\n");
				UpperBound->Reset();
				LowerBound->Reset();
				delete UpperBound;
				delete LowerBound;
				return 0;
			}
			
			if(first)
			{
				for(i=0; i<table->Total; i++)
				{
					LowerBound->Data[i] = n - smtab->Data[i];
				}
				
				first = 0;
			}
			else
			{
				if(plus == -1)
				{
					for(i=0; i<table->Total; i++)
					{
						LowerBound->Data[i] -= smtab->Data[i];
					}
				}
				else //plus == 1
				{
					for(i=0; i<table->Total; i++)
					{
						LowerBound->Data[i] += smtab->Data[i];
					}
				}
			}
			
			plus = - plus;
			smtab->Reset();
			delete smtab;
		}
		
		for(i=0; i<table->Total; i++)
		{
			LowerBound->Data[i] -= nMinBar->Data[i];
		}
		
		nMinBar->Reset();
		delete nMinBar;
	}
	
	for(i=0; i<table->Total; i++)
	{
		if(LowerBound->Data[i] < 0)
		{
			LowerBound->Data[i] = 0;
		}
	}
	
	int rez = WriteBounds(UpperBound, LowerBound, sFileName);
	
	UpperBound->Reset();
	LowerBound->Reset();
	delete UpperBound;
	delete LowerBound;
	
	return rez;
}
Beispiel #10
0
// -----------------------------------------------------------------------------------
// Write a binary model dump
void WriteBinaryDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, 
	bool shortened, bool compressed, ImportData& imp)
{
	time_t tt = ::time(NULL);
	tm* p     = ::gmtime(&tt);

	// header
	::fprintf(out,"ASSIMP.binary-dump.%s.",::asctime(p));
	// == 45 bytes

	WriteInteger(aiGetVersionMajor(),out);
	WriteInteger(aiGetVersionMinor(),out);
	WriteInteger(aiGetVersionRevision(),out);
	WriteInteger(aiGetCompileFlags(),out);
	WriteShort(shortened,out);
	WriteShort(compressed,out);
	// ==  20 bytes

	char buff[256]; 
	::strncpy(buff,src,256);
	::fwrite(buff,256,1,out);

	::strncpy(buff,cmd,128);
	::fwrite(buff,128,1,out);

	// leave 41 bytes free for future extensions
	::memset(buff,0xcd,41);
	::fwrite(buff,32,1,out);
	// == 435 bytes

	// ==== total header size: 500 bytes
	// Up to here the data is uncompressed. For compressed files, the rest
	// is compressed using standard DEFLATE from zlib.
	
	// basic scene information
	WriteInteger(scene->mFlags,out);
	WriteInteger(scene->mNumAnimations,out);
	WriteInteger(scene->mNumTextures,out);
	WriteInteger(scene->mNumMaterials,out);
	WriteInteger(scene->mNumCameras,out);
	WriteInteger(scene->mNumLights,out);
	WriteInteger(scene->mNumMeshes,out);

	// write node graph
	WriteBinaryNode(scene->mRootNode,out);

	// write materials
	for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
		const aiMaterial* mat = scene->mMaterials[i];

		WriteMagic("#MA",out);
		WriteInteger(mat->mNumProperties,out);

		for (unsigned int a = 0; a < mat->mNumProperties;++a) {
			const aiMaterialProperty* prop = mat->mProperties[a];
			
			WriteMagic("#MP",out);
			WriteAiString(prop->mKey,out);
			WriteInteger(prop->mSemantic,out);
			WriteInteger(prop->mIndex,out);

			WriteInteger(prop->mDataLength,out);
			::fwrite(prop->mData,prop->mDataLength,1,out);
		}
	}

	// write cameras
	for (unsigned int i = 0; i < scene->mNumCameras;++i) {
		const aiCamera* cam = scene->mCameras[i];

		WriteMagic("#CA",out);
		WriteAiString(cam->mName,out);
		WriteVec3(cam->mPosition,out);
		WriteVec3(cam->mLookAt,out);
		WriteVec3(cam->mUp,out);
		WriteFloat(cam->mClipPlaneNear,out);
		WriteFloat(cam->mClipPlaneFar,out);
		WriteFloat(cam->mHorizontalFOV,out);
		WriteFloat(cam->mAspect,out);
	}

	// write lights
	for (unsigned int i = 0; i < scene->mNumLights;++i) {
		const aiLight* l = scene->mLights[i];

		WriteMagic("#LI",out);
		WriteAiString(l->mName,out);
		WriteInteger(l->mType,out);

		WriteVec3((const aiVector3D&)l->mColorDiffuse,out);
		WriteVec3((const aiVector3D&)l->mColorSpecular,out);
		WriteVec3((const aiVector3D&)l->mColorAmbient,out);

		if (l->mType != aiLightSource_DIRECTIONAL) { 
			WriteVec3(l->mPosition,out);
			WriteFloat(l->mAttenuationLinear,out);
			WriteFloat(l->mAttenuationConstant,out);
			WriteFloat(l->mAttenuationQuadratic,out);
		}

		if (l->mType != aiLightSource_POINT) {
			WriteVec3(l->mDirection,out);
		}

		if (l->mType == aiLightSource_SPOT) {
			WriteFloat(l->mAttenuationConstant,out);
			WriteFloat(l->mAttenuationQuadratic,out);
		}
	}

	// write all animations
	for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
		const aiAnimation* anim = scene->mAnimations[i];
		
		WriteMagic("#AN",out);
		WriteAiString (anim->mName,out);
		WriteDouble (anim->mTicksPerSecond,out);
		WriteDouble (anim->mDuration,out);
		WriteInteger(anim->mNumChannels,out);

		for (unsigned int a = 0; a < anim->mNumChannels;++a) {
			const aiNodeAnim* nd = anim->mChannels[a];

			WriteMagic("#NA",out);
			WriteAiString(nd->mNodeName,out);
			WriteInteger(nd->mPreState,out);
			WriteInteger(nd->mPostState,out);
			WriteInteger(nd->mNumPositionKeys,out);
			WriteInteger(nd->mNumRotationKeys,out);
			WriteInteger(nd->mNumScalingKeys,out);

			if (nd->mPositionKeys) {
				if (shortened) {
					WriteBounds(nd->mPositionKeys,nd->mNumPositionKeys,out);

				} // else write as usual
				else ::fwrite(nd->mPositionKeys,sizeof(aiVectorKey),nd->mNumPositionKeys,out);
			}
			if (nd->mRotationKeys) {
				if (shortened) {
					WriteBounds(nd->mRotationKeys,nd->mNumRotationKeys,out);

				} // else write as usual
				else ::fwrite(nd->mRotationKeys,sizeof(aiQuatKey),nd->mNumRotationKeys,out);
			}
			if (nd->mScalingKeys) {
				if (shortened) {
					WriteBounds(nd->mScalingKeys,nd->mNumScalingKeys,out);

				} // else write as usual
				else ::fwrite(nd->mScalingKeys,sizeof(aiVectorKey),nd->mNumScalingKeys,out);
			}
		}
	}

	// write all meshes
	for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
		const aiMesh* mesh = scene->mMeshes[i];

		WriteMagic("#ME",out);
		WriteInteger(mesh->mPrimitiveTypes,out);
		WriteInteger(mesh->mNumBones,out);
		WriteInteger(mesh->mNumFaces,out);
		WriteInteger(mesh->mNumVertices,out);

		// write bones
		if (mesh->mNumBones) {
			for (unsigned int a = 0; a < mesh->mNumBones;++a) {
				const aiBone* b = mesh->mBones[a];

				WriteMagic("#BN",out);
				WriteAiString(b->mName,out);
				WriteMat4x4(b->mOffsetMatrix,out);
				WriteInteger(b->mNumWeights,out);

				// 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(b->mWeights,b->mNumWeights,out);
				} // else write as usual
				else ::fwrite(b->mWeights,sizeof(aiVertexWeight),b->mNumWeights,out);
			}
		}

		// 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) {

				unsigned int hash = 0;
				for (unsigned int a = 0; a < job;++a) {

					const aiFace& f = mesh->mFaces[processed+a];
					hash = SuperFastHash((const char*)&f.mNumIndices,sizeof(unsigned int),hash);
					hash = SuperFastHash((const char*) f.mIndices,f.mNumIndices*sizeof(unsigned int),hash);
				}
				WriteInteger(hash,out);
			}
		}
		else // else write as usual
		{
			for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
				const aiFace& f = mesh->mFaces[i];

				WriteInteger(f.mNumIndices,out);
				for (unsigned int a = 0; a < f.mNumIndices;++a)
					WriteInteger(f.mIndices[a],out);
			}
		}

		// first of all, write bits for all existent vertex components
		unsigned int c = 0;
		if (mesh->mVertices) 
			c |= 1;
		if (mesh->mNormals)
			c |= 2;
		if (mesh->mTangents && mesh->mBitangents) 
			c |= 4;
		for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
			if (!mesh->mTextureCoords[n])break;
			c |= (8 << n);
		}
		for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
			if (!mesh->mColors[n])break;
			c |= (16 << n);
		}
		WriteInteger(c,out);
		
		aiVector3D minVec, maxVec;
		if (mesh->mVertices) {
			if (shortened) {
				WriteBounds(mesh->mVertices,mesh->mNumVertices,out);
			} // else write as usual
			else ::fwrite(mesh->mVertices,12*mesh->mNumVertices,1,out);
		}
		if (mesh->mNormals) {
			if (shortened) {
				WriteBounds(mesh->mNormals,mesh->mNumVertices,out);
			} // else write as usual
			else ::fwrite(mesh->mNormals,12*mesh->mNumVertices,1,out);
		}
		if (mesh->mTangents && mesh->mBitangents) {
			if (shortened) {
				WriteBounds(mesh->mTangents,mesh->mNumVertices,out);
				WriteBounds(mesh->mBitangents,mesh->mNumVertices,out);
			} // else write as usual
			else {
				::fwrite(mesh->mTangents,12*mesh->mNumVertices,1,out);
				::fwrite(mesh->mBitangents,12*mesh->mNumVertices,1,out);
			}
		}
		for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
			if (!mesh->mTextureCoords[n])break;

			// write number of UV components
			WriteInteger(mesh->mNumUVComponents[n],out);

			if (shortened) {
				WriteBounds(mesh->mTextureCoords[n],mesh->mNumVertices,out);
			} // else write as usual
			else ::fwrite(mesh->mTextureCoords[n],12*mesh->mNumVertices,1,out);
		}
		for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
			if (!mesh->mColors[n])
				break;

			if (shortened) {
				WriteBounds(mesh->mColors[n],mesh->mNumVertices,out);
			} // else write as usual
			else ::fwrite(mesh->mColors[n],16*mesh->mNumVertices,1,out);
		}
	}
}