Selaa lähdekoodia

Requested modifications

bzt 5 vuotta sitten
vanhempi
commit
a10b0d4de3
5 muutettua tiedostoa jossa 130 lisäystä ja 69 poistoa
  1. 30 5
      code/M3D/M3DExporter.cpp
  2. 53 29
      code/M3D/M3DImporter.cpp
  3. 14 7
      code/M3D/M3DWrapper.cpp
  4. 4 0
      code/M3D/M3DWrapper.h
  5. 29 28
      code/M3D/m3d.h

+ 30 - 5
code/M3D/M3DExporter.cpp

@@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define M3D_IMPLEMENTATION
 #define M3D_NOIMPORTER
 #define M3D_EXPORTER
-#define M3D_ASCII
 #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
 #define M3D_NODUP
 #endif
@@ -65,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Exporter.hpp>
 #include <assimp/IOSystem.hpp>
 
+#include "M3DWrapper.h"
 #include "M3DExporter.h"
 #include "M3DMaterials.h"
-#include "M3DWrapper.h"
 
 // RESOURCES:
 // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
@@ -131,6 +130,28 @@ void addProp(m3dm_t *m, uint8_t type, uint32_t value) {
 	m->prop[i].value.num = value;
 }
 
+// ------------------------------------------------------------------------------------------------
+// convert aiString to identifier safe C string. This is a duplication of _m3d_safestr
+char *SafeStr(aiString str, bool isStrict)
+{
+	char *s = (char *)&str.data;
+	char *d, *ret;
+	int i, len;
+
+	for(len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--);
+	if(len > 255) len = 255;
+	ret = (char *)M3D_MALLOC(len + 1);
+	if (!ret) {
+		throw DeadlyExportError("memory allocation error");
+	}
+	for(i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) {
+		*d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s);
+	}
+	for(; d > ret && (*(d-1) == ' ' || *(d-1) == '\t'); d--);
+	*d = 0;
+	return ret;
+}
+
 // ------------------------------------------------------------------------------------------------
 // add a material to the output
 M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
@@ -157,7 +178,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
 			if (!m3d->material) {
 				throw DeadlyExportError("memory allocation error");
 			}
-			m3d->material[mi].name = _m3d_safestr((char *)&name.data, 0);
+			m3d->material[mi].name = SafeStr(name, true);
 			m3d->material[mi].numprop = 0;
 			m3d->material[mi].prop = NULL;
 			// iterate through the material property table and see what we got
@@ -218,7 +239,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
 							(name.data[j + 1] == 'g' || name.data[j + 1] == 'G'))
 						name.data[j] = 0;
 					// do we have this texture saved already?
-					fn = _m3d_safestr((char *)&name.data, 0);
+					fn = SafeStr(name, true);
 					for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++)
 						if (!strcmp(fn, m3d->texture[j].name)) {
 							i = j;
@@ -275,11 +296,15 @@ void ExportSceneA3D(
 		const ExportProperties *pProperties
 
 ) {
+#ifdef M3D_ASCII
 	// initialize the exporter
 	M3DExporter exporter(pScene, pProperties);
 
 	// perform ascii export
 	exporter.doExport(pFile, pIOSystem, true);
+#else
+	throw DeadlyExportError("Assimp configured without M3D_ASCII support");
+#endif
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -306,7 +331,7 @@ void M3DExporter::doExport(
 	if (!m3d) {
 		throw DeadlyExportError("memory allocation error");
 	}
-	m3d->name = _m3d_safestr((char *)&mScene->mRootNode->mName.data, 2);
+	m3d->name = SafeStr(mScene->mRootNode->mName, false);
 
 	// Create a model from assimp structures
 	aiMatrix4x4 m;

+ 53 - 29
code/M3D/M3DImporter.cpp

@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
 
 #define M3D_IMPLEMENTATION
-#define M3D_ASCII
 #define M3D_NONORMALS /* leave the post-processing to Assimp */
 #define M3D_NOWEIGHTS
 #define M3D_NOANIMATION
@@ -57,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Importer.hpp>
 #include <memory>
 
+#include "M3DWrapper.h"
 #include "M3DImporter.h"
 #include "M3DMaterials.h"
-#include "M3DWrapper.h"
 
 // RESOURCES:
 // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md
@@ -96,7 +95,11 @@ static const aiImporterDesc desc = {
 	0,
 	0,
 	0,
+#ifdef M3D_ASCII
 	"m3d a3d"
+#else
+	"m3d"
+#endif
 };
 
 namespace Assimp {
@@ -113,7 +116,11 @@ M3DImporter::M3DImporter() :
 bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
 	const std::string extension = GetExtension(pFile);
 
-	if (extension == "m3d" || extension == "a3d")
+	if (extension == "m3d"
+#ifdef M3D_ASCII
+		|| extension == "a3d"
+#endif
+		)
 		return true;
 	else if (!extension.length() || checkSig) {
 		if (!pIOHandler) {
@@ -131,7 +138,11 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
 		if (4 != pStream->Read(data, 1, 4)) {
 			return false;
 		}
-		return !memcmp(data, "3DMO", 4) /* bin */ || !memcmp(data, "3dmo", 4) /* ASCII */;
+		return !memcmp(data, "3DMO", 4) /* bin */
+#ifdef M3D_ASCII
+			|| !memcmp(data, "3dmo", 4) /* ASCII */
+#endif
+		;
 	}
 	return false;
 }
@@ -163,6 +174,12 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
 	if(!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) {
 		throw DeadlyImportError("Bad binary header in file " + file + ".");
 	}
+#ifdef M3D_ASCII
+	// make sure there's a terminator zero character, as input must be ASCIIZ
+	if(!memcmp(buffer.data(), "3dmo", 4)) {
+		buffer.push_back(0);
+	}
+#endif
 
 	// Get the path for external assets
 	std::string folderName("./");
@@ -180,7 +197,6 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
 	// let the C SDK do the hard work for us
 	M3DWrapper m3d(pIOHandler, buffer);
 
-
 	if (!m3d) {
 		throw DeadlyImportError("Unable to parse " + file + " as M3D.");
 	}
@@ -310,32 +326,40 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
 	for (i = 0; i < m3d->numtexture; i++) {
 		unsigned int j, k;
 		t = &m3d->texture[i];
-		if (!t->w || !t->h || !t->f || !t->d) continue;
 		aiTexture *tx = new aiTexture;
-		strcpy(tx->achFormatHint, formatHint[t->f - 1]);
 		tx->mFilename = aiString(std::string(t->name) + ".png");
-		tx->mWidth = t->w;
-		tx->mHeight = t->h;
-		tx->pcData = new aiTexel[tx->mWidth * tx->mHeight];
-		for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) {
-			switch (t->f) {
-				case 1: tx->pcData[j].g = t->d[k++]; break;
-				case 2:
-					tx->pcData[j].g = t->d[k++];
-					tx->pcData[j].a = t->d[k++];
-					break;
-				case 3:
-					tx->pcData[j].r = t->d[k++];
-					tx->pcData[j].g = t->d[k++];
-					tx->pcData[j].b = t->d[k++];
-					tx->pcData[j].a = 255;
-					break;
-				case 4:
-					tx->pcData[j].r = t->d[k++];
-					tx->pcData[j].g = t->d[k++];
-					tx->pcData[j].b = t->d[k++];
-					tx->pcData[j].a = t->d[k++];
-					break;
+		if (!t->w || !t->h || !t->f || !t->d) {
+			/* without ASSIMP_USE_M3D_READFILECB, we only have the filename, but no texture data ever */
+			tx->mWidth = 0;
+			tx->mHeight = 0;
+			memcpy(tx->achFormatHint, "png\000", 4);
+			tx->pcData = nullptr;
+		} else {
+			/* if we have the texture loaded, set format hint and pcData too */
+			tx->mWidth = t->w;
+			tx->mHeight = t->h;
+			strcpy(tx->achFormatHint, formatHint[t->f - 1]);
+			tx->pcData = new aiTexel[tx->mWidth * tx->mHeight];
+			for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) {
+				switch (t->f) {
+					case 1: tx->pcData[j].g = t->d[k++]; break;
+					case 2:
+						tx->pcData[j].g = t->d[k++];
+						tx->pcData[j].a = t->d[k++];
+						break;
+					case 3:
+						tx->pcData[j].r = t->d[k++];
+						tx->pcData[j].g = t->d[k++];
+						tx->pcData[j].b = t->d[k++];
+						tx->pcData[j].a = 255;
+						break;
+					case 4:
+						tx->pcData[j].r = t->d[k++];
+						tx->pcData[j].g = t->d[k++];
+						tx->pcData[j].b = t->d[k++];
+						tx->pcData[j].a = t->d[k++];
+						break;
+				}
 			}
 		}
 		mScene->mTextures[i] = tx;

+ 14 - 7
code/M3D/M3DWrapper.cpp

@@ -48,15 +48,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOStreamBuffer.h>
 #include <assimp/ai_assert.h>
 
-#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
-# define threadlocal thread_local
-#else
-# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
-#  define threadlocal __declspec(thread)
+#ifdef ASSIMP_USE_M3D_READFILECB
+
+# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
+#  define threadlocal thread_local
 # else
-#  define threadlocal
+#  if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
+#   define threadlocal __declspec(thread)
+#  else
+#   define threadlocal
+#  endif
 # endif
-#endif
 
 extern "C" {
 
@@ -89,6 +91,7 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
 	return data;
 }
 }
+#endif
 
 namespace Assimp {
 M3DWrapper::M3DWrapper() {
@@ -97,11 +100,15 @@ M3DWrapper::M3DWrapper() {
 }
 
 M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
+#ifdef ASSIMP_USE_M3D_READFILECB
 	// pass this IOHandler to the C callback in a thread-local pointer
 	m3dimporter_pIOHandler = pIOHandler;
 	m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
 	// Clear the C callback
 	m3dimporter_pIOHandler = nullptr;
+#else
+	m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
+#endif
 }
 
 M3DWrapper::~M3DWrapper() {

+ 4 - 0
code/M3D/M3DWrapper.h

@@ -52,6 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <vector>
 #include <string>
 
+// Assimp specific M3D configuration. Comment out these defines to remove functionality
+#define ASSIMP_USE_M3D_READFILECB
+#define M3D_ASCII
+
 #include "m3d.h"
 
 namespace Assimp {

+ 29 - 28
code/M3D/m3d.h

@@ -91,11 +91,7 @@ typedef uint16_t M3D_INDEX;
 #else
 #define _inline
 #define _pack
-#  ifdef __cplusplus /* only for c++ code */
-#    define _unused __pragma(warning(suppress:4100))
-#  else
-#    define _unused (void)
-#  endif
+#define _unused __pragma(warning(suppress:4100))
 #endif
 #ifndef  __cplusplus
 #define _register register
@@ -2064,7 +2060,7 @@ static char *_m3d_getfloat(char *s, M3D_FLOAT *ret)
     return _m3d_findarg(e);
 }
 #endif
-#if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER))
+#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_ASCII) || defined(M3D_EXPORTER))
 /* helper function to create safe strings */
 char *_m3d_safestr(char *in, int morelines)
 {
@@ -2139,45 +2135,48 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
             buff = (*readfilecb)(fn2, &len);
             M3D_FREE(fn2);
         }
-        if(!buff)
+        if(!buff) {
             buff = (*readfilecb)(fn, &len);
+            if(!buff) return M3D_UNDEF;
+        }
     }
-    if(!buff) return M3D_UNDEF;
     /* add to textures array */
     i = model->numtexture++;
     model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t));
     if(!model->texture) {
-        if(freecb) (*freecb)(buff);
+        if(buff && freecb) (*freecb)(buff);
         model->errcode = M3D_ERR_ALLOC;
         return M3D_UNDEF;
     }
     model->texture[i].name = fn;
     model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL;
-    if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
+    if(buff) {
+        if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
 #ifdef STBI__PNG_TYPE
-        s.read_from_callbacks = 0;
-        s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
-        s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
-        /* don't use model->texture[i].w directly, it's a uint16_t */
-        w = h = len = 0;
-        ri.bits_per_channel = 8;
-        model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri);
-        model->texture[i].w = w;
-        model->texture[i].h = h;
-        model->texture[i].f = (uint8_t)len;
+            s.read_from_callbacks = 0;
+            s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
+            s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
+            /* don't use model->texture[i].w directly, it's a uint16_t */
+            w = h = len = 0;
+            ri.bits_per_channel = 8;
+            model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri);
+            model->texture[i].w = w;
+            model->texture[i].h = h;
+            model->texture[i].f = (uint8_t)len;
 #endif
-    } else {
+        } else {
 #ifdef M3D_TX_INTERP
-        if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
-            M3D_LOG("Unable to generate texture");
-            M3D_LOG(fn);
-        }
+            if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
+                M3D_LOG("Unable to generate texture");
+                M3D_LOG(fn);
+            }
 #else
-        M3D_LOG("Unimplemented interpreter");
-        M3D_LOG(fn);
+            M3D_LOG("Unimplemented interpreter");
+            M3D_LOG(fn);
 #endif
+        }
+        if(freecb) (*freecb)(buff);
     }
-    if(freecb) (*freecb)(buff);
     if(!model->texture[i].d)
         model->errcode = M3D_ERR_UNKIMG;
     return i;
@@ -2589,6 +2588,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
                                 if(!pe || !*pe) goto asciiend;
                                 m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe);
                                 if(model->errcode == M3D_ERR_ALLOC) { M3D_FREE(pe); goto memerr; }
+                                /* this error code only returned if readfilecb was specified */
                                 if(m->prop[j].value.textureid == M3D_UNDEF) {
                                     M3D_LOG("Texture not found");
                                     M3D_LOG(pe);
@@ -3254,6 +3254,7 @@ memerr:         M3D_LOG("Out of memory");
                             M3D_GETSTR(name);
                             m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name);
                             if(model->errcode == M3D_ERR_ALLOC) goto memerr;
+                            /* this error code only returned if readfilecb was specified */
                             if(m->prop[i].value.textureid == M3D_UNDEF) {
                                 M3D_LOG("Texture not found");
                                 M3D_LOG(m->name);