Merge branch 'master' into fix_vertex_weighted_repeatedly

pull/2752/head
Kim Kulling 2019-12-01 22:46:18 +01:00 committed by GitHub
commit 54720e36cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 209 additions and 107 deletions

View File

@ -253,7 +253,7 @@ ELSEIF(MSVC)
IF(MSVC12) IF(MSVC12)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi") SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi /O0")
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
IF(NOT HUNTER_ENABLED) IF(NOT HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")

View File

@ -3234,13 +3234,12 @@ void ColladaParser::ReadScene()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception // Aborts the file reading with an exception
AI_WONT_RETURN void ColladaParser::ThrowException(const std::string& pError) const AI_WONT_RETURN void ColladaParser::ThrowException(const std::string& pError) const {
{
throw DeadlyImportError(format() << "Collada: " << mFileName << " - " << pError); throw DeadlyImportError(format() << "Collada: " << mFileName << " - " << pError);
} }
void ColladaParser::ReportWarning(const char* msg, ...)
{ void ColladaParser::ReportWarning(const char* msg, ...) {
ai_assert(NULL != msg); ai_assert(nullptr != msg);
va_list args; va_list args;
va_start(args, msg); va_start(args, msg);
@ -3255,11 +3254,11 @@ void ColladaParser::ReportWarning(const char* msg, ...)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the current element // Skips all data until the end node of the current element
void ColladaParser::SkipElement() void ColladaParser::SkipElement() {
{
// nothing to skip if it's an <element /> // nothing to skip if it's an <element />
if (mReader->isEmptyElement()) if (mReader->isEmptyElement()) {
return; return;
}
// reroute // reroute
SkipElement(mReader->getNodeName()); SkipElement(mReader->getNodeName());
@ -3267,63 +3266,75 @@ void ColladaParser::SkipElement()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the given element // Skips all data until the end node of the given element
void ColladaParser::SkipElement(const char* pElement) void ColladaParser::SkipElement(const char* pElement) {
{
// copy the current node's name because it'a pointer to the reader's internal buffer, // copy the current node's name because it'a pointer to the reader's internal buffer,
// which is going to change with the upcoming parsing // which is going to change with the upcoming parsing
std::string element = pElement; std::string element = pElement;
while (mReader->read()) while (mReader->read()) {
{ if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) if (mReader->getNodeName() == element) {
if (mReader->getNodeName() == element)
break; break;
} }
}
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for an opening element of the given name, throws an exception if not found // Tests for an opening element of the given name, throws an exception if not found
void ColladaParser::TestOpening(const char* pName) void ColladaParser::TestOpening(const char* pName) {
{
// read element start // read element start
if (!mReader->read()) if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element."); ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element.");
}
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading beginning of <" << pName << "> element."); ThrowException(format() << "Unexpected end of file while reading beginning of <" << pName << "> element.");
}
}
if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected start of <" << pName << "> element."); ThrowException(format() << "Expected start of <" << pName << "> element.");
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for the closing tag of the given element, throws an exception if not found // Tests for the closing tag of the given element, throws an exception if not found
void ColladaParser::TestClosing(const char* pName) void ColladaParser::TestClosing(const char* pName) {
{ // check if we have an empty (self-closing) element
// check if we're already on the closing tag and return right away if (mReader->isEmptyElement()) {
if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0)
return; return;
}
// check if we're already on the closing tag and return right away
if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0) {
return;
}
// if not, read some more // if not, read some more
if (!mReader->read()) if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element.");
}
// whitespace in front is ok, just read again if found // whitespace in front is ok, just read again if found
if (mReader->getNodeType() == irr::io::EXN_TEXT) if (mReader->getNodeType() == irr::io::EXN_TEXT) {
if (!mReader->read()) if (!mReader->read()) {
ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element.");
}
}
// but this has the be the closing tag, or we're lost // but this has the be the closing tag, or we're lost
if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) {
ThrowException(format() << "Expected end of <" << pName << "> element."); ThrowException(format() << "Expected end of <" << pName << "> element.");
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes // Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
int ColladaParser::GetAttribute(const char* pAttr) const int ColladaParser::GetAttribute(const char* pAttr) const {
{
int index = TestAttribute(pAttr); int index = TestAttribute(pAttr);
if (index != -1) if (index != -1) {
return index; return index;
}
// attribute not found -> throw an exception // attribute not found -> throw an exception
ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");

View File

@ -66,6 +66,12 @@ ASSIMP_API const char* aiGetLegalString () {
return LEGAL_INFORMATION; return LEGAL_INFORMATION;
} }
// ------------------------------------------------------------------------------------------------
// Get Assimp patch version
ASSIMP_API unsigned int aiGetVersionPatch() {
return VER_PATCH;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get Assimp minor version // Get Assimp minor version
ASSIMP_API unsigned int aiGetVersionMinor () { ASSIMP_API unsigned int aiGetVersionMinor () {

View File

@ -388,7 +388,7 @@ typedef struct {
/* label entry */ /* label entry */
typedef struct { typedef struct {
char *name; /* name of the annotation group or NULL */ char *name; /* name of the annotation layer or NULL */
char *lang; /* language code or NULL */ char *lang; /* language code or NULL */
char *text; /* the label text */ char *text; /* the label text */
uint32_t color; /* color */ uint32_t color; /* color */
@ -438,7 +438,7 @@ typedef struct {
typedef struct { typedef struct {
m3dhdr_t *raw; /* pointer to raw data */ m3dhdr_t *raw; /* pointer to raw data */
char flags; /* internal flags */ char flags; /* internal flags */
char errcode; /* returned error code */ signed char errcode; /* returned error code */
char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s,fi_s; /* decoded sizes for types */ char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s,fi_s; /* decoded sizes for types */
char *name; /* name of the model, like "Utah teapot" */ char *name; /* name of the model, like "Utah teapot" */
char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */ char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */
@ -1192,7 +1192,6 @@ static int _m3dstbi__parse_zlib(_m3dstbi__zbuf *a, int parse_header)
return 0; return 0;
} else { } else {
if (type == 1) { if (type == 1) {
_m3dstbi__init_zdefaults();
if (!_m3dstbi__zbuild_huffman(&a->z_length , _m3dstbi__zdefault_length , 288)) return 0; if (!_m3dstbi__zbuild_huffman(&a->z_length , _m3dstbi__zdefault_length , 288)) return 0;
if (!_m3dstbi__zbuild_huffman(&a->z_distance, _m3dstbi__zdefault_distance, 32)) return 0; if (!_m3dstbi__zbuild_huffman(&a->z_distance, _m3dstbi__zdefault_distance, 32)) return 0;
} else { } else {
@ -1210,7 +1209,7 @@ static int _m3dstbi__do_zlib(_m3dstbi__zbuf *a, char *obuf, int olen, int exp, i
a->zout = obuf; a->zout = obuf;
a->zout_end = obuf + olen; a->zout_end = obuf + olen;
a->z_expandable = exp; a->z_expandable = exp;
_m3dstbi__init_zdefaults();
return _m3dstbi__parse_zlib(a, parse_header); return _m3dstbi__parse_zlib(a, parse_header);
} }
@ -2012,6 +2011,9 @@ unsigned char * _m3dstbi_zlib_compress(unsigned char *data, int data_len, int *o
#include <stdio.h> /* get sprintf */ #include <stdio.h> /* get sprintf */
#include <locale.h> /* sprintf and strtod cares about number locale */ #include <locale.h> /* sprintf and strtod cares about number locale */
#endif #endif
#ifdef M3D_PROFILING
#include <sys/time.h>
#endif
#if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII) #if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII)
/* helper functions for the ASCII parser */ /* helper functions for the ASCII parser */
@ -2088,7 +2090,7 @@ char *_m3d_safestr(char *in, int morelines)
} }
for(; o > out && (*(o-1) == ' ' || *(o-1) == '\t' || *(o-1) == '\r' || *(o-1) == '\n'); o--); for(; o > out && (*(o-1) == ' ' || *(o-1) == '\t' || *(o-1) == '\r' || *(o-1) == '\n'); o--);
*o = 0; *o = 0;
out = (char*)M3D_REALLOC(out, (uint64_t)o - (uint64_t)out + 1); out = (char*)M3D_REALLOC(out, (uintptr_t)o - (uintptr_t)out + 1);
} }
return out; return out;
} }
@ -2322,6 +2324,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
m3da_t *a; m3da_t *a;
m3di_t *t; m3di_t *t;
#ifndef M3D_NONORMALS #ifndef M3D_NONORMALS
char neednorm = 0;
m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb; m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb;
#endif #endif
#ifndef M3D_NOANIMATION #ifndef M3D_NOANIMATION
@ -2339,6 +2342,10 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
const char *ol; const char *ol;
char *ptr, *pe, *fn; char *ptr, *pe, *fn;
#endif #endif
#ifdef M3D_PROFILING
struct timeval tv0, tv1, tvd;
gettimeofday(&tv0, NULL);
#endif
if(!data || (!M3D_CHUNKMAGIC(data, '3','D','M','O') if(!data || (!M3D_CHUNKMAGIC(data, '3','D','M','O')
#ifdef M3D_ASCII #ifdef M3D_ASCII
@ -2647,6 +2654,9 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
if(!*ptr) goto asciiend; if(!*ptr) goto asciiend;
} }
} }
#ifndef M3D_NONORMALS
if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1;
#endif
ptr = _m3d_findarg(ptr); ptr = _m3d_findarg(ptr);
} }
} }
@ -2870,7 +2880,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
pe = _m3d_findarg(pe); pe = _m3d_findarg(pe);
if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend;
buff = (unsigned char*)_m3d_findnl(ptr); buff = (unsigned char*)_m3d_findnl(ptr);
k = ((uint32_t)((uint64_t)buff - (uint64_t)ptr) / 3) + 1; k = ((uint32_t)((uintptr_t)buff - (uintptr_t)ptr) / 3) + 1;
i = model->numextra++; i = model->numextra++;
model->extra = (m3dchunk_t**)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t*)); model->extra = (m3dchunk_t**)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t*));
if(!model->extra) goto memerr; if(!model->extra) goto memerr;
@ -2892,8 +2902,8 @@ asciiend:
setlocale(LC_NUMERIC, ol); setlocale(LC_NUMERIC, ol);
goto postprocess; goto postprocess;
} }
/* Binary variant */
#endif #endif
/* Binary variant */
if(!M3D_CHUNKMAGIC(data + 8, 'H','E','A','D')) { if(!M3D_CHUNKMAGIC(data + 8, 'H','E','A','D')) {
buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, ((m3dchunk_t*)data)->length-8, buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, ((m3dchunk_t*)data)->length-8,
4096, (int*)&len, 1); 4096, (int*)&len, 1);
@ -2905,6 +2915,14 @@ asciiend:
buff = (unsigned char*)M3D_REALLOC(buff, len); buff = (unsigned char*)M3D_REALLOC(buff, len);
model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */ model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */
data = buff; data = buff;
#ifdef M3D_PROFILING
gettimeofday(&tv1, NULL);
tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
printf(" Deflate model %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
memcpy(&tv0, &tv1, sizeof(struct timeval));
#endif
} else { } else {
len = ((m3dhdr_t*)data)->length; len = ((m3dhdr_t*)data)->length;
data += 8; data += 8;
@ -2961,7 +2979,7 @@ asciiend:
return NULL; return NULL;
} }
if(model->nb_s > M3D_NUMBONE) { if(model->nb_s > M3D_NUMBONE) {
M3D_LOG("Model has more bones per vertex than what importer configured to support"); M3D_LOG("Model has more bones per vertex than what importer was configured to support");
model->errcode = M3D_ERR_TRUNC; model->errcode = M3D_ERR_TRUNC;
} }
@ -3295,6 +3313,9 @@ memerr: M3D_LOG("Out of memory");
/* normal */ /* normal */
if(k & 2) if(k & 2)
data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]); data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]);
#ifndef M3D_NONORMALS
if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1;
#endif
} }
} }
model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t)); model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t));
@ -3454,9 +3475,18 @@ postprocess:
#endif #endif
if(model) { if(model) {
M3D_LOG("Post-process"); M3D_LOG("Post-process");
#ifdef M3D_PROFILING
gettimeofday(&tv1, NULL);
tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;
tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
printf(" Parsing chunks %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
#endif
#ifndef M3D_NONORMALS #ifndef M3D_NONORMALS
if(model->numface && model->face) { if(model->numface && model->face && neednorm) {
/* if they are missing, calculate triangle normals into a temporary buffer */ /* if they are missing, calculate triangle normals into a temporary buffer */
norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t));
if(!norm) goto memerr;
for(i = 0, n = model->numvertex; i < model->numface; i++) for(i = 0, n = model->numvertex; i < model->numface; i++)
if(model->face[i].normal[0] == -1U) { if(model->face[i].normal[0] == -1U) {
v0 = &model->vertex[model->face[i].vertex[0]]; v0 = &model->vertex[model->face[i].vertex[0]];
@ -3464,10 +3494,6 @@ postprocess:
v2 = &model->vertex[model->face[i].vertex[2]]; v2 = &model->vertex[model->face[i].vertex[2]];
va.x = v1->x - v0->x; va.y = v1->y - v0->y; va.z = v1->z - v0->z; va.x = v1->x - v0->x; va.y = v1->y - v0->y; va.z = v1->z - v0->z;
vb.x = v2->x - v0->x; vb.y = v2->y - v0->y; vb.z = v2->z - v0->z; vb.x = v2->x - v0->x; vb.y = v2->y - v0->y; vb.z = v2->z - v0->z;
if(!norm) {
norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t));
if(!norm) goto memerr;
}
v0 = &norm[i]; v0 = &norm[i];
v0->x = (va.y * vb.z) - (va.z * vb.y); v0->x = (va.y * vb.z) - (va.z * vb.y);
v0->y = (va.z * vb.x) - (va.x * vb.z); v0->y = (va.z * vb.x) - (va.x * vb.z);
@ -3479,7 +3505,6 @@ postprocess:
model->face[i].normal[2] = model->face[i].vertex[2] + n; model->face[i].normal[2] = model->face[i].vertex[2] + n;
} }
/* this is the fast way, we don't care if a normal is repeated in model->vertex */ /* this is the fast way, we don't care if a normal is repeated in model->vertex */
if(norm) {
M3D_LOG("Generating normals"); M3D_LOG("Generating normals");
model->flags |= M3D_FLG_GENNORM; model->flags |= M3D_FLG_GENNORM;
model->numvertex <<= 1; model->numvertex <<= 1;
@ -3501,7 +3526,6 @@ postprocess:
} }
M3D_FREE(norm); M3D_FREE(norm);
} }
}
#endif #endif
if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) { if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) {
#ifndef M3D_NOWEIGHTS #ifndef M3D_NOWEIGHTS
@ -3539,6 +3563,13 @@ postprocess:
_m3d_inv((M3D_FLOAT*)&model->bone[i].mat4); _m3d_inv((M3D_FLOAT*)&model->bone[i].mat4);
#endif #endif
} }
#ifdef M3D_PROFILING
gettimeofday(&tv0, NULL);
tvd.tv_sec = tv0.tv_sec - tv1.tv_sec;
tvd.tv_usec = tv0.tv_usec - tv1.tv_usec;
if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
printf(" Post-process %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec);
#endif
} }
return model; return model;
} }
@ -4509,8 +4540,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(model->preview.data && model->preview.length) { if(model->preview.data && model->preview.length) {
sl = _m3d_safestr(sn, 0); sl = _m3d_safestr(sn, 0);
if(sl) { if(sl) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + 20; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 20;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl); ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl);
M3D_FREE(sl); sl = NULL; M3D_FREE(sl); sl = NULL;
@ -4519,8 +4550,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
M3D_FREE(sn); sn = NULL; M3D_FREE(sn); sn = NULL;
/* texture map */ /* texture map */
if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + maxtmap * 32 + 12; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxtmap * 32 + 12;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Textmap\r\n"); ptr += sprintf(ptr, "Textmap\r\n");
last = (M3D_INDEX)-1U; last = (M3D_INDEX)-1U;
@ -4533,8 +4564,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
/* vertex chunk */ /* vertex chunk */
if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) { if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + maxvrtx * 128 + 10; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxvrtx * 128 + 10;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Vertex\r\n"); ptr += sprintf(ptr, "Vertex\r\n");
last = (M3D_INDEX)-1U; last = (M3D_INDEX)-1U;
@ -4559,11 +4590,11 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
/* bones chunk */ /* bones chunk */
if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + 9; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 9;
for(i = 0; i < model->numbone; i++) { for(i = 0; i < model->numbone; i++) {
len += strlen(model->bone[i].name) + 128; len += strlen(model->bone[i].name) + 128;
} }
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Bones\r\n"); ptr += sprintf(ptr, "Bones\r\n");
ptr = _m3d_prtbone(ptr, model->bone, model->numbone, (M3D_INDEX)-1U, 0, vrtxidx); ptr = _m3d_prtbone(ptr, model->bone, model->numbone, (M3D_INDEX)-1U, 0, vrtxidx);
@ -4576,14 +4607,14 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
m = &model->material[j]; m = &model->material[j];
sn = _m3d_safestr(m->name, 0); sn = _m3d_safestr(m->name, 0);
if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 12; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 12;
for(i = 0; i < m->numprop; i++) { for(i = 0; i < m->numprop; i++) {
if(m->prop[i].type < 128) if(m->prop[i].type < 128)
len += 32; len += 32;
else if(m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name) else if(m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name)
len += strlen(model->texture[m->prop[i].value.textureid].name) + 16; len += strlen(model->texture[m->prop[i].value.textureid].name) + 16;
} }
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Material %s\r\n", sn); ptr += sprintf(ptr, "Material %s\r\n", sn);
M3D_FREE(sn); sn = NULL; M3D_FREE(sn); sn = NULL;
@ -4645,8 +4676,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(k) continue; if(k) continue;
sn = _m3d_safestr(model->inlined[j].name, 0); sn = _m3d_safestr(model->inlined[j].name, 0);
if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 18; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 18;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn); ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn);
M3D_FREE(sn); sn = NULL; M3D_FREE(sn); sn = NULL;
@ -4654,7 +4685,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
/* mesh face */ /* mesh face */
if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { if(model->numface && face && !(flags & M3D_EXP_NOFACE)) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + model->numface * 128 + 6; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + model->numface * 128 + 6;
last = (M3D_INDEX)-1U; last = (M3D_INDEX)-1U;
if(!(flags & M3D_EXP_NOMATERIAL)) if(!(flags & M3D_EXP_NOMATERIAL))
for(i = 0; i < model->numface; i++) { for(i = 0; i < model->numface; i++) {
@ -4666,7 +4697,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
len += 6; len += 6;
} }
} }
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Mesh\r\n"); ptr += sprintf(ptr, "Mesh\r\n");
last = (M3D_INDEX)-1U; last = (M3D_INDEX)-1U;
@ -4703,8 +4734,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
for(j = 0; j < model->numshape; j++) { for(j = 0; j < model->numshape; j++) {
sn = _m3d_safestr(model->shape[j].name, 0); sn = _m3d_safestr(model->shape[j].name, 0);
if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 33; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 33;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Shape %s\r\n", sn); ptr += sprintf(ptr, "Shape %s\r\n", sn);
M3D_FREE(sn); sn = NULL; M3D_FREE(sn); sn = NULL;
@ -4715,14 +4746,14 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg)
continue; continue;
cd = &m3d_commandtypes[cmd->type]; cd = &m3d_commandtypes[cmd->type];
ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(cd->key) + 3; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(cd->key) + 3;
for(k = 0; k < cd->p; k++) for(k = 0; k < cd->p; k++)
switch(cd->a[k]) { switch(cd->a[k]) {
case m3dcp_mi_t: if(cmd->arg[k] != -1U) { len += strlen(model->material[cmd->arg[k]].name) + 1; } break; case m3dcp_mi_t: if(cmd->arg[k] != -1U) { len += strlen(model->material[cmd->arg[k]].name) + 1; } break;
case m3dcp_va_t: len += cmd->arg[k] * (cd->p - k - 1) * 16; k = cd->p; break; case m3dcp_va_t: len += cmd->arg[k] * (cd->p - k - 1) * 16; k = cd->p; break;
default: len += 16; break; default: len += 16; break;
} }
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "%s", cd->key); ptr += sprintf(ptr, "%s", cd->key);
for(k = n = 0, l = cd->p; k < l; k++) { for(k = n = 0, l = cd->p; k < l; k++) {
@ -4755,8 +4786,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(model->label[i].text) j += strlen(model->label[i].text); if(model->label[i].text) j += strlen(model->label[i].text);
j += 40; j += 40;
} }
ptr -= (uint64_t)out; len = (uint64_t)ptr + j; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
for(i = 0; i < model->numlabel; i++) { for(i = 0; i < model->numlabel; i++) {
if(!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) { if(!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) {
@ -4790,10 +4821,10 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
a = &model->action[j]; a = &model->action[j];
sn = _m3d_safestr(a->name, 0); sn = _m3d_safestr(a->name, 0);
if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 48; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 48;
for(i = 0; i < a->numframe; i++) for(i = 0; i < a->numframe; i++)
len += a->frame[i].numtransform * 128 + 8; len += a->frame[i].numtransform * 128 + 8;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn); ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn);
M3D_FREE(sn); sn = NULL; M3D_FREE(sn); sn = NULL;
@ -4813,8 +4844,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(model->inlined[i].name) if(model->inlined[i].name)
j += strlen(model->inlined[i].name) + 6; j += strlen(model->inlined[i].name) + 6;
if(j > 0) { if(j > 0) {
ptr -= (uint64_t)out; len = (uint64_t)ptr + j + 16; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j + 16;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Assets\r\n"); ptr += sprintf(ptr, "Assets\r\n");
for(i = 0; i < model->numinlined; i++) for(i = 0; i < model->numinlined; i++)
@ -4827,8 +4858,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
if(model->numextra && (flags & M3D_EXP_EXTRA)) { if(model->numextra && (flags & M3D_EXP_EXTRA)) {
for(i = 0; i < model->numextra; i++) { for(i = 0; i < model->numextra; i++) {
if(model->extra[i]->length < 9) continue; if(model->extra[i]->length < 9) continue;
ptr -= (uint64_t)out; len = (uint64_t)ptr + 17 + model->extra[i]->length * 3; ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 17 + model->extra[i]->length * 3;
out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out;
if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; }
ptr += sprintf(ptr, "Extra %c%c%c%c\r\n", ptr += sprintf(ptr, "Extra %c%c%c%c\r\n",
model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_', model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_',
@ -4842,7 +4873,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
} }
setlocale(LC_NUMERIC, ol); setlocale(LC_NUMERIC, ol);
len = (uint64_t)ptr - (uint64_t)out; len = (uintptr_t)ptr - (uintptr_t)out;
out = (unsigned char*)M3D_REALLOC(out, len + 1); out = (unsigned char*)M3D_REALLOC(out, len + 1);
if(!out) goto memerr; if(!out) goto memerr;
out[len] = 0; out[len] = 0;
@ -4943,7 +4974,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
case 8: *((double*)out) = tmap[i].data.u; out += 8; *((double*)out) = tmap[i].data.v; out += 8; break; case 8: *((double*)out) = tmap[i].data.u; out += 8; *((double*)out) = tmap[i].data.v; out += 8; break;
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
out = NULL; out = NULL;
len += *length; len += *length;
} }
@ -4993,7 +5024,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid); out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
out = NULL; out = NULL;
len += *length; len += *length;
} }
@ -5035,7 +5066,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
out = NULL; out = NULL;
len += *length; len += *length;
} }
@ -5084,7 +5115,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
break; break;
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
out = NULL; out = NULL;
} }
@ -5144,7 +5175,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]); out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
out = NULL; out = NULL;
} }
@ -5195,7 +5226,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
} }
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
out = NULL; out = NULL;
} }
@ -5207,7 +5238,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
sl = model->label[i].lang; sl = model->label[i].lang;
sn = model->label[i].name; sn = model->label[i].name;
if(length) { if(length) {
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
} }
chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s); chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s);
@ -5229,7 +5260,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text)); out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
} }
if(length) { if(length) {
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
} }
out = NULL; out = NULL;
@ -5257,7 +5288,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]); out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
} }
} }
*length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len);
len += *length; len += *length;
out = NULL; out = NULL;
} }

View File

@ -273,14 +273,14 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a aiUVTransform (4 floats) from the material // Get a aiUVTransform (5 floats) from the material
aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat, aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
const char* pKey, const char* pKey,
unsigned int type, unsigned int type,
unsigned int index, unsigned int index,
aiUVTransform* pOut) aiUVTransform* pOut)
{ {
unsigned int iMax = 4; unsigned int iMax = 5;
return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax); return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
} }

View File

@ -1034,6 +1034,12 @@ namespace glTF2
bool KHR_texture_transform; bool KHR_texture_transform;
} extensionsUsed; } extensionsUsed;
//! Keeps info about the required extensions
struct RequiredExtensions
{
bool KHR_draco_mesh_compression;
} extensionsRequired;
AssetMetadata asset; AssetMetadata asset;
@ -1076,6 +1082,7 @@ namespace glTF2
, textures (*this, "textures") , textures (*this, "textures")
{ {
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); memset(&extensionsUsed, 0, sizeof(extensionsUsed));
memset(&extensionsRequired, 0, sizeof(extensionsRequired));
} }
//! Main function //! Main function
@ -1094,6 +1101,7 @@ namespace glTF2
void ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData); void ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData);
void ReadExtensionsUsed(Document& doc); void ReadExtensionsUsed(Document& doc);
void ReadExtensionsRequired(Document& doc);
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
}; };

View File

@ -1432,6 +1432,12 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
// Load the metadata // Load the metadata
asset.Read(doc); asset.Read(doc);
ReadExtensionsUsed(doc); ReadExtensionsUsed(doc);
ReadExtensionsRequired(doc);
// Currently Draco is not supported
if (extensionsRequired.KHR_draco_mesh_compression) {
throw DeadlyImportError("GLTF: Draco mesh compression not currently supported.");
}
// Prepare the dictionaries // Prepare the dictionaries
for (size_t i = 0; i < mDicts.size(); ++i) { for (size_t i = 0; i < mDicts.size(); ++i) {
@ -1478,6 +1484,29 @@ inline void Asset::SetAsBinary()
} }
} }
// As required extensions are only a concept in glTF 2.0, this is here
// instead of glTFCommon.h
#define CHECK_REQUIRED_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true;
inline void Asset::ReadExtensionsRequired(Document& doc)
{
Value* extsRequired = FindArray(doc, "extensionsRequired");
if (nullptr == extsRequired) {
return;
}
std::gltf_unordered_map<std::string, bool> exts;
for (unsigned int i = 0; i < extsRequired->Size(); ++i) {
if ((*extsRequired)[i].IsString()) {
exts[(*extsRequired)[i].GetString()] = true;
}
}
CHECK_REQUIRED_EXT(KHR_draco_mesh_compression);
#undef CHECK_REQUIRED_EXT
}
inline void Asset::ReadExtensionsUsed(Document& doc) inline void Asset::ReadExtensionsUsed(Document& doc)
{ {

View File

@ -204,11 +204,21 @@ inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
if (prop.textureTransformSupported) { if (prop.textureTransformSupported) {
aiUVTransform transform; aiUVTransform transform;
transform.mTranslation.x = prop.TextureTransformExt_t.offset[0];
transform.mTranslation.y = prop.TextureTransformExt_t.offset[0];
transform.mRotation = prop.TextureTransformExt_t.rotation;
transform.mScaling.x = prop.TextureTransformExt_t.scale[0]; transform.mScaling.x = prop.TextureTransformExt_t.scale[0];
transform.mScaling.y = prop.TextureTransformExt_t.scale[1]; transform.mScaling.y = prop.TextureTransformExt_t.scale[1];
transform.mRotation = -prop.TextureTransformExt_t.rotation; // must be negated
// A change of coordinates is required to map glTF UV transformations into the space used by
// Assimp. In glTF all UV origins are at 0,1 (top left of texture) in Assimp space. In Assimp
// rotation occurs around the image center (0.5,0.5) where as in glTF rotation is around the
// texture origin. All three can be corrected for solely by a change of the translation since
// the transformations available are shape preserving. Note the importer already flips the V
// coordinate of the actual meshes during import.
const ai_real rcos(cos(-transform.mRotation));
const ai_real rsin(sin(-transform.mRotation));
transform.mTranslation.x = (0.5 * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0];
transform.mTranslation.y = ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];;
mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot);
} }

View File

@ -62,6 +62,13 @@ extern "C" {
*/ */
ASSIMP_API const char* aiGetLegalString (void); ASSIMP_API const char* aiGetLegalString (void);
// ---------------------------------------------------------------------------
/** @brief Returns the current patch version number of Assimp.
* @return Patch version of the Assimp runtime the application was
* linked/built against
*/
ASSIMP_API unsigned int aiGetVersionPatch(void);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Returns the current minor version number of Assimp. /** @brief Returns the current minor version number of Assimp.
* @return Minor version of the Assimp runtime the application was * @return Minor version of the Assimp runtime the application was