Ejemplo n.º 1
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryLight(const aiLight* l)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AILIGHT);

	len += Write<aiString>(l->mName);
	len += Write<unsigned int>(l->mType);

	if (l->mType != aiLightSource_DIRECTIONAL) { 
		len += Write<float>(l->mAttenuationConstant);
		len += Write<float>(l->mAttenuationLinear);
		len += Write<float>(l->mAttenuationQuadratic);
	}

	len += Write<aiVector3D>((const aiVector3D&)l->mColorDiffuse);
	len += Write<aiVector3D>((const aiVector3D&)l->mColorSpecular);
	len += Write<aiVector3D>((const aiVector3D&)l->mColorAmbient);

	if (l->mType == aiLightSource_SPOT) {
		len += Write<float>(l->mAngleInnerCone);
		len += Write<float>(l->mAngleOuterCone);
	}

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 2
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryScene(const aiScene* scene)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AISCENE);

	// basic scene information
	len += Write<unsigned int>(scene->mFlags);
	len += Write<unsigned int>(scene->mNumMeshes);
	len += Write<unsigned int>(scene->mNumMaterials);
	len += Write<unsigned int>(scene->mNumAnimations);
	len += Write<unsigned int>(scene->mNumTextures);
	len += Write<unsigned int>(scene->mNumLights);
	len += Write<unsigned int>(scene->mNumCameras);
	
	// write node graph
	len += WriteBinaryNode(scene->mRootNode)+8;

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

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

	// write all animations
	for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
		const aiAnimation* anim = scene->mAnimations[i];
		len += WriteBinaryAnim(anim)+8;
	}


	// write all textures
	for (unsigned int i = 0; i < scene->mNumTextures;++i) {
		const aiTexture* mesh = scene->mTextures[i];
		len += WriteBinaryTexture(mesh)+8;
	}

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

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

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 3
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryMaterial(const aiMaterial* mat)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMATERIAL);

	len += Write<unsigned int>(mat->mNumProperties);
	for (unsigned int i = 0; i < mat->mNumProperties;++i) {
		len += WriteBinaryMaterialProperty(mat->mProperties[i])+8;
	}

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 4
0
// -----------------------------------------------------------------------------------
// Write a single node in a binary dump
void WriteBinaryNode(const aiNode* node, FILE* out)
{
	WriteMagic("#ND",out);
	WriteAiString(node->mName,out);
	WriteMat4x4(node->mTransformation,out);

	WriteInteger(node->mNumMeshes,out);
	for (unsigned int i = 0; i < node->mNumMeshes;++i)
		WriteInteger(node->mMeshes[i],out);

	WriteInteger(node->mNumChildren,out);
	for (unsigned int i = 0; i < node->mNumChildren;++i)
		WriteBinaryNode(node->mChildren[i],out);
}
Ejemplo n.º 5
0
int EXRFile::OpenOutputFile(const char* i_fileName)
{
	m_file = fopen(i_fileName, "wb");
	
	if (!m_file)
	{
		return IMF_ERROR_ERROR;
	}
	
	m_channelList = new ChannelList(*m_header->GetChannelList());
	m_channelList->Sort();
	
	m_header->GetAttribute("dataWindow", "box2i", (char*)&m_dataWindow[0]);
	m_header->GetAttribute("compression", "compression", (char*)&m_compression);
	
	int width = m_dataWindow[2] - m_dataWindow[0] + 1;
	size_t datasize = m_channelList->GetPixelSize() * width;
	if (m_compression == IMF_ZIP_COMPRESSION)
	{
		m_scanline_block =
			new ScanLineZipBlock(
				m_file,
				datasize,
				m_dataWindow[1]);
	}
	else
	{
		m_scanline_block =
			new ScanLineBlock(
				m_file,
				datasize,
				m_dataWindow[1]);
	}

	int height = m_dataWindow[3] - m_dataWindow[1] + 1;

	m_blocks =  height / m_scanline_block->NumLinesInBlock();
	m_blocks += height % m_scanline_block->NumLinesInBlock() > 0;

	m_offset_table = new uint64_t [m_blocks];
	m_offset_table_counter = 0;
	
	WriteMagic();
	WriteVersion();
	WriteHeader();
	WriteZerroOffsets();

	return IMF_ERROR_NOERROR;
}
Ejemplo n.º 6
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryMaterialProperty(const aiMaterialProperty* prop)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMATERIALPROPERTY);

	len += Write<aiString>(prop->mKey);
	len += Write<unsigned int>(prop->mSemantic);
	len += Write<unsigned int>(prop->mIndex);

	len += Write<unsigned int>(prop->mDataLength);
	len += Write<unsigned int>((unsigned int)prop->mType);
	len += fwrite(prop->mData,1,prop->mDataLength,out);

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 7
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryCamera(const aiCamera* cam)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AICAMERA);

	len += Write<aiString>(cam->mName);
	len += Write<aiVector3D>(cam->mPosition);
	len += Write<aiVector3D>(cam->mLookAt);
	len += Write<aiVector3D>(cam->mUp);
	len += Write<float>(cam->mHorizontalFOV);
	len += Write<float>(cam->mClipPlaneNear);
	len += Write<float>(cam->mClipPlaneFar);
	len += Write<float>(cam->mAspect);

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 8
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryAnim(const aiAnimation* anim)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIANIMATION);

	len += Write<aiString> (anim->mName);
	len += Write<double> (anim->mDuration);
	len += Write<double> (anim->mTicksPerSecond);
	len += Write<unsigned int>(anim->mNumChannels);

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

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryNode(const aiNode* node)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AINODE);
	len += Write<aiString>(node->mName);
	len += Write<aiMatrix4x4>(node->mTransformation);
	len += Write<unsigned int>(node->mNumChildren);
	len += Write<unsigned int>(node->mNumMeshes);

	for (unsigned int i = 0; i < node->mNumMeshes;++i) {
		len += Write<unsigned int>(node->mMeshes[i]);
	}

	for (unsigned int i = 0; i < node->mNumChildren;++i) {
		len += WriteBinaryNode(node->mChildren[i])+8;
	}

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 11
0
// -----------------------------------------------------------------------------------
uint32_t WriteBinaryTexture(const aiTexture* tex)
{
	uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AITEXTURE);

	len += Write<unsigned int>(tex->mWidth);
	len += Write<unsigned int>(tex->mHeight);
	len += fwrite(tex->achFormatHint,1,4,out);

	if(!shortened) {
		if (!tex->mHeight) {
			len += fwrite(tex->pcData,1,tex->mWidth,out);
		}
		else {
			len += fwrite(tex->pcData,1,tex->mWidth*tex->mHeight*4,out);
		}
	}

	ChangeInteger(old,len);
	return len;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
int EXRFile::OpenOutputFile(const char* i_fileName)
{
	m_file = fopen(i_fileName, "wb");
	
	if (!m_file)
	{
		return IMF_ERROR_ERROR;
	}
	
	m_channelList = new ChannelList(*m_header->GetChannelList());
	m_channelList->Sort();
	
	m_header->GetAttribute("dataWindow", "box2i", (char*)&m_dataWindow[0]);
	m_header->GetAttribute("compression", "compression", (char*)&m_compression);

	/* TODO: Get and use length of the attribute */
	char type[256];
	const char* deepscanline = "deepscanline";
	m_header->GetAttribute("type", "string", type);
	if (strncmp(type, deepscanline, strlen(deepscanline)) == 0)
	{
		m_dataType = IMF_DEEPSCANLINE;
	}
	else
	{
		m_dataType = IMF_SCANLINEIMAGE;
	}

	int width = m_dataWindow[2] - m_dataWindow[0] + 1;
	size_t datasize = m_channelList->GetPixelSize() * width;

	if( m_dataType == IMF_DEEPSCANLINE )
	{
		if (m_compression == IMF_ZIPS_COMPRESSION)
		{
			m_scanline_block =
				new ScanLineDeepZipSBlock(
						m_file,
						width * sizeof(m_fb_sampleCount[0]),
						m_channelList->GetPixelSize(),
						m_dataWindow[1]);
		}
		else
		{
			m_scanline_block =
				new ScanLineDeepBlock(
						m_file,
						width * sizeof(m_fb_sampleCount[0]),
						m_channelList->GetPixelSize(),
						m_dataWindow[1]);
		}
	}
	else
	switch( m_compression )
	{
		case IMF_ZIP_COMPRESSION:
			m_scanline_block =
				new ScanLineZipBlock(
					m_file,
					datasize,
					m_dataWindow[1],
					ScanLineZipBlock::kDefaultBlockSize);
			break;
		case IMF_ZIPS_COMPRESSION:
			m_scanline_block =
				new ScanLineZipBlock(
					m_file,
					datasize,
					m_dataWindow[1],
					1);
			break;
		default:
			m_scanline_block =
				new ScanLineBlock(
					m_file,
					datasize,
					m_dataWindow[1]);
	}

	int height = m_dataWindow[3] - m_dataWindow[1] + 1;

	m_blocks =  height / m_scanline_block->NumLinesInBlock();
	m_blocks += height % m_scanline_block->NumLinesInBlock() > 0;

	m_offset_table = new uint64_t [m_blocks];
	// Initialize table to 0, so that valgrind doesn't complain about writing it out to file before we initialize it
	for( int i = 0; i < m_blocks; i++ ) m_offset_table[i] = 0;
	m_offset_table_counter = 0;
	
	WriteMagic();
	WriteVersion();
	WriteHeader();
	WriteZerroOffsets();

	return IMF_ERROR_NOERROR;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
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);
		}
	}
}