Browse Source

blender loader now reads basic material colors and even simple textures, be them embedded into the BLEND file or not.
adding some test files.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@735 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

aramis_acg 15 years ago
parent
commit
188aa3da37

+ 20 - 0
code/BlenderDNA.h

@@ -111,6 +111,15 @@ struct Pointer
 	uint64_t val;
 	uint64_t val;
 };
 };
 
 
+// -------------------------------------------------------------------------------
+/** Represents a generic offset within a BLEND file */
+// -------------------------------------------------------------------------------
+struct FileOffset
+{
+	FileOffset() : val() {}
+	uint64_t val;
+};
+
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** Dummy derivate of std::vector to be able to use it in templates simultaenously
 /** Dummy derivate of std::vector to be able to use it in templates simultaenously
  *  with boost::shared_ptr, which takes only one template argument 
  *  with boost::shared_ptr, which takes only one template argument 
@@ -263,6 +272,13 @@ public:
 	void ReadFieldPtr(TOUT<T>& out, const char* name, 
 	void ReadFieldPtr(TOUT<T>& out, const char* name, 
 		const FileDatabase& db) const;
 		const FileDatabase& db) const;
 
 
+	// --------------------------------------------------------
+	// field parsing for static arrays of pointer or dynamic
+	// array types (boost::shared_ptr[] or boost::shared_array[])
+	template <int error_policy, template <typename> class TOUT, typename T, size_t N>
+	void ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
+		const FileDatabase& db) const;
+
 	// --------------------------------------------------------
 	// --------------------------------------------------------
 	// field parsing for `normal` values
 	// field parsing for `normal` values
 	template <int error_policy, typename T>
 	template <int error_policy, typename T>
@@ -281,6 +297,10 @@ private:
 	void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
 	void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
 		const FileDatabase& db, const Field& f) const;
 		const FileDatabase& db, const Field& f) const;
 
 
+	// --------------------------------------------------------
+	void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
+		const FileDatabase& db, const Field& f) const;
+
 	// --------------------------------------------------------
 	// --------------------------------------------------------
 	inline const FileBlockHead* LocateFileBlockForAddress(
 	inline const FileBlockHead* LocateFileBlockForAddress(
 		const Pointer & ptrval,
 		const Pointer & ptrval,

+ 78 - 4
code/BlenderDNA.inl

@@ -181,8 +181,7 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
 		// sanity check, should never happen if the genblenddna script is right
 		// sanity check, should never happen if the genblenddna script is right
 		if (!(f->flags & FieldFlag_Pointer)) {
 		if (!(f->flags & FieldFlag_Pointer)) {
 			throw Error((Formatter::format(),"Field `",name,"` of structure `",
 			throw Error((Formatter::format(),"Field `",name,"` of structure `",
-				this->name,"` ought to be a pointer"
-				));
+				this->name,"` ought to be a pointer"));
 		}
 		}
 
 
 		db.reader->IncPtr(f->offset);
 		db.reader->IncPtr(f->offset);
@@ -204,9 +203,57 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
 	db.reader->SetCurrentPos(old);
 	db.reader->SetCurrentPos(old);
 
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	if (out) {
-		++db.stats().pointers_resolved;
+	++db.stats().fields_read;
+#endif
+}
+
+//--------------------------------------------------------------------------------
+template <int error_policy, template <typename> class TOUT, typename T, size_t N>
+void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
+	const FileDatabase& db) const
+{
+	// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
+	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+	Pointer ptrval[N];
+	const Field* f;
+	try {
+		f = &(*this)[name];
+
+		// sanity check, should never happen if the genblenddna script is right
+		if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
+			throw Error((Formatter::format(),"Field `",name,"` of structure `",
+				this->name,"` ought to be a pointer AND an array"));
+		}
+
+		db.reader->IncPtr(f->offset);
+
+		size_t i = 0;
+		for(; i < std::min(f->array_sizes[0],N); ++i) {
+			Convert(ptrval[i],db);
+		}
+		for(; i < N; ++i) {
+			_defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
+		}
+
+		// actually it is meaningless on which Structure the Convert is called
+		// because the `Pointer` argument triggers a special implementation.
+	}
+	catch (const Error& e) {
+		_defaultInitializer<error_policy>()(out,e.what());
+		for(size_t i = 0; i < N; ++i) {
+			out[i].reset();
+		}
+		return;
 	}
 	}
+	for(size_t i = 0; i < N; ++i) {
+		// resolve the pointer and load the corresponding structure
+		ResolvePointer(out[i],ptrval[i],db,*f);
+	}
+
+	// and recover the previous stream position
+	db.reader->SetCurrentPos(old);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 	++db.stats().fields_read;
 	++db.stats().fields_read;
 #endif
 #endif
 }
 }
@@ -282,6 +329,29 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
 	}
 	}
 
 
 	db.reader->SetCurrentPos(pold);
 	db.reader->SetCurrentPos(pold);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	if(out) {
+		++db.stats().pointers_resolved;
+	}
+#endif
+}
+
+//--------------------------------------------------------------------------------
+inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const
+{
+	// Currently used exclusively by PackedFile::data to represent
+	// a simple offset into the mapped BLEND file. 
+	out.reset();
+	if (!ptrval.val) { 
+		return;
+	}
+
+	// find the file block the pointer is pointing to
+	const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+	out =  boost::shared_ptr< FileOffset > (new FileOffset());
+	out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
@@ -372,6 +442,10 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
 	// cache the object now that construction is complete
 	// cache the object now that construction is complete
 	// FIXME we need to do this in ConvertBlobToStructure
 	// FIXME we need to do this in ConvertBlobToStructure
 	db.cache(out).set(s,out,ptrval);
 	db.cache(out).set(s,out,ptrval);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	++db.stats().pointers_resolved;
+#endif
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------

+ 197 - 12
code/BlenderLoader.cpp

@@ -75,9 +75,12 @@ static const aiLoaderDesc blenderDesc = {
 namespace Assimp {
 namespace Assimp {
 namespace Blender {
 namespace Blender {
 
 
+	// --------------------------------------------------------------------
 	/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
 	/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
+	// --------------------------------------------------------------------
 	template <template <typename,typename> class TCLASS, typename T>
 	template <template <typename,typename> class TCLASS, typename T>
 	struct TempArray	{
 	struct TempArray	{
+		typedef TCLASS< T*,std::allocator<T*> > mywrap;
 
 
 		TempArray() {
 		TempArray() {
 		}
 		}
@@ -92,19 +95,23 @@ namespace Blender {
 			arr.clear();
 			arr.clear();
 		}
 		}
 
 
-		TCLASS< T*,std::allocator<T*> >* operator -> () {
+		mywrap* operator -> () {
 			return &arr;
 			return &arr;
 		}
 		}
 
 
-		operator TCLASS< T*,std::allocator<T*> > () {
+		operator mywrap& () {
 			return arr;
 			return arr;
 		}
 		}
 
 
-		TCLASS< T*,std::allocator<T*> >& get () {
+		operator const mywrap& () const {
 			return arr;
 			return arr;
 		}
 		}
 
 
-		const TCLASS< T*,std::allocator<T*> >& get () const {
+		mywrap& get () {
+			return arr;
+		}
+
+		const mywrap& get () const {
 			return arr;
 			return arr;
 		}
 		}
 
 
@@ -121,24 +128,73 @@ namespace Blender {
 		}
 		}
 
 
 	private:
 	private:
-		TCLASS< T*,std::allocator<T*> > arr;
+		mywrap arr;
 	};
 	};
 	
 	
+#ifdef _MSC_VER
+#	pragma warning(disable:4351)
+#endif
+	// --------------------------------------------------------------------
 	/** ConversionData acts as intermediate storage location for
 	/** ConversionData acts as intermediate storage location for
 	 *  the various ConvertXXX routines in BlenderImporter.*/
 	 *  the various ConvertXXX routines in BlenderImporter.*/
-	struct ConversionData	{
+	// --------------------------------------------------------------------
+	struct ConversionData	
+	{
+		ConversionData(const FileDatabase& db)
+			: sentinel_cnt()
+			, next_texture()
+			, db(db)
+		{}
+
 		std::set<const Object*> objects;
 		std::set<const Object*> objects;
 
 
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiMesh> meshes;
 		TempArray <std::vector, aiCamera> cameras;
 		TempArray <std::vector, aiCamera> cameras;
 		TempArray <std::vector, aiLight> lights;
 		TempArray <std::vector, aiLight> lights;
 		TempArray <std::vector, aiMaterial> materials;
 		TempArray <std::vector, aiMaterial> materials;
+		TempArray <std::vector, aiTexture> textures;
 
 
 		// set of all materials referenced by at least one mesh in the scene
 		// set of all materials referenced by at least one mesh in the scene
 		std::deque< boost::shared_ptr< Material > > materials_raw;
 		std::deque< boost::shared_ptr< Material > > materials_raw;
+
+		// counter to name sentinel textures inserted as substitutes for procedural textures.
+		unsigned int sentinel_cnt;
+
+		// next texture ID for each texture type, respectively
+		unsigned int next_texture[aiTextureType_UNKNOWN+1];
+
+		// original file data
+		const FileDatabase& db;
 	};
 	};
+#ifdef _MSC_VER
+#	pragma warning(default:4351)
+#endif
+
+// ------------------------------------------------------------------------------------------------
+const char* GetTextureTypeDisplayString(Tex::Type t)
+{
+	switch (t)	{
+	case Tex::Type_CLOUDS		:  return  "Clouds";			
+	case Tex::Type_WOOD			:  return  "Wood";			
+	case Tex::Type_MARBLE		:  return  "Marble";			
+	case Tex::Type_MAGIC		:  return  "Magic";		
+	case Tex::Type_BLEND		:  return  "Blend";			
+	case Tex::Type_STUCCI		:  return  "Stucci";			
+	case Tex::Type_NOISE		:  return  "Noise";			
+	case Tex::Type_PLUGIN		:  return  "Plugin";			
+	case Tex::Type_MUSGRAVE		:  return  "Musgrave";		
+	case Tex::Type_VORONOI		:  return  "Voronoi";			
+	case Tex::Type_DISTNOISE	:  return  "DistortedNoise";	
+	case Tex::Type_ENVMAP		:  return  "EnvMap";	
+	case Tex::Type_IMAGE		:  return  "Image";	
+	default: 
+		break;
+	}
+	return "<Unknown>";
 }
 }
-}
+
+} // ! Blender
+} // ! Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
@@ -220,7 +276,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
 	Scene scene;
 	Scene scene;
 	ExtractScene(scene,file);
 	ExtractScene(scene,file);
 
 
-	ConvertBlendFile(pScene,scene);
+	ConvertBlendFile(pScene,scene,file);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -294,9 +350,9 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in) 
+void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file) 
 {
 {
-	ConversionData conv;
+	ConversionData conv(file);
 
 
 	// FIXME it must be possible to take the hierarchy directly from
 	// FIXME it must be possible to take the hierarchy directly from
 	// the file. This is terrible. Here, we're first looking for
 	// the file. This is terrible. Here, we're first looking for
@@ -357,6 +413,11 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in)
 		conv.materials.dismiss();
 		conv.materials.dismiss();
 	}
 	}
 
 
+	if (conv.textures->size()) {
+		out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )];
+		std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures);
+		conv.textures.dismiss();
+	}
 
 
 	// acknowledge that the scene might come out incomplete
 	// acknowledge that the scene might come out incomplete
 	// by Assimps definition of `complete`: blender scenes
 	// by Assimps definition of `complete`: blender scenes
@@ -367,6 +428,113 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in)
 	}
 	}
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+void BlenderImporter::ResolveImage(MaterialHelper* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data)
+{
+	mat; tex; conv_data;
+	aiString name;
+
+	// check if the file contents are bundled with the BLEND file
+	if (img->packedfile) {
+		name.data[0] = '*';
+		name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size());
+
+		conv_data.textures->push_back(new aiTexture());
+		aiTexture* tex = conv_data.textures->back();
+
+		// usually 'img->name' will be the original file name of the embedded textures,
+		// so we can extract the file extension from it.
+		const size_t nlen = strlen( img->name );
+		const char* s = img->name+nlen, *e = s;
+
+		while (s >= img->name && *s != '.')--s;
+
+		tex->achFormatHint[0] = s+1>e ? '\0' : s[1];
+		tex->achFormatHint[1] = s+2>e ? '\0' : s[2];
+		tex->achFormatHint[2] = s+3>e ? '\0' : s[3];
+		tex->achFormatHint[3] = '\0';
+
+		// tex->mHeight = 0;
+		tex->mWidth = img->packedfile->size;
+		uint8_t* ch = new uint8_t[tex->mWidth];
+
+		conv_data.db.reader->SetCurrentPos(img->packedfile->data->val);
+		conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
+
+		tex->pcData = reinterpret_cast<aiTexel*>(ch);
+
+		LogInfo("Reading embedded texture, original file was "+std::string(img->name));
+	}
+	else {
+		name = aiString( img->name );
+	}
+	out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
+		conv_data.next_texture[aiTextureType_DIFFUSE]++)
+	);
+}
+
+// ------------------------------------------------------------------------------------------------
+void BlenderImporter::AddSentinelTexture(MaterialHelper* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
+{
+	mat; tex; conv_data;
+
+	aiString name;
+	name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
+		GetTextureTypeDisplayString(tex->tex->type)
+	);
+	out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
+		conv_data.next_texture[aiTextureType_DIFFUSE]++)
+	);
+}
+
+// ------------------------------------------------------------------------------------------------
+void BlenderImporter::ResolveTexture(MaterialHelper* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
+{
+	const Tex* rtex = tex->tex.get();
+	if(!rtex || !rtex->type) {
+		return;
+	}
+	
+	// We can't support most of the texture types because the're mostly procedural.
+	// These are substituted by a dummy texture.
+	const char* dispnam = "";
+	switch( rtex->type ) 
+	{
+			// these are listed in blender's UI
+		case Tex::Type_CLOUDS		:  
+		case Tex::Type_WOOD			:  
+		case Tex::Type_MARBLE		:  
+		case Tex::Type_MAGIC		: 
+		case Tex::Type_BLEND		:  
+		case Tex::Type_STUCCI		: 
+		case Tex::Type_NOISE		: 
+		case Tex::Type_PLUGIN		: 
+		case Tex::Type_MUSGRAVE		:  
+		case Tex::Type_VORONOI		:  
+		case Tex::Type_DISTNOISE	:  
+		case Tex::Type_ENVMAP		:  
+
+			// these do no appear in the UI, why?
+		case Tex::Type_POINTDENSITY	:  
+		case Tex::Type_VOXELDATA	: 
+
+			LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam);
+			AddSentinelTexture(out, mat, tex, conv_data);
+			break;
+
+		case Tex::Type_IMAGE		:
+			if (!rtex->ima) {
+				LogError("A texture claims to be an Image, but no image reference is given");
+				break;
+			}
+			ResolveImage(out, mat, tex, rtex->ima.get(),conv_data);
+			break;
+
+		default:
+			ai_assert(false);
+	};
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::BuildMaterials(ConversionData& conv_data) 
 void BlenderImporter::BuildMaterials(ConversionData& conv_data) 
 {
 {
@@ -386,6 +554,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 				p->r = p->g = p->b = 0.6f;
 				p->r = p->g = p->b = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->specr = p->specg = p->specb = 0.6f;
 				p->ambir = p->ambig = p->ambib = 0.0f;
 				p->ambir = p->ambig = p->ambib = 0.0f;
+				p->mirr = p->mirg = p->mirb = 0.0f;
 				p->emit = 0.f;
 				p->emit = 0.f;
 				p->alpha = 0.f;
 				p->alpha = 0.f;
 
 
@@ -401,6 +570,11 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 	}
 	}
 
 
 	for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) {
 	for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) {
+
+		// reset per material global counters
+		for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
+			conv_data.next_texture[i] = 0 ;
+		}
 	
 	
 		MaterialHelper* mout = new MaterialHelper();
 		MaterialHelper* mout = new MaterialHelper();
 		conv_data.materials->push_back(mout);
 		conv_data.materials->push_back(mout);
@@ -419,6 +593,17 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 
 
 		col = aiColor3D(mat->ambir,mat->ambig,mat->ambib);
 		col = aiColor3D(mat->ambir,mat->ambig,mat->ambib);
 		mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
 		mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
+
+		col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
+		mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
+
+		for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) {
+			if (!mat->mtex[i]) {
+				continue;
+			}
+
+			ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
+		}
 	}
 	}
 }
 }
 
 
@@ -451,11 +636,11 @@ void BlenderImporter::ConvertMesh(const Scene& in, const Object* obj, const Mesh
 	}
 	}
 
 
 	// some sanity checks
 	// some sanity checks
-	if (mesh->totface > mesh->mface.size() ){
+	if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){
 		ThrowException("Number of faces is larger than the corresponding array");
 		ThrowException("Number of faces is larger than the corresponding array");
 	}
 	}
 
 
-	if (mesh->totvert > mesh->mvert.size()) {
+	if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) {
 		ThrowException("Number of vertices is larger than the corresponding array");
 		ThrowException("Number of vertices is larger than the corresponding array");
 	}
 	}
 
 

+ 32 - 2
code/BlenderLoader.h

@@ -66,6 +66,9 @@ namespace Assimp	{
 		struct Mesh;
 		struct Mesh;
 		struct Camera;
 		struct Camera;
 		struct Lamp;
 		struct Lamp;
+		struct MTex;
+		struct Image;
+		struct Material;
 	}
 	}
 
 
 	// BlenderLoader.cpp
 	// BlenderLoader.cpp
@@ -157,7 +160,8 @@ protected:
 
 
 	// --------------------
 	// --------------------
 	void ConvertBlendFile(aiScene* out,
 	void ConvertBlendFile(aiScene* out,
-		const Blender::Scene& in
+		const Blender::Scene& in,
+		const Blender::FileDatabase& file
 	);
 	);
 
 
 private:
 private:
@@ -191,7 +195,33 @@ private:
 	); 
 	); 
 
 
 	// --------------------
 	// --------------------
-	void BuildMaterials(Blender::ConversionData& conv_data) ;
+	void BuildMaterials(
+		Blender::ConversionData& conv_data
+	) ;
+
+	// --------------------
+	void ResolveTexture(
+		MaterialHelper* out, 
+		const Blender::Material* mat, 
+		const Blender::MTex* tex,
+		Blender::ConversionData& conv_data
+	);
+
+	// --------------------
+	void ResolveImage(
+		MaterialHelper* out, 
+		const Blender::Material* mat, 
+		const Blender::MTex* tex, 
+		const Blender::Image* img,
+		Blender::ConversionData& conv_data
+	);
+
+	void AddSentinelTexture(
+		MaterialHelper* out, 
+		const Blender::Material* mat,
+		const Blender::MTex* tex, 
+		Blender::ConversionData& conv_data
+	);
 
 
 private: // static stuff, mostly logging and error reporting.
 private: // static stuff, mostly logging and error reporting.
 
 

+ 5 - 1
code/BlenderScene.cpp

@@ -207,6 +207,9 @@ template <> void Structure :: Convert<PackedFile> (
     ) const
     ) const
 { 
 { 
 
 
+    ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
+    ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
+    ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
 
 
 	db.reader->IncPtr(size);
 	db.reader->IncPtr(size);
 }
 }
@@ -271,6 +274,7 @@ template <> void Structure :: Convert<Material> (
     ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db);
     ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db);
     ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db);
     ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
     ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
+    ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
 
 
 	db.reader->IncPtr(size);
 	db.reader->IncPtr(size);
 }
 }
@@ -338,7 +342,7 @@ template <> void Structure :: Convert<MVert> (
     ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
     ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
-    ReadField<ErrorPolicy_Fail>(dest.bweight,"bweight",db);
+    ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
 
 
 	db.reader->IncPtr(size);
 	db.reader->IncPtr(size);
 }
 }

+ 6 - 5
code/BlenderScene.h

@@ -92,6 +92,7 @@ namespace Assimp	{
 #define FAIL // fail the import if the field does not exist
 #define FAIL // fail the import if the field does not exist
 
 
 struct Object;
 struct Object;
+struct MTex;
 
 
 #define AI_BLEND_MESH_MAX_VERTS 2000000000L
 #define AI_BLEND_MESH_MAX_VERTS 2000000000L
 
 
@@ -112,9 +113,9 @@ struct ListBase : ElemBase {
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 struct PackedFile : ElemBase {
 struct PackedFile : ElemBase {
-     // int size;
-     // int seek;
-     // void* data;
+     int size WARN;
+     int seek WARN;
+	 boost::shared_ptr< FileOffset > data WARN;
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -144,7 +145,7 @@ struct MVert : ElemBase {
 	float no[3] FAIL;
 	float no[3] FAIL;
 	char flag;
 	char flag;
 	int mat_nr WARN;
 	int mat_nr WARN;
-	int bweight FAIL;
+	int bweight;
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -222,7 +223,7 @@ struct Material : ElemBase {
 	short diff_shader WARN;
 	short diff_shader WARN;
 	short spec_shader WARN;
 	short spec_shader WARN;
 
 
-	//MTex *mtex[18];
+	boost::shared_ptr<MTex> mtex[18];
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------

BIN
test/models/BLEND/NoisyTexturedCube_VoronoiGlob_248.blend


BIN
test/models/BLEND/TexturedCube_ImageGlob_248.blend


BIN
test/models/BLEND/TexturedPlane_ImageUvPacked_248.blend


BIN
test/models/BLEND/TexturedPlane_ImageUv_248.blend