Merge branch 'master' into preserve_error_string

pull/2769/head
Mike Samsonov 2019-12-02 10:35:29 +00:00 committed by GitHub
commit 631da3a3d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 4770 additions and 2759 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
build build
.project .project
*.kdev4* *.kdev4*
.DS_Store
# build artefacts # build artefacts
*.o *.o

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

@ -60,14 +60,19 @@ __Importers__:
- ENFF - ENFF
- [FBX](https://en.wikipedia.org/wiki/FBX) - [FBX](https://en.wikipedia.org/wiki/FBX)
- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB - [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0) - [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0):
At the moment for glTF2.0 the following extensions are supported:
+ KHR_lights_punctual ( 5.0 )
+ KHR_materials_pbrSpecularGlossiness ( 5.0 )
+ KHR_materials_unlit ( 5.0 )
+ KHR_texture_transform ( 5.1 under test )
- HMB - HMB
- IFC-STEP - IFC-STEP
- IRR / IRRMESH - IRR / IRRMESH
- [LWO](https://en.wikipedia.org/wiki/LightWave_3D) - [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
- LWS - LWS
- LXO - LXO
- [M3D](https://gitlab.com/bztsrc/model3d) - [M3D](https://bztsrc.gitlab.io/model3d)
- MD2 - MD2
- MD3 - MD3
- MD5 - MD5

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

@ -107,7 +107,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
return nullptr; return nullptr;
#endif #endif
// Platform-independent default streams // Platform-independent default streams
case aiDefaultLogStream_STDERR: case aiDefaultLogStream_STDERR:
return new StdOStreamLogStream(std::cerr); return new StdOStreamLogStream(std::cerr);
case aiDefaultLogStream_STDOUT: case aiDefaultLogStream_STDOUT:
@ -121,7 +121,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
}; };
// For compilers without dead code path detection // For compilers without dead code path detection
return NULL; return nullptr;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -445,8 +445,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties;
pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again);
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
pimpl->mProgressHandler->UpdateFileWrite(4, 4); pimpl->mProgressHandler->UpdateFileWrite(4, 4);

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

@ -169,6 +169,33 @@ void M3DExporter::doExport (
outfile.reset(); outfile.reset();
} }
// ------------------------------------------------------------------------------------------------
// helper to add a vertex (private to NodeWalk)
m3dv_t *M3DExporter::AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx)
{
if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0;
if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0;
if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0;
if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0;
vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t));
memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t));
*idx = *numvrtx;
(*numvrtx)++;
return vrtx;
}
// ------------------------------------------------------------------------------------------------
// helper to add a tmap (private to NodeWalk)
m3dti_t *M3DExporter::AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx)
{
tmap = (m3dti_t*)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t));
memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t));
*idx = *numtmap;
(*numtmap)++;
return tmap;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// recursive node walker // recursive node walker
void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m)
@ -221,25 +248,23 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m)
if(mesh->HasVertexColors(0)) if(mesh->HasVertexColors(0))
vertex.color = mkColor(&mesh->mColors[0][l]); vertex.color = mkColor(&mesh->mColors[0][l]);
// save the vertex to the output // save the vertex to the output
m3d->vertex = _m3d_addvrtx(m3d->vertex, &m3d->numvertex, m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex,
&vertex, &idx); &vertex, &idx);
m3d->face[n].vertex[k] = (M3D_INDEX)idx; m3d->face[n].vertex[k] = (M3D_INDEX)idx;
// do we have texture coordinates? // do we have texture coordinates?
if(mesh->HasTextureCoords(0)) { if(mesh->HasTextureCoords(0)) {
ti.u = mesh->mTextureCoords[0][l].x; ti.u = mesh->mTextureCoords[0][l].x;
ti.v = mesh->mTextureCoords[0][l].y; ti.v = mesh->mTextureCoords[0][l].y;
m3d->tmap = _m3d_addtmap(m3d->tmap, &m3d->numtmap, &ti, m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx);
&idx);
m3d->face[n].texcoord[k] = (M3D_INDEX)idx; m3d->face[n].texcoord[k] = (M3D_INDEX)idx;
} }
// do we have normal vectors? // do we have normal vectors?
if(mesh->HasNormals()) { if(mesh->HasNormals()) {
vertex.color = 0;
vertex.x = mesh->mNormals[l].x; vertex.x = mesh->mNormals[l].x;
vertex.y = mesh->mNormals[l].y; vertex.y = mesh->mNormals[l].y;
vertex.z = mesh->mNormals[l].z; vertex.z = mesh->mNormals[l].z;
m3d->vertex = _m3d_addnorm(m3d->vertex, &m3d->numvertex, vertex.color = 0;
&vertex, &idx); m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx);
m3d->face[n].normal[k] = (M3D_INDEX)idx; m3d->face[n].normal[k] = (M3D_INDEX)idx;
} }
} }

View File

@ -87,6 +87,8 @@ namespace Assimp
// helper to do the recursive walking // helper to do the recursive walking
void NodeWalk(const aiNode* pNode, aiMatrix4x4 m); void NodeWalk(const aiNode* pNode, aiMatrix4x4 m);
m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx);
m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx);
uint32_t mkColor(aiColor4D* c); uint32_t mkColor(aiColor4D* c);
M3D_INDEX addMaterial(const aiMaterial *mat); M3D_INDEX addMaterial(const aiMaterial *mat);
void addProp(m3dm_t *m, uint8_t type, uint32_t value); void addProp(m3dm_t *m, uint8_t type, uint32_t value);

View File

@ -44,6 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define M3D_IMPLEMENTATION #define M3D_IMPLEMENTATION
#define M3D_ASCII #define M3D_ASCII
#define M3D_NONORMALS /* leave the post-processing to Assimp */
#define M3D_NOWEIGHTS
#define M3D_NOANIMATION
#include <assimp/IOStreamBuffer.h> #include <assimp/IOStreamBuffer.h>
#include <memory> #include <memory>
@ -104,16 +107,21 @@ extern "C" {
std::string file(fn); std::string file(fn);
std::unique_ptr<Assimp::IOStream> pStream( std::unique_ptr<Assimp::IOStream> pStream(
(reinterpret_cast<Assimp::IOSystem*>(m3dimporter_pIOHandler))->Open( file, "rb")); (reinterpret_cast<Assimp::IOSystem*>(m3dimporter_pIOHandler))->Open( file, "rb"));
size_t fileSize = pStream->FileSize(); size_t fileSize = 0;
// should be allocated with malloc(), because the library will call free() to deallocate unsigned char *data = NULL;
unsigned char *data = (unsigned char*)malloc(fileSize); // sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess)
if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) { if(pStream) {
fileSize = pStream->FileSize();
// should be allocated with malloc(), because the library will call free() to deallocate
data = (unsigned char*)malloc(fileSize);
if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) {
pStream.reset();
*size = 0;
// don't throw a deadly exception, it's not fatal if we can't read an external asset
return nullptr;
}
pStream.reset(); pStream.reset();
*size = 0;
// don't throw a deadly exception, it's not fatal if we can't read an external asset
return nullptr;
} }
pStream.reset();
*size = (int)fileSize; *size = (int)fileSize;
return data; return data;
} }
@ -307,7 +315,7 @@ void M3DImporter::importMaterials()
m->prop[j].value.textureid < m3d->numtexture && m->prop[j].value.textureid < m3d->numtexture &&
m3d->texture[m->prop[j].value.textureid].name) { m3d->texture[m->prop[j].value.textureid].name) {
name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png"));
mat->AddProperty(&name, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
n = 0; n = 0;
mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
} }
@ -321,6 +329,7 @@ void M3DImporter::importMaterials()
void M3DImporter::importTextures() void M3DImporter::importTextures()
{ {
unsigned int i; unsigned int i;
const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" };
m3dtx_t *t; m3dtx_t *t;
ai_assert(mScene != nullptr); ai_assert(mScene != nullptr);
@ -334,14 +343,29 @@ void M3DImporter::importTextures()
mScene->mTextures = new aiTexture*[m3d->numtexture]; mScene->mTextures = new aiTexture*[m3d->numtexture];
for(i = 0; i < m3d->numtexture; i++) { for(i = 0; i < m3d->numtexture; i++) {
unsigned int j, k;
t = &m3d->texture[i]; t = &m3d->texture[i];
if(!t->w || !t->h || !t->f || !t->d) continue;
aiTexture *tx = new aiTexture; aiTexture *tx = new aiTexture;
strcpy(tx->achFormatHint, "rgba8888"); strcpy(tx->achFormatHint, formatHint[t->f - 1]);
tx->mFilename = aiString(std::string(t->name) + ".png"); tx->mFilename = aiString(std::string(t->name) + ".png");
tx->mWidth = t->w; tx->mWidth = t->w;
tx->mHeight = t->h; tx->mHeight = t->h;
tx->pcData = new aiTexel[ tx->mWidth*tx->mHeight ]; tx->pcData = new aiTexel[ tx->mWidth*tx->mHeight ];
memcpy(tx->pcData, t->d, tx->mWidth*tx->mHeight*4); 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; mScene->mTextures[i] = tx;
} }
} }
@ -372,9 +396,14 @@ void M3DImporter::importMeshes()
// we must switch mesh if material changes // we must switch mesh if material changes
if(lastMat != m3d->face[i].materialid) { if(lastMat != m3d->face[i].materialid) {
lastMat = m3d->face[i].materialid; lastMat = m3d->face[i].materialid;
if(pMesh && vertices->size() && faces->size()) { if(pMesh && vertices && vertices->size() && faces && faces->size()) {
populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids);
meshes->push_back(pMesh); meshes->push_back(pMesh);
delete faces;
delete vertices;
delete normals;
delete texcoords;
delete colors;
delete vertexids; // this is not stored in pMesh, just to collect bone vertices delete vertexids; // this is not stored in pMesh, just to collect bone vertices
} }
pMesh = new aiMesh; pMesh = new aiMesh;
@ -574,15 +603,15 @@ void M3DImporter::convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int o
m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0;
m->a1 = m->b2 = m->c3 = -1.0; m->a1 = m->b2 = m->c3 = -1.0;
} else { } else {
m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -1e-7 && m->a1 < 1e-7) m->a1 = 0.0; m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0;
m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -1e-7 && m->a2 < 1e-7) m->a2 = 0.0; m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0;
m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -1e-7 && m->a3 < 1e-7) m->a3 = 0.0; m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0;
m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -1e-7 && m->b1 < 1e-7) m->b1 = 0.0; m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0;
m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -1e-7 && m->b2 < 1e-7) m->b2 = 0.0; m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0;
m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -1e-7 && m->b3 < 1e-7) m->b3 = 0.0; m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0;
m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -1e-7 && m->c1 < 1e-7) m->c1 = 0.0; m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0;
m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -1e-7 && m->c2 < 1e-7) m->c2 = 0.0; m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0;
m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -1e-7 && m->c3 < 1e-7) m->c3 = 0.0; m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0;
} }
/* set translation */ /* set translation */

View File

@ -75,7 +75,7 @@ static const aiMatProp aiProps[] = {
{ AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */ { AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */
{ NULL, 0, 0 }, /* m3dp_Ps */ { NULL, 0, 0 }, /* m3dp_Ps */
{ AI_MATKEY_REFRACTI }, /* m3dp_Ni */ { AI_MATKEY_REFRACTI }, /* m3dp_Ni */
{ NULL, 0, 0 }, { NULL, 0, 0 }, /* m3dp_Nt */
{ NULL, 0, 0 }, { NULL, 0, 0 },
{ NULL, 0, 0 }, { NULL, 0, 0 },
{ NULL, 0, 0 } { NULL, 0, 0 }
@ -97,7 +97,7 @@ static const aiMatProp aiTxProps[] = {
{ AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */
{ NULL, 0, 0 }, /* m3dp_map_Ps */ { NULL, 0, 0 }, /* m3dp_map_Ps */
{ AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ni */ { AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ni */
{ NULL, 0, 0 }, { NULL, 0, 0 }, /* m3dp_map_Nt */
{ NULL, 0, 0 }, { NULL, 0, 0 },
{ NULL, 0, 0 }, { NULL, 0, 0 },
{ NULL, 0, 0 } { NULL, 0, 0 }

File diff suppressed because it is too large Load Diff

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);
} }
@ -471,12 +471,12 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
aiPropertyTypeInfo pType aiPropertyTypeInfo pType
) )
{ {
ai_assert( pInput != NULL ); ai_assert( pInput != nullptr );
ai_assert( pKey != NULL ); ai_assert(pKey != nullptr );
ai_assert( 0 != pSizeInBytes ); ai_assert( 0 != pSizeInBytes );
if ( 0 == pSizeInBytes ) { if ( 0 == pSizeInBytes ) {
return AI_FAILURE;
} }
// first search the list whether there is already an entry with this key // first search the list whether there is already an entry with this key

View File

@ -603,15 +603,18 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
ReportError("%s #%i is set, but there are only %i %s textures", ReportError("%s #%i is set, but there are only %i %s textures",
szType,iIndex,iNumIndices,szType); szType,iIndex,iNumIndices,szType);
} }
if (!iNumIndices)return; if (!iNumIndices) {
return;
}
std::vector<aiTextureMapping> mappings(iNumIndices); std::vector<aiTextureMapping> mappings(iNumIndices);
// Now check whether all UV indices are valid ... // Now check whether all UV indices are valid ...
bool bNoSpecified = true; bool bNoSpecified = true;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) {
{
aiMaterialProperty* prop = pMaterial->mProperties[i]; aiMaterialProperty* prop = pMaterial->mProperties[i];
if (prop->mSemantic != type)continue; if (prop->mSemantic != type) {
continue;
}
if ((int)prop->mIndex >= iNumIndices) if ((int)prop->mIndex >= iNumIndices)
{ {
@ -634,7 +637,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
ReportError("Material property %s%i is expected to be 5 floats large (size is %i)", ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
prop->mKey.data,prop->mIndex, prop->mDataLength); prop->mKey.data,prop->mIndex, prop->mDataLength);
} }
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData); //mappings[prop->mIndex] = ((aiUVTransform*)prop->mData);
} }
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) { else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)

View File

@ -1427,9 +1427,6 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
} }
} }
#define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
CHECK_EXT(KHR_binary_glTF); CHECK_EXT(KHR_binary_glTF);
CHECK_EXT(KHR_materials_common); CHECK_EXT(KHR_materials_common);

View File

@ -188,7 +188,7 @@ namespace glTFCommon {
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
inline inline
size_t DecodeBase64(const char* in, uint8_t*& out) { size_t DecodeBase64(const char* in, uint8_t*& out) {
return DecodeBase64(in, strlen(in), out); return DecodeBase64(in, strlen(in), out);
} }
@ -221,25 +221,22 @@ namespace glTFCommon {
}; };
inline inline
char EncodeCharBase64(uint8_t b) { char EncodeCharBase64(uint8_t b) {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)]; return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
} }
inline inline
uint8_t DecodeCharBase64(char c) { uint8_t DecodeCharBase64(char c) {
return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs? return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
/*if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return 64; // '-' */
} }
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out); void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
} } // namespace Util
#define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
} }

View File

@ -685,6 +685,13 @@ namespace glTF2
Ref<Texture> texture; Ref<Texture> texture;
unsigned int index; unsigned int index;
unsigned int texCoord = 0; unsigned int texCoord = 0;
bool textureTransformSupported = false;
struct TextureTransformExt {
float offset[2];
float rotation;
float scale[2];
} TextureTransformExt_t;
}; };
struct NormalTextureInfo : TextureInfo struct NormalTextureInfo : TextureInfo
@ -1024,9 +1031,15 @@ namespace glTF2
bool KHR_materials_pbrSpecularGlossiness; bool KHR_materials_pbrSpecularGlossiness;
bool KHR_materials_unlit; bool KHR_materials_unlit;
bool KHR_lights_punctual; bool KHR_lights_punctual;
bool KHR_texture_transform;
} extensionsUsed; } extensionsUsed;
//! Keeps info about the required extensions
struct RequiredExtensions
{
bool KHR_draco_mesh_compression;
} extensionsRequired;
AssetMetadata asset; AssetMetadata asset;
@ -1069,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
@ -1087,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

@ -800,8 +800,34 @@ inline void Texture::Read(Value& obj, Asset& r)
} }
namespace { namespace {
inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) {
{ if (r.extensionsUsed.KHR_texture_transform) {
if (Value *extensions = FindObject(*prop, "extensions")) {
out.textureTransformSupported = true;
if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) {
if (Value *array = FindArray(*pKHR_texture_transform, "offset")) {
out.TextureTransformExt_t.offset[0] = (*array)[0].GetFloat();
out.TextureTransformExt_t.offset[1] = (*array)[1].GetFloat();
} else {
out.TextureTransformExt_t.offset[0] = 0;
out.TextureTransformExt_t.offset[1] = 0;
}
if (!ReadMember(*pKHR_texture_transform, "rotation", out.TextureTransformExt_t.rotation)) {
out.TextureTransformExt_t.rotation = 0;
}
if (Value *array = FindArray(*pKHR_texture_transform, "scale")) {
out.TextureTransformExt_t.scale[0] = (*array)[0].GetFloat();
out.TextureTransformExt_t.scale[1] = (*array)[1].GetFloat();
} else {
out.TextureTransformExt_t.scale[0] = 1;
out.TextureTransformExt_t.scale[1] = 1;
}
}
}
}
if (Value* index = FindUInt(*prop, "index")) { if (Value* index = FindUInt(*prop, "index")) {
out.texture = r.textures.Retrieve(index->GetUint()); out.texture = r.textures.Retrieve(index->GetUint());
} }
@ -877,6 +903,9 @@ inline void Material::Read(Value& material, Asset& r)
} }
} }
if (r.extensionsUsed.KHR_texture_transform) {
}
unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit"); unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit");
} }
} }
@ -1403,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) {
@ -1449,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)
{ {
@ -1463,12 +1521,10 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
} }
} }
#define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
CHECK_EXT(KHR_materials_pbrSpecularGlossiness); CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
CHECK_EXT(KHR_materials_unlit); CHECK_EXT(KHR_materials_unlit);
CHECK_EXT(KHR_lights_punctual); CHECK_EXT(KHR_lights_punctual);
CHECK_EXT(KHR_texture_transform);
#undef CHECK_EXT #undef CHECK_EXT
} }

View File

@ -74,6 +74,7 @@ namespace glTF2
struct Texture; struct Texture;
// Vec/matrix types, as raw float arrays // Vec/matrix types, as raw float arrays
typedef float (vec2)[2];
typedef float (vec3)[3]; typedef float (vec3)[3];
typedef float (vec4)[4]; typedef float (vec4)[4];
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/build/ /build/
/test/build/ /test/build/
/xcodeproj/ /xcodeproj/
.vscode/
# Object files # Object files
*.o *.o
@ -54,3 +55,4 @@ zip.dir/
test/test.exe.vcxproj.filters test/test.exe.vcxproj.filters
test/test.exe.vcxproj test/test.exe.vcxproj
test/test.exe.dir/ test/test.exe.dir/

View File

@ -1,10 +1,14 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 3.0)
project(zip)
enable_language(C) project(zip
LANGUAGES C
VERSION "0.1.15")
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
if (MSVC) if (MSVC)
# Use secure functions by defaualt and suppress warnings about "deprecated" functions # Use secure functions by default and suppress warnings about "deprecated" functions
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
@ -12,28 +16,80 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
"${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
"${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
if(ENABLE_COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
endif()
endif (MSVC) endif (MSVC)
# zip # zip
set(SRC src/miniz.h src/zip.h src/zip.c) set(SRC src/miniz.h src/zip.h src/zip.c)
add_library(${PROJECT_NAME} ${SRC}) add_library(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} INTERFACE src) target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>
)
# test # test
if (NOT CMAKE_DISABLE_TESTING) if (NOT CMAKE_DISABLE_TESTING)
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
find_package(Sanitizers) find_package(Sanitizers)
add_sanitizers(${PROJECT_NAME} test.exe) add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out})
add_sanitizers(${PROJECT_NAME} test_miniz.exe)
endif() endif()
####
# Installation (https://github.com/forexample/package-example) {
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(INCLUDE_INSTALL_DIR "include")
set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
# Configuration
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NAMESPACE "${PROJECT_NAME}::")
# Include module with fuction 'write_basic_package_version_file'
include(CMakePackageConfigHelpers)
# Note: PROJECT_VERSION is used as a VERSION
write_basic_package_version_file(
"${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion
)
# Use variables:
# * TARGETS_EXPORT_NAME
# * PROJECT_NAME
configure_package_config_file(
"cmake/Config.cmake.in"
"${PROJECT_CONFIG}"
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
)
# }
install(TARGETS ${PROJECT_NAME} install(TARGETS ${PROJECT_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
COMPONENT library) INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR}
install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION include) )
install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip)
# uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake) # uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake)
if(NOT TARGET uninstall) if(NOT TARGET uninstall)
@ -45,3 +101,12 @@ if(NOT TARGET uninstall)
add_custom_target(uninstall add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake)
endif() endif()
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif()

View File

@ -71,7 +71,7 @@ int arg = 2;
zip_extract("foo.zip", "/tmp", on_extract_entry, &arg); zip_extract("foo.zip", "/tmp", on_extract_entry, &arg);
``` ```
* Extract a zip entry into memory. * Extract a zip entry into memory.
```c ```c
void *buf = NULL; void *buf = NULL;
size_t bufsize; size_t bufsize;
@ -89,7 +89,7 @@ zip_close(zip);
free(buf); free(buf);
``` ```
* Extract a zip entry into memory (no internal allocation). * Extract a zip entry into memory (no internal allocation).
```c ```c
unsigned char *buf; unsigned char *buf;
size_t bufsize; size_t bufsize;
@ -110,7 +110,7 @@ zip_close(zip);
free(buf); free(buf);
``` ```
* Extract a zip entry into memory using callback. * Extract a zip entry into memory using callback.
```c ```c
struct buffer_t { struct buffer_t {
char *data; char *data;
@ -144,7 +144,7 @@ free(buf.data);
``` ```
* Extract a zip entry into a file. * Extract a zip entry into a file.
```c ```c
struct zip_t *zip = zip_open("foo.zip", 0, 'r'); struct zip_t *zip = zip_open("foo.zip", 0, 'r');
{ {
@ -157,7 +157,7 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
zip_close(zip); zip_close(zip);
``` ```
* List of all zip entries * List of all zip entries
```c ```c
struct zip_t *zip = zip_open("foo.zip", 0, 'r'); struct zip_t *zip = zip_open("foo.zip", 0, 'r');
int i, n = zip_total_entries(zip); int i, n = zip_total_entries(zip);
@ -174,7 +174,7 @@ for (i = 0; i < n; ++i) {
zip_close(zip); zip_close(zip);
``` ```
## Bindings # Bindings
Compile zip library as a dynamic library. Compile zip library as a dynamic library.
```shell ```shell
$ mkdir build $ mkdir build

View File

@ -1,4 +1,4 @@
version: zip-0.1.9.{build} version: zip-0.1.15.{build}
build_script: build_script:
- cmd: >- - cmd: >-
cd c:\projects\zip cd c:\projects\zip

View File

@ -221,6 +221,7 @@
#ifndef MINIZ_HEADER_INCLUDED #ifndef MINIZ_HEADER_INCLUDED
#define MINIZ_HEADER_INCLUDED #define MINIZ_HEADER_INCLUDED
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
// Defines to completely disable specific portions of miniz.c: // Defines to completely disable specific portions of miniz.c:
@ -284,7 +285,8 @@
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
#if MINIZ_X86_OR_X64_CPU #if MINIZ_X86_OR_X64_CPU
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
* integer loads and stores from unaligned addresses. */
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
#define MINIZ_UNALIGNED_USE_MEMCPY #define MINIZ_UNALIGNED_USE_MEMCPY
#else #else
@ -354,6 +356,44 @@ enum {
MZ_FIXED = 4 MZ_FIXED = 4
}; };
/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or
* modify this enum. */
typedef enum {
MZ_ZIP_NO_ERROR = 0,
MZ_ZIP_UNDEFINED_ERROR,
MZ_ZIP_TOO_MANY_FILES,
MZ_ZIP_FILE_TOO_LARGE,
MZ_ZIP_UNSUPPORTED_METHOD,
MZ_ZIP_UNSUPPORTED_ENCRYPTION,
MZ_ZIP_UNSUPPORTED_FEATURE,
MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,
MZ_ZIP_NOT_AN_ARCHIVE,
MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,
MZ_ZIP_UNSUPPORTED_MULTIDISK,
MZ_ZIP_DECOMPRESSION_FAILED,
MZ_ZIP_COMPRESSION_FAILED,
MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,
MZ_ZIP_CRC_CHECK_FAILED,
MZ_ZIP_UNSUPPORTED_CDIR_SIZE,
MZ_ZIP_ALLOC_FAILED,
MZ_ZIP_FILE_OPEN_FAILED,
MZ_ZIP_FILE_CREATE_FAILED,
MZ_ZIP_FILE_WRITE_FAILED,
MZ_ZIP_FILE_READ_FAILED,
MZ_ZIP_FILE_CLOSE_FAILED,
MZ_ZIP_FILE_SEEK_FAILED,
MZ_ZIP_FILE_STAT_FAILED,
MZ_ZIP_INVALID_PARAMETER,
MZ_ZIP_INVALID_FILENAME,
MZ_ZIP_BUF_TOO_SMALL,
MZ_ZIP_INTERNAL_ERROR,
MZ_ZIP_FILE_NOT_FOUND,
MZ_ZIP_ARCHIVE_TOO_LARGE,
MZ_ZIP_VALIDATION_FAILED,
MZ_ZIP_WRITE_CALLBACK_FAILED,
MZ_ZIP_TOTAL_ERRORS
} mz_zip_error;
// Method // Method
#define MZ_DEFLATED 8 #define MZ_DEFLATED 8
@ -696,6 +736,7 @@ typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
void *pBuf, size_t n); void *pBuf, size_t n);
typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
const void *pBuf, size_t n); const void *pBuf, size_t n);
typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
struct mz_zip_internal_state_tag; struct mz_zip_internal_state_tag;
typedef struct mz_zip_internal_state_tag mz_zip_internal_state; typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
@ -707,13 +748,27 @@ typedef enum {
MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
} mz_zip_mode; } mz_zip_mode;
typedef struct mz_zip_archive_tag { typedef enum {
MZ_ZIP_TYPE_INVALID = 0,
MZ_ZIP_TYPE_USER,
MZ_ZIP_TYPE_MEMORY,
MZ_ZIP_TYPE_HEAP,
MZ_ZIP_TYPE_FILE,
MZ_ZIP_TYPE_CFILE,
MZ_ZIP_TOTAL_TYPES
} mz_zip_type;
typedef struct {
mz_uint64 m_archive_size; mz_uint64 m_archive_size;
mz_uint64 m_central_directory_file_ofs; mz_uint64 m_central_directory_file_ofs;
mz_uint m_total_files;
mz_zip_mode m_zip_mode;
mz_uint m_file_offset_alignment; /* We only support up to UINT32_MAX files in zip64 mode. */
mz_uint32 m_total_files;
mz_zip_mode m_zip_mode;
mz_zip_type m_zip_type;
mz_zip_error m_last_error;
mz_uint64 m_file_offset_alignment;
mz_alloc_func m_pAlloc; mz_alloc_func m_pAlloc;
mz_free_func m_pFree; mz_free_func m_pFree;
@ -722,6 +777,7 @@ typedef struct mz_zip_archive_tag {
mz_file_read_func m_pRead; mz_file_read_func m_pRead;
mz_file_write_func m_pWrite; mz_file_write_func m_pWrite;
mz_file_needs_keepalive m_pNeeds_keepalive;
void *m_pIO_opaque; void *m_pIO_opaque;
mz_zip_internal_state *m_pState; mz_zip_internal_state *m_pState;
@ -1263,6 +1319,9 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
int strategy); int strategy);
#endif // #ifndef MINIZ_NO_ZLIB_APIS #endif // #ifndef MINIZ_NO_ZLIB_APIS
#define MZ_UINT16_MAX (0xFFFFU)
#define MZ_UINT32_MAX (0xFFFFFFFFU)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -1311,6 +1370,11 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
#endif #endif
#define MZ_READ_LE64(p) \
(((mz_uint64)MZ_READ_LE32(p)) | \
(((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \
<< 32U))
#ifdef _MSC_VER #ifdef _MSC_VER
#define MZ_FORCEINLINE __forceinline #define MZ_FORCEINLINE __forceinline
#elif defined(__GNUC__) #elif defined(__GNUC__)
@ -4160,6 +4224,17 @@ enum {
MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
/* ZIP64 archive identifier and record sizes */
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
// Central directory header record offsets // Central directory header record offsets
MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_SIG_OFS = 0,
MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
@ -4199,6 +4274,31 @@ enum {
MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
/* ZIP64 End of central directory locator offsets */
MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
/* ZIP64 End of central directory header offsets */
MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
}; };
typedef struct { typedef struct {
@ -4211,7 +4311,24 @@ struct mz_zip_internal_state_tag {
mz_zip_array m_central_dir; mz_zip_array m_central_dir;
mz_zip_array m_central_dir_offsets; mz_zip_array m_central_dir_offsets;
mz_zip_array m_sorted_central_dir_offsets; mz_zip_array m_sorted_central_dir_offsets;
/* The flags passed in when the archive is initially opened. */
uint32_t m_init_flags;
/* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
*/
mz_bool m_zip64;
/* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
* will also be slammed to true too, even if we didn't find a zip64 end of
* central dir header, etc.) */
mz_bool m_zip64_has_extended_info_fields;
/* These fields are used by the file, FILE, memory, and memory/heap read/write
* helpers. */
MZ_FILE *m_pFile; MZ_FILE *m_pFile;
mz_uint64 m_file_archive_start_ofs;
void *m_pMem; void *m_pMem;
size_t m_mem_size; size_t m_mem_size;
size_t m_mem_capacity; size_t m_mem_capacity;
@ -4363,6 +4480,13 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
#endif /* #ifndef MINIZ_NO_STDIO */ #endif /* #ifndef MINIZ_NO_STDIO */
#endif /* #ifndef MINIZ_NO_TIME */ #endif /* #ifndef MINIZ_NO_TIME */
static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
mz_zip_error err_num) {
if (pZip)
pZip->m_last_error = err_num;
return MZ_FALSE;
}
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
mz_uint32 flags) { mz_uint32 flags) {
(void)flags; (void)flags;
@ -4480,127 +4604,346 @@ mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
} }
} }
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
mz_uint32 flags) { mz_uint32 record_sig,
mz_uint cdir_size, num_this_disk, cdir_disk_index; mz_uint32 record_size,
mz_uint64 cdir_ofs; mz_int64 *pOfs) {
mz_int64 cur_file_ofs; mz_int64 cur_file_ofs;
const mz_uint8 *p;
mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
mz_uint8 *pBuf = (mz_uint8 *)buf_u32; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
mz_bool sort_central_dir =
((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); /* Basic sanity checks - reject files which are too small */
// Basic sanity checks - reject files which are too small, and check the first if (pZip->m_archive_size < record_size)
// 4 bytes of the file to make sure a local header is there.
if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
return MZ_FALSE; return MZ_FALSE;
// Find the end of central directory record by scanning the file from the end
// towards the beginning. /* Find the record by scanning the file from the end towards the beginning. */
cur_file_ofs = cur_file_ofs =
MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
for (;;) { for (;;) {
int i, int i,
n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
return MZ_FALSE; return MZ_FALSE;
for (i = n - 4; i >= 0; --i)
if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) for (i = n - 4; i >= 0; --i) {
break; mz_uint s = MZ_READ_LE32(pBuf + i);
if (s == record_sig) {
if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
break;
}
}
if (i >= 0) { if (i >= 0) {
cur_file_ofs += i; cur_file_ofs += i;
break; break;
} }
/* Give up if we've searched the entire file, or we've gone back "too far"
* (~64kb) */
if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
(0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) (MZ_UINT16_MAX + record_size)))
return MZ_FALSE; return MZ_FALSE;
cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
} }
// Read and verify the end of central directory record.
*pOfs = cur_file_ofs;
return MZ_TRUE;
}
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
mz_uint flags) {
mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
cdir_disk_index = 0;
mz_uint64 cdir_ofs = 0;
mz_int64 cur_file_ofs = 0;
const mz_uint8 *p;
mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
mz_bool sort_central_dir =
((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
mz_uint32 zip64_end_of_central_dir_locator_u32
[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
mz_uint32 zip64_end_of_central_dir_header_u32
[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
mz_uint8 *pZip64_end_of_central_dir =
(mz_uint8 *)zip64_end_of_central_dir_header_u32;
mz_uint64 zip64_end_of_central_dir_ofs = 0;
/* Basic sanity checks - reject files which are too small, and check the first
* 4 bytes of the file to make sure a local header is there. */
if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
if (!mz_zip_reader_locate_header_sig(
pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
/* Read and verify the end of central directory record. */
if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
((pZip->m_total_files =
MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) !=
MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
return MZ_FALSE;
if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
if (pZip->m_pRead(pZip->m_pIO_opaque,
cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
pZip64_locator,
MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
zip64_end_of_central_dir_ofs = MZ_READ_LE64(
pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
if (zip64_end_of_central_dir_ofs >
(pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
pZip64_end_of_central_dir,
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
pZip->m_pState->m_zip64 = MZ_TRUE;
}
}
}
}
}
pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
cdir_entries_on_this_disk =
MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
if (pZip->m_pState->m_zip64) {
mz_uint32 zip64_total_num_of_disks =
MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
mz_uint64 zip64_size_of_central_directory =
MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
if (zip64_size_of_end_of_central_dir_record <
(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
if (zip64_total_num_of_disks != 1U)
return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
/* Check for miniz's practical limits */
if (zip64_cdir_total_entries > MZ_UINT32_MAX)
return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
cdir_entries_on_this_disk =
(mz_uint32)zip64_cdir_total_entries_on_this_disk;
/* Check for miniz's current practical limits (sorry, this should be enough
* for millions of files) */
if (zip64_size_of_central_directory > MZ_UINT32_MAX)
return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
cdir_size = (mz_uint32)zip64_size_of_central_directory;
num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
cdir_ofs =
MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
}
if (pZip->m_total_files != cdir_entries_on_this_disk)
return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
if (((num_this_disk | cdir_disk_index) != 0) && if (((num_this_disk | cdir_disk_index) != 0) &&
((num_this_disk != 1) || (cdir_disk_index != 1))) ((num_this_disk != 1) || (cdir_disk_index != 1)))
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
return MZ_FALSE;
cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
pZip->m_central_directory_file_ofs = cdir_ofs; pZip->m_central_directory_file_ofs = cdir_ofs;
if (pZip->m_total_files) { if (pZip->m_total_files) {
mz_uint i, n; mz_uint i, n;
/* Read the entire central directory into a heap block, and allocate another
// Read the entire central directory into a heap block, and allocate another * heap block to hold the unsorted central dir file record offsets, and
// heap block to hold the unsorted central dir file record offsets, and * possibly another to hold the sorted indices. */
// another to hold the sorted indices.
if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
MZ_FALSE)) || MZ_FALSE)) ||
(!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
pZip->m_total_files, MZ_FALSE))) pZip->m_total_files, MZ_FALSE)))
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
if (sort_central_dir) { if (sort_central_dir) {
if (!mz_zip_array_resize(pZip, if (!mz_zip_array_resize(pZip,
&pZip->m_pState->m_sorted_central_dir_offsets, &pZip->m_pState->m_sorted_central_dir_offsets,
pZip->m_total_files, MZ_FALSE)) pZip->m_total_files, MZ_FALSE))
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
} }
if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
pZip->m_pState->m_central_dir.m_p, pZip->m_pState->m_central_dir.m_p,
cdir_size) != cdir_size) cdir_size) != cdir_size)
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
// Now create an index into the central directory file records, do some /* Now create an index into the central directory file records, do some
// basic sanity checking on each record, and check for zip64 entries (which * basic sanity checking on each record */
// are not yet supported).
p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
mz_uint total_header_size, comp_size, decomp_size, disk_index; mz_uint total_header_size, disk_index, bit_flags, filename_size,
ext_data_size;
mz_uint64 comp_size, decomp_size, local_header_ofs;
if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
(MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
i) = i) =
(mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
if (sort_central_dir) if (sort_central_dir)
MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
mz_uint32, i) = i; mz_uint32, i) = i;
comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
(decomp_size != comp_size)) || filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
(decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
(comp_size == 0xFFFFFFFF))
return MZ_FALSE; if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
(ext_data_size) &&
(MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
MZ_UINT32_MAX)) {
/* Attempt to find zip64 extended information field in the entry's extra
* data */
mz_uint32 extra_size_remaining = ext_data_size;
if (extra_size_remaining) {
const mz_uint8 *pExtra_data;
void *buf = NULL;
if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
n) {
buf = MZ_MALLOC(ext_data_size);
if (buf == NULL)
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
if (pZip->m_pRead(pZip->m_pIO_opaque,
cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
filename_size,
buf, ext_data_size) != ext_data_size) {
MZ_FREE(buf);
return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
}
pExtra_data = (mz_uint8 *)buf;
} else {
pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
}
do {
mz_uint32 field_id;
mz_uint32 field_data_size;
if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
MZ_FREE(buf);
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
}
field_id = MZ_READ_LE16(pExtra_data);
field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
if ((field_data_size + sizeof(mz_uint16) * 2) >
extra_size_remaining) {
MZ_FREE(buf);
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
}
if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
/* Ok, the archive didn't have any zip64 headers but it uses a
* zip64 extended information field so mark it as zip64 anyway
* (this can occur with infozip's zip util when it reads
* compresses files from stdin). */
pZip->m_pState->m_zip64 = MZ_TRUE;
pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
break;
}
pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
extra_size_remaining =
extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
} while (extra_size_remaining);
MZ_FREE(buf);
}
}
/* I've seen archives that aren't marked as zip64 that uses zip64 ext
* data, argh */
if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
(decomp_size != comp_size)) ||
(decomp_size && !comp_size))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
}
disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
if ((disk_index != num_this_disk) && (disk_index != 1)) if ((disk_index == MZ_UINT16_MAX) ||
return MZ_FALSE; ((disk_index != num_this_disk) && (disk_index != 1)))
if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
return MZ_FALSE; if (comp_size != MZ_UINT32_MAX) {
if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
}
bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
n) n)
return MZ_FALSE; return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
n -= total_header_size; n -= total_header_size;
p += total_header_size; p += total_header_size;
} }

View File

@ -24,7 +24,6 @@
((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \
(P)[1] == ':') (P)[1] == ':')
#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0) #define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0)
#define ISSLASH(C) ((C) == '/' || (C) == '\\')
#else #else
@ -48,7 +47,7 @@ int symlink(const char *target, const char *linkpath); // needed on Linux
#endif #endif
#ifndef ISSLASH #ifndef ISSLASH
#define ISSLASH(C) ((C) == '/') #define ISSLASH(C) ((C) == '/' || (C) == '\\')
#endif #endif
#define CLEANUP(ptr) \ #define CLEANUP(ptr) \
@ -78,26 +77,34 @@ static const char *base_name(const char *name) {
return base; return base;
} }
static int mkpath(const char *path) { static int mkpath(char *path) {
char const *p; char *p;
char npath[MAX_PATH + 1]; char npath[MAX_PATH + 1];
int len = 0; int len = 0;
int has_device = HAS_DEVICE(path); int has_device = HAS_DEVICE(path);
memset(npath, 0, MAX_PATH + 1); memset(npath, 0, MAX_PATH + 1);
if (has_device) {
#ifdef _WIN32 // only on windows
// only on windows fix the path npath[0] = path[0];
npath[0] = path[0]; npath[1] = path[1];
npath[1] = path[1]; len = 2;
len = 2; }
#endif // _WIN32
for (p = path + len; *p && len < MAX_PATH; p++) { for (p = path + len; *p && len < MAX_PATH; p++) {
if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) { if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) {
if (MKDIR(npath) == -1) #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
if (errno != EEXIST) defined(__MINGW32__)
#else
if ('\\' == *p) {
*p = '/';
}
#endif
if (MKDIR(npath) == -1) {
if (errno != EEXIST) {
return -1; return -1;
}
}
} }
npath[len++] = *p; npath[len++] = *p;
} }
@ -279,7 +286,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.header_offset = zip->archive.m_archive_size; zip->entry.header_offset = zip->archive.m_archive_size;
memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8)); memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8));
zip->entry.method = 0; zip->entry.method = 0;
// UNIX or APPLE
#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19
// regular file with rw-r--r-- persmissions
zip->entry.external_attr = (mz_uint32)(0100644) << 16;
#else
zip->entry.external_attr = 0; zip->entry.external_attr = 0;
#endif
num_alignment_padding_bytes = num_alignment_padding_bytes =
mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
@ -660,7 +674,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
} }
if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index, if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index,
buf, bufsize, 0, NULL, 0)) { buf, bufsize, 0, NULL, 0)) {
return -1; return -1;
} }
@ -670,10 +684,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
int zip_entry_fread(struct zip_t *zip, const char *filename) { int zip_entry_fread(struct zip_t *zip, const char *filename) {
mz_zip_archive *pzip = NULL; mz_zip_archive *pzip = NULL;
mz_uint idx; mz_uint idx;
#if defined(_MSC_VER)
#else
mz_uint32 xattr = 0; mz_uint32 xattr = 0;
#endif
mz_zip_archive_file_stat info; mz_zip_archive_file_stat info;
if (!zip) { if (!zip) {
@ -875,12 +886,19 @@ int zip_extract(const char *zipname, const char *dir,
goto out; goto out;
} }
if ((((info.m_version_made_by >> 8) == 3) || ((info.m_version_made_by >> 8) == 19)) // if zip is produced on Unix or macOS (3 and 19 from section 4.4.2.2 of zip standard) if ((((info.m_version_made_by >> 8) == 3) ||
&& info.m_external_attr & (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 is directory) ((info.m_version_made_by >> 8) ==
19)) // if zip is produced on Unix or macOS (3 and 19 from
// section 4.4.2.2 of zip standard)
&& info.m_external_attr &
(0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40
// is directory)
#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
defined(__MINGW32__) defined(__MINGW32__)
#else #else
if (info.m_uncomp_size > MAX_PATH || !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, MAX_PATH, 0, NULL, 0)) { if (info.m_uncomp_size > MAX_PATH ||
!mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to,
MAX_PATH, 0, NULL, 0)) {
goto out; goto out;
} }
symlink_to[info.m_uncomp_size] = '\0'; symlink_to[info.m_uncomp_size] = '\0';

View File

@ -20,241 +20,240 @@ extern "C" {
#endif #endif
#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \
!defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(__ssize_t_defined) !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \
#define _SSIZE_T !defined(_SSIZE_T) && !defined(_SSIZE_T_)
// 64-bit Windows is the only mainstream platform // 64-bit Windows is the only mainstream platform
// where sizeof(long) != sizeof(void*) // where sizeof(long) != sizeof(void*)
#ifdef _WIN64 #ifdef _WIN64
typedef long long ssize_t; /* byte count or error */ typedef long long ssize_t; /* byte count or error */
#else #else
typedef long ssize_t; /* byte count or error */ typedef long ssize_t; /* byte count or error */
#endif #endif
#define _SSIZE_T_DEFINED
#define _SSIZE_T_DEFINED_
#define __DEFINED_ssize_t
#define __ssize_t_defined
#define _SSIZE_T
#define _SSIZE_T_
#endif #endif
#ifndef MAX_PATH #ifndef MAX_PATH
#define MAX_PATH 32767 /* # chars in a path name including NULL */ #define MAX_PATH 32767 /* # chars in a path name including NULL */
#endif #endif
/**
* @mainpage
*
* Documenation for @ref zip.
*/
/**
* @addtogroup zip
* @{
*/
/**
* Default zip compression level.
*/
#define ZIP_DEFAULT_COMPRESSION_LEVEL 6 #define ZIP_DEFAULT_COMPRESSION_LEVEL 6
/* /**
This data structure is used throughout the library to represent zip archive * @struct zip_t
- forward declaration. *
*/ * This data structure is used throughout the library to represent zip archive -
* forward declaration.
*/
struct zip_t; struct zip_t;
/* /**
Opens zip archive with compression level using the given mode. * Opens zip archive with compression level using the given mode.
*
Args: * @param zipname zip archive file name.
zipname: zip archive file name. * @param level compression level (0-9 are the standard zlib-style levels).
level: compression level (0-9 are the standard zlib-style levels). * @param mode file access mode.
mode: file access mode. * - 'r': opens a file for reading/extracting (the file must exists).
'r': opens a file for reading/extracting (the file must exists). * - 'w': creates an empty file for writing.
'w': creates an empty file for writing. * - 'a': appends to an existing archive.
'a': appends to an existing archive. *
* @return the zip archive handler or NULL on error
Returns: */
The zip archive handler or NULL on error
*/
extern struct zip_t *zip_open(const char *zipname, int level, char mode); extern struct zip_t *zip_open(const char *zipname, int level, char mode);
/* /**
Closes the zip archive, releases resources - always finalize. * Closes the zip archive, releases resources - always finalize.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. */
*/
extern void zip_close(struct zip_t *zip); extern void zip_close(struct zip_t *zip);
/* /**
Opens an entry by name in the zip archive. * Opens an entry by name in the zip archive.
For zip archive opened in 'w' or 'a' mode the function will append *
a new entry. In readonly mode the function tries to locate the entry * For zip archive opened in 'w' or 'a' mode the function will append
in global dictionary. * a new entry. In readonly mode the function tries to locate the entry
* in global dictionary.
Args: *
zip: zip archive handler. * @param zip zip archive handler.
entryname: an entry name in local dictionary. * @param entryname an entry name in local dictionary.
*
Returns: * @return the return code - 0 on success, negative number (< 0) on error.
The return code - 0 on success, negative number (< 0) on error. */
*/
extern int zip_entry_open(struct zip_t *zip, const char *entryname); extern int zip_entry_open(struct zip_t *zip, const char *entryname);
/* /**
Opens a new entry by index in the zip archive. * Opens a new entry by index in the zip archive.
This function is only valid if zip archive was opened in 'r' (readonly) mode. *
* This function is only valid if zip archive was opened in 'r' (readonly) mode.
Args: *
zip: zip archive handler. * @param zip zip archive handler.
index: index in local dictionary. * @param index index in local dictionary.
*
Returns: * @return the return code - 0 on success, negative number (< 0) on error.
The return code - 0 on success, negative number (< 0) on error. */
*/
extern int zip_entry_openbyindex(struct zip_t *zip, int index); extern int zip_entry_openbyindex(struct zip_t *zip, int index);
/* /**
Closes a zip entry, flushes buffer and releases resources. * Closes a zip entry, flushes buffer and releases resources.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns: */
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_entry_close(struct zip_t *zip); extern int zip_entry_close(struct zip_t *zip);
/* /**
Returns a local name of the current zip entry. * Returns a local name of the current zip entry.
The main difference between user's entry name and local entry name *
is optional relative path. * The main difference between user's entry name and local entry name
Following .ZIP File Format Specification - the path stored MUST not contain * is optional relative path.
a drive or device letter, or a leading slash. * Following .ZIP File Format Specification - the path stored MUST not contain
All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' * a drive or device letter, or a leading slash.
for compatibility with Amiga and UNIX file systems etc. * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\'
* for compatibility with Amiga and UNIX file systems etc.
Args: *
zip: zip archive handler. * @param zip: zip archive handler.
*
Returns: * @return the pointer to the current zip entry name, or NULL on error.
The pointer to the current zip entry name, or NULL on error. */
*/
extern const char *zip_entry_name(struct zip_t *zip); extern const char *zip_entry_name(struct zip_t *zip);
/* /**
Returns an index of the current zip entry. * Returns an index of the current zip entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the index on success, negative number (< 0) on error.
Returns: */
The index on success, negative number (< 0) on error.
*/
extern int zip_entry_index(struct zip_t *zip); extern int zip_entry_index(struct zip_t *zip);
/* /**
Determines if the current zip entry is a directory entry. * Determines if the current zip entry is a directory entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the return code - 1 (true), 0 (false), negative number (< 0) on
Returns: * error.
The return code - 1 (true), 0 (false), negative number (< 0) on error. */
*/
extern int zip_entry_isdir(struct zip_t *zip); extern int zip_entry_isdir(struct zip_t *zip);
/* /**
Returns an uncompressed size of the current zip entry. * Returns an uncompressed size of the current zip entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the uncompressed size in bytes.
Returns: */
The uncompressed size in bytes.
*/
extern unsigned long long zip_entry_size(struct zip_t *zip); extern unsigned long long zip_entry_size(struct zip_t *zip);
/* /**
Returns CRC-32 checksum of the current zip entry. * Returns CRC-32 checksum of the current zip entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the CRC-32 checksum.
Returns: */
The CRC-32 checksum.
*/
extern unsigned int zip_entry_crc32(struct zip_t *zip); extern unsigned int zip_entry_crc32(struct zip_t *zip);
/* /**
Compresses an input buffer for the current zip entry. * Compresses an input buffer for the current zip entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. * @param buf input buffer.
buf: input buffer. * @param bufsize input buffer size (in bytes).
bufsize: input buffer size (in bytes). *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns: */
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize);
/* /**
Compresses a file for the current zip entry. * Compresses a file for the current zip entry.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. * @param filename input file.
filename: input file. *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns: */
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_entry_fwrite(struct zip_t *zip, const char *filename); extern int zip_entry_fwrite(struct zip_t *zip, const char *filename);
/* /**
Extracts the current zip entry into output buffer. * Extracts the current zip entry into output buffer.
The function allocates sufficient memory for a output buffer. *
* The function allocates sufficient memory for a output buffer.
Args: *
zip: zip archive handler. * @param zip zip archive handler.
buf: output buffer. * @param buf output buffer.
bufsize: output buffer size (in bytes). * @param bufsize output buffer size (in bytes).
*
Note: * @note remember to release memory allocated for a output buffer.
- remember to release memory allocated for a output buffer. * for large entries, please take a look at zip_entry_extract function.
- for large entries, please take a look at zip_entry_extract function. *
* @return the return code - the number of bytes actually read on success.
Returns: * Otherwise a -1 on error.
The return code - the number of bytes actually read on success. */
Otherwise a -1 on error.
*/
extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize); extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
/* /**
Extracts the current zip entry into a memory buffer using no memory * Extracts the current zip entry into a memory buffer using no memory
allocation. * allocation.
*
* @param zip zip archive handler.
* @param buf preallocated output buffer.
* @param bufsize output buffer size (in bytes).
*
* @note ensure supplied output buffer is large enough.
* zip_entry_size function (returns uncompressed size for the current
* entry) can be handy to estimate how big buffer is needed. for large
* entries, please take a look at zip_entry_extract function.
*
* @return the return code - the number of bytes actually read on success.
* Otherwise a -1 on error (e.g. bufsize is not large enough).
*/
extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf,
size_t bufsize);
Args: /**
zip: zip archive handler. * Extracts the current zip entry into output file.
buf: preallocated output buffer. *
bufsize: output buffer size (in bytes). * @param zip zip archive handler.
* @param filename output file.
Note: *
- ensure supplied output buffer is large enough. * @return the return code - 0 on success, negative number (< 0) on error.
- zip_entry_size function (returns uncompressed size for the current entry) */
can be handy to estimate how big buffer is needed.
- for large entries, please take a look at zip_entry_extract function.
Returns:
The return code - the number of bytes actually read on success.
Otherwise a -1 on error (e.g. bufsize is not large enough).
*/
extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize);
/*
Extracts the current zip entry into output file.
Args:
zip: zip archive handler.
filename: output file.
Returns:
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_entry_fread(struct zip_t *zip, const char *filename); extern int zip_entry_fread(struct zip_t *zip, const char *filename);
/* /**
Extracts the current zip entry using a callback function (on_extract). * Extracts the current zip entry using a callback function (on_extract).
*
Args: * @param zip zip archive handler.
zip: zip archive handler. * @param on_extract callback function.
on_extract: callback function. * @param arg opaque pointer (optional argument, which you can pass to the
arg: opaque pointer (optional argument, * on_extract callback)
which you can pass to the on_extract callback) *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns:
The return code - 0 on success, negative number (< 0) on error.
*/ */
extern int extern int
zip_entry_extract(struct zip_t *zip, zip_entry_extract(struct zip_t *zip,
@ -262,53 +261,49 @@ zip_entry_extract(struct zip_t *zip,
const void *data, size_t size), const void *data, size_t size),
void *arg); void *arg);
/* /**
Returns the number of all entries (files and directories) in the zip archive. * Returns the number of all entries (files and directories) in the zip archive.
*
Args: * @param zip zip archive handler.
zip: zip archive handler. *
* @return the return code - the number of entries on success, negative number
Returns: * (< 0) on error.
The return code - the number of entries on success, */
negative number (< 0) on error.
*/
extern int zip_total_entries(struct zip_t *zip); extern int zip_total_entries(struct zip_t *zip);
/* /**
Creates a new archive and puts files into a single zip archive. * Creates a new archive and puts files into a single zip archive.
*
Args: * @param zipname zip archive file.
zipname: zip archive file. * @param filenames input files.
filenames: input files. * @param len: number of input files.
len: number of input files. *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns: */
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_create(const char *zipname, const char *filenames[], size_t len); extern int zip_create(const char *zipname, const char *filenames[], size_t len);
/* /**
Extracts a zip archive file into directory. * Extracts a zip archive file into directory.
*
If on_extract_entry is not NULL, the callback will be called after * If on_extract_entry is not NULL, the callback will be called after
successfully extracted each zip entry. * successfully extracted each zip entry.
Returning a negative value from the callback will cause abort and return an * Returning a negative value from the callback will cause abort and return an
error. The last argument (void *arg) is optional, which you can use to pass * error. The last argument (void *arg) is optional, which you can use to pass
data to the on_extract_entry callback. * data to the on_extract_entry callback.
*
Args: * @param zipname zip archive file.
zipname: zip archive file. * @param dir output directory.
dir: output directory. * @param on_extract_entry on extract callback.
on_extract_entry: on extract callback. * @param arg opaque pointer.
arg: opaque pointer. *
* @return the return code - 0 on success, negative number (< 0) on error.
Returns: */
The return code - 0 on success, negative number (< 0) on error.
*/
extern int zip_extract(const char *zipname, const char *dir, extern int zip_extract(const char *zipname, const char *dir,
int (*on_extract_entry)(const char *filename, void *arg), int (*on_extract_entry)(const char *filename, void *arg),
void *arg); void *arg);
/** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,19 +1,16 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
if(ENABLE_COVERAGE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
endif()
endif ()
# test # test
include_directories(../src) set(test_out test.out)
add_executable(test.exe test.c ../src/zip.c) set(test_miniz_out test_miniz.out)
add_executable(test_miniz.exe test_miniz.c)
add_test(NAME test COMMAND test.exe) add_executable(${test_out} test.c)
add_test(NAME test_miniz COMMAND test_miniz.exe) target_link_libraries(${test_out} zip)
add_executable(${test_miniz_out} test_miniz.c)
target_link_libraries(${test_miniz_out} zip)
add_test(NAME ${test_out} COMMAND ${test_out})
add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out})
set(test_out ${test_out} PARENT_SCOPE)
set(test_miniz_out ${test_miniz_out} PARENT_SCOPE)

View File

@ -29,6 +29,8 @@
#define XFILE "7.txt\0" #define XFILE "7.txt\0"
#define XMODE 0100777 #define XMODE 0100777
#define UNIXMODE 0100644
#define UNUSED(x) (void)x #define UNUSED(x) (void)x
static int total_entries = 0; static int total_entries = 0;
@ -102,7 +104,8 @@ static void test_read(void) {
assert(0 == zip_entry_close(zip)); assert(0 == zip_entry_close(zip));
free(buf); free(buf);
buf = NULL; buf = NULL;
bufsize = 0;
assert(0 == zip_entry_open(zip, "test/test-2.txt")); assert(0 == zip_entry_open(zip, "test/test-2.txt"));
assert(strlen(TESTDATA2) == zip_entry_size(zip)); assert(strlen(TESTDATA2) == zip_entry_size(zip));
assert(CRC32DATA2 == zip_entry_crc32(zip)); assert(CRC32DATA2 == zip_entry_crc32(zip));
@ -131,7 +134,8 @@ static void test_read(void) {
assert(0 == zip_entry_close(zip)); assert(0 == zip_entry_close(zip));
free(buf); free(buf);
buf = NULL; buf = NULL;
bufsize = 0;
buftmp = strlen(TESTDATA1); buftmp = strlen(TESTDATA1);
buf = calloc(buftmp, sizeof(char)); buf = calloc(buftmp, sizeof(char));
assert(0 == zip_entry_open(zip, "test/test-1.txt")); assert(0 == zip_entry_open(zip, "test/test-1.txt"));
@ -433,6 +437,35 @@ static void test_mtime(void) {
remove(ZIPNAME); remove(ZIPNAME);
} }
static void test_unix_permissions(void) {
#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
#else
// UNIX or APPLE
struct MZ_FILE_STAT_STRUCT file_stats;
remove(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
assert(zip != NULL);
assert(0 == zip_entry_open(zip, RFILE));
assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
assert(0 == zip_entry_close(zip));
zip_close(zip);
remove(RFILE);
assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
assert(0 == MZ_FILE_STAT(RFILE, &file_stats));
assert(UNIXMODE == file_stats.st_mode);
remove(RFILE);
remove(ZIPNAME);
#endif
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
UNUSED(argc); UNUSED(argc);
UNUSED(argv); UNUSED(argv);
@ -453,6 +486,7 @@ int main(int argc, char *argv[]) {
test_write_permissions(); test_write_permissions();
test_exe_permissions(); test_exe_permissions();
test_mtime(); test_mtime();
test_unix_permissions();
remove(ZIPNAME); remove(ZIPNAME);
return 0; return 0;

View File

@ -23,16 +23,39 @@ int main(int argc, char *argv[]) {
uint step = 0; uint step = 0;
int cmp_status; int cmp_status;
uLong src_len = (uLong)strlen(s_pStr); uLong src_len = (uLong)strlen(s_pStr);
uLong cmp_len = compressBound(src_len);
uLong uncomp_len = src_len; uLong uncomp_len = src_len;
uLong cmp_len;
uint8 *pCmp, *pUncomp; uint8 *pCmp, *pUncomp;
size_t sz;
uint total_succeeded = 0; uint total_succeeded = 0;
(void)argc, (void)argv; (void)argc, (void)argv;
printf("miniz.c version: %s\n", MZ_VERSION); printf("miniz.c version: %s\n", MZ_VERSION);
do { do {
pCmp = (uint8 *)tdefl_compress_mem_to_heap(s_pStr, src_len, &cmp_len, 0);
if (!pCmp) {
printf("tdefl_compress_mem_to_heap failed\n");
return EXIT_FAILURE;
}
if (src_len <= cmp_len) {
printf("tdefl_compress_mem_to_heap failed: from %u to %u bytes\n",
(mz_uint32)uncomp_len, (mz_uint32)cmp_len);
free(pCmp);
return EXIT_FAILURE;
}
sz = tdefl_compress_mem_to_mem(pCmp, cmp_len, s_pStr, src_len, 0);
if (sz != cmp_len) {
printf("tdefl_compress_mem_to_mem failed: expected %u, got %u\n",
(mz_uint32)cmp_len, (mz_uint32)sz);
free(pCmp);
return EXIT_FAILURE;
}
// Allocate buffers to hold compressed and uncompressed data. // Allocate buffers to hold compressed and uncompressed data.
free(pCmp);
cmp_len = compressBound(src_len);
pCmp = (mz_uint8 *)malloc((size_t)cmp_len); pCmp = (mz_uint8 *)malloc((size_t)cmp_len);
pUncomp = (mz_uint8 *)malloc((size_t)src_len); pUncomp = (mz_uint8 *)malloc((size_t)src_len);
if ((!pCmp) || (!pUncomp)) { if ((!pCmp) || (!pUncomp)) {

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

View File

@ -0,0 +1,46 @@
FIND_PACKAGE(DirectX)
IF ( MSVC )
SET(M_LIB)
ENDIF ( MSVC )
if ( MSVC )
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
endif ( MSVC )
INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/include
${Assimp_SOURCE_DIR}/code
${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR}
${Assimp_SOURCE_DIR}/samples/freeglut/include
)
LINK_DIRECTORIES(
${Assimp_BINARY_DIR}
${Assimp_BINARY_DIR}/lib
)
ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32
SimpleTexturedDirectx11/Mesh.h
SimpleTexturedDirectx11/ModelLoader.cpp
SimpleTexturedDirectx11/ModelLoader.h
#SimpleTexturedDirectx11/PixelShader.hlsl
SimpleTexturedDirectx11/TextureLoader.cpp
SimpleTexturedDirectx11/TextureLoader.h
#SimpleTexturedDirectx11/VertexShader.hlsl
SimpleTexturedDirectx11/main.cpp
)
SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
TARGET_LINK_LIBRARIES( assimp_simpletextureddirectx11 assimp ${DirectX_LIBRARY} comctl32.lib winmm.lib )
SET_TARGET_PROPERTIES( assimp_simpletextureddirectx11 PROPERTIES
OUTPUT_NAME assimp_simpletextureddirectx11
)
INSTALL( TARGETS assimp_simpletextureddirectx11
DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
)

View File

@ -1,28 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -180,6 +180,8 @@ string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat
{ {
return "textures are on disk"; return "textures are on disk";
} }
return ".";
} }
int ModelLoader::getTextureIndex(aiString * str) int ModelLoader::getTextureIndex(aiString * str)

View File

@ -1,146 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{E3B160B5-E71F-4F3F-9310-B8F156F736D8}</ProjectGuid>
<RootNamespace>SimpleTexturedDirectx11</RootNamespace>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(IncludePath);E:\OpenGL VS Files\include</IncludePath>
<LibraryPath>$(LibraryPath);E:\OpenGL VS Files\lib</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<AdditionalDependencies>assimp-vc140-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="ModelLoader.cpp" />
<ClCompile Include="TextureLoader.cpp" />
</ItemGroup>
<ItemGroup>
<FxCompile Include="PixelShader.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
</FxCompile>
<FxCompile Include="VertexShader.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
</FxCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Mesh.h" />
<ClInclude Include="ModelLoader.h" />
<ClInclude Include="TextureLoader.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{b6a86d3e-70a5-4d1e-ba05-c20902300206}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ModelLoader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TextureLoader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<FxCompile Include="VertexShader.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="PixelShader.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ModelLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Mesh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TextureLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,540 @@
{
"accessors": [
{
"bufferView": 0,
"componentType": 5126,
"count": 4,
"type": "VEC3",
"max": [
0.5,
0.5,
0.0
],
"min": [
-0.5,
-0.5,
0.0
],
"name": "Positions"
},
{
"bufferView": 1,
"componentType": 5126,
"count": 4,
"type": "VEC2",
"name": "UV0"
},
{
"bufferView": 2,
"componentType": 5126,
"count": 4,
"type": "VEC2",
"name": "UV1"
},
{
"bufferView": 3,
"componentType": 5125,
"count": 6,
"type": "SCALAR",
"name": "Indices"
}
],
"asset": {
"version": "2.0"
},
"buffers": [
{
"uri": "TextureTransformTest.bin",
"byteLength": 136
}
],
"bufferViews": [
{
"buffer": 0,
"byteLength": 48,
"name": "Positions"
},
{
"buffer": 0,
"byteOffset": 48,
"byteLength": 32,
"name": "UV0"
},
{
"buffer": 0,
"byteOffset": 80,
"byteLength": 32,
"name": "UV1"
},
{
"buffer": 0,
"byteOffset": 112,
"byteLength": 24,
"name": "Indices"
}
],
"extensionsUsed": [
"KHR_texture_transform"
],
"images": [
{
"uri": "UV.png"
},
{
"uri": "Arrow.png"
},
{
"uri": "Correct.png"
},
{
"uri": "NotSupported.png"
},
{
"uri": "Error.png"
}
],
"materials": [
{
"name": "Offset U",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0,
"extensions": {
"KHR_texture_transform": {
"offset": [
0.5,
0.0
]
}
}
},
"metallicFactor": 0
}
},
{
"name": "Offset V",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0,
"extensions": {
"KHR_texture_transform": {
"offset": [
0.0,
0.5
]
}
}
},
"metallicFactor": 0
}
},
{
"name": "Offset UV",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0,
"extensions": {
"KHR_texture_transform": {
"offset": [
0.5,
0.5
]
}
}
},
"metallicFactor": 0
}
},
{
"name": "Rotation",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 1,
"extensions": {
"KHR_texture_transform": {
"rotation": 0.39269908169872415480783042290994
}
}
},
"metallicFactor": 0
}
},
{
"name": "Scale",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 1,
"extensions": {
"KHR_texture_transform": {
"scale": [
1.5,
1.5
]
}
}
},
"metallicFactor": 0
}
},
{
"name": "All",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 1,
"extensions": {
"KHR_texture_transform": {
"offset": [
-0.2,
-0.1
],
"rotation": 0.3,
"scale": [
1.5,
1.5
]
}
}
},
"metallicFactor": 0
}
},
{
"name": "Correct",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 2
},
"metallicFactor": 0
}
},
{
"name": "NotSupported",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 3
},
"metallicFactor": 0
}
},
{
"name": "Error",
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 4
},
"metallicFactor": 0
}
}
],
"meshes": [
{
"name": "Offset U",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 2
},
"indices": 3,
"material": 0
}
]
},
{
"name": "Offset V",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 2
},
"indices": 3,
"material": 1
}
]
},
{
"name": "Offset UV",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 2
},
"indices": 3,
"material": 2
}
]
},
{
"name": "Rotation",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 3
}
]
},
{
"name": "Scale",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 4
}
]
},
{
"name": "All",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 5
}
]
},
{
"name": "Correct Marker",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 6
}
]
},
{
"name": "Not Supported Marker",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 7
}
]
},
{
"name": "Error Marker",
"primitives": [
{
"attributes": {
"POSITION": 0,
"TEXCOORD_0": 1
},
"indices": 3,
"material": 8
}
]
}
],
"nodes": [
{
"name": "Offset U",
"mesh": 0,
"translation": [
-1.1,
0.55,
0
]
},
{
"name": "Offset V",
"mesh": 1,
"translation": [
0,
0.55,
0
]
},
{
"name": "Offset UV",
"mesh": 2,
"translation": [
1.1,
0.55,
0
]
},
{
"name": "Rotation",
"mesh": 3,
"translation": [
-1.1,
-0.55,
0
],
"children": [
4,
5,
6
]
},
{
"name": "Rotation - Correct",
"mesh": 6,
"translation": [
-0.07904822439840125109869401756656,
-0.51626748576241543174100150833647,
0.01
],
"scale": [
0.15,
0.15,
0.15
]
},
{
"name": "Rotation - Not Supported",
"mesh": 7,
"translation": [
0.27781745930520227684092879831533,
-0.27781745930520227684092879831533,
0.01
],
"scale": [
0.15,
0.15,
0.15
]
},
{
"name": "Rotation - Error",
"mesh": 8,
"translation": [
0.51626748576241543174100150833647,
0.07904822439840125109869401756656,
0.01
],
"scale": [
0.15,
0.15,
0.15
]
},
{
"name": "Scale",
"mesh": 4,
"translation": [
0,
-0.55,
0
],
"children": [
8,
9
]
},
{
"name": "Scale - Correct",
"mesh": 6,
"translation": [
0.01854497287013485122728586554355,
-0.01854497287013485122728586554355,
0.01
],
"scale": [
0.1,
0.1,
0.1
]
},
{
"name": "Scale - Not Supported",
"mesh": 7,
"translation": [
0.27781745930520227684092879831533,
-0.27781745930520227684092879831533,
0.01
],
"scale": [
0.15,
0.15,
0.15
]
},
{
"name": "All",
"mesh": 5,
"translation": [
1.1,
-0.55,
0
],
"children": [
11
]
},
{
"name": "All - Correct",
"mesh": 6,
"translation": [
-0.07,
-0.25,
0.01
],
"scale": [
0.1,
0.1,
0.1
]
}
],
"scene": 0,
"scenes": [
{
"nodes": [
0,
1,
2,
3,
7,
10
]
}
],
"textures": [
{
"source": 0,
"sampler": 0
},
{
"source": 1,
"sampler": 0
},
{
"source": 2
},
{
"source": 3
},
{
"source": 4
}
],
"samplers": [
{
"wrapS": 33071,
"wrapT": 33071,
"magFilter": 9729,
"minFilter": 9729
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -54,7 +54,7 @@ class utM3DImportExport : public AbstractImportExportBase {
public: public:
virtual bool importerTest() { virtual bool importerTest() {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/WusonBlitz0.m3d", aiProcess_ValidateDataStructure ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals.m3d", aiProcess_ValidateDataStructure );
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
return nullptr != scene; return nullptr != scene;
#else #else

View File

@ -405,6 +405,13 @@ TEST_F(utglTF2ImportExport, incorrect_vertex_arrays) {
EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u); EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u);
} }
TEST_F( utglTF2ImportExport, texture_transform_test ) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/textureTransform/TextureTransformTest.gltf",
aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) {
EXPECT_TRUE( exporterTest() ); EXPECT_TRUE( exporterTest() );