Merge branch 'master' into preserve_error_string
commit
631da3a3d1
|
@ -2,6 +2,7 @@
|
||||||
build
|
build
|
||||||
.project
|
.project
|
||||||
*.kdev4*
|
*.kdev4*
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# build artefacts
|
# build artefacts
|
||||||
*.o
|
*.o
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() << ">.");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
|
|
|
@ -447,7 +447,6 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
|
||||||
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);
|
||||||
} catch (DeadlyExportError& err) {
|
} catch (DeadlyExportError& err) {
|
||||||
|
|
|
@ -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 () {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,9 +107,13 @@ 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;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
// sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess)
|
||||||
|
if(pStream) {
|
||||||
|
fileSize = pStream->FileSize();
|
||||||
// should be allocated with malloc(), because the library will call free() to deallocate
|
// should be allocated with malloc(), because the library will call free() to deallocate
|
||||||
unsigned char *data = (unsigned char*)malloc(fileSize);
|
data = (unsigned char*)malloc(fileSize);
|
||||||
if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) {
|
if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) {
|
||||||
pStream.reset();
|
pStream.reset();
|
||||||
*size = 0;
|
*size = 0;
|
||||||
|
@ -114,6 +121,7 @@ extern "C" {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pStream.reset();
|
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 */
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
3118
code/M3D/m3d.h
3118
code/M3D/m3d.h
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -228,18 +228,15 @@ namespace glTFCommon {
|
||||||
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,18 +43,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||||
|
|
||||||
#include "glTF2/glTF2Importer.h"
|
#include "glTF2/glTF2Importer.h"
|
||||||
|
#include "PostProcessing/MakeVerboseFormat.h"
|
||||||
#include "glTF2/glTF2Asset.h"
|
#include "glTF2/glTF2Asset.h"
|
||||||
#include "glTF2/glTF2AssetWriter.h"
|
#include "glTF2/glTF2AssetWriter.h"
|
||||||
#include "PostProcessing/MakeVerboseFormat.h"
|
|
||||||
|
|
||||||
|
#include <assimp/CreateAnimMesh.h>
|
||||||
#include <assimp/StringComparison.h>
|
#include <assimp/StringComparison.h>
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/DefaultLogger.hpp>
|
|
||||||
#include <assimp/importerdesc.h>
|
#include <assimp/importerdesc.h>
|
||||||
#include <assimp/CreateAnimMesh.h>
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -91,11 +91,11 @@ static const aiImporterDesc desc = {
|
||||||
"gltf glb"
|
"gltf glb"
|
||||||
};
|
};
|
||||||
|
|
||||||
glTF2Importer::glTF2Importer()
|
glTF2Importer::glTF2Importer() :
|
||||||
: BaseImporter()
|
BaseImporter(),
|
||||||
, meshOffsets()
|
meshOffsets(),
|
||||||
, embeddedTexIdxs()
|
embeddedTexIdxs(),
|
||||||
, mScene( NULL ) {
|
mScene(NULL) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +103,11 @@ glTF2Importer::~glTF2Importer() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiImporterDesc* glTF2Importer::GetInfo() const
|
const aiImporterDesc *glTF2Importer::GetInfo() const {
|
||||||
{
|
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const
|
bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
|
||||||
{
|
|
||||||
const std::string &extension = GetExtension(pFile);
|
const std::string &extension = GetExtension(pFile);
|
||||||
|
|
||||||
if (extension != "gltf" && extension != "glb")
|
if (extension != "gltf" && extension != "glb")
|
||||||
|
@ -125,8 +123,7 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
|
static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
|
||||||
{
|
|
||||||
switch (gltfWrapMode) {
|
switch (gltfWrapMode) {
|
||||||
case SamplerWrap::Mirrored_Repeat:
|
case SamplerWrap::Mirrored_Repeat:
|
||||||
return aiTextureMapMode_Mirror;
|
return aiTextureMapMode_Mirror;
|
||||||
|
@ -180,22 +177,19 @@ static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
|
||||||
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
|
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
|
inline void SetMaterialColorProperty(Asset & /*r*/, vec4 &prop, aiMaterial *mat, const char *pKey, unsigned int type, unsigned int idx) {
|
||||||
{
|
|
||||||
aiColor4D col;
|
aiColor4D col;
|
||||||
CopyValue(prop, col);
|
CopyValue(prop, col);
|
||||||
mat->AddProperty(&col, 1, pKey, type, idx);
|
mat->AddProperty(&col, 1, pKey, type, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
|
inline void SetMaterialColorProperty(Asset & /*r*/, vec3 &prop, aiMaterial *mat, const char *pKey, unsigned int type, unsigned int idx) {
|
||||||
{
|
|
||||||
aiColor4D col;
|
aiColor4D col;
|
||||||
glTFCommon::CopyValue(prop, col);
|
glTFCommon::CopyValue(prop, col);
|
||||||
mat->AddProperty(&col, 1, pKey, type, idx);
|
mat->AddProperty(&col, 1, pKey, type, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
|
inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/, glTF2::TextureInfo prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) {
|
||||||
{
|
|
||||||
if (prop.texture && prop.texture->source) {
|
if (prop.texture && prop.texture->source) {
|
||||||
aiString uri(prop.texture->source->uri);
|
aiString uri(prop.texture->source->uri);
|
||||||
|
|
||||||
|
@ -207,7 +201,26 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
|
||||||
}
|
}
|
||||||
|
|
||||||
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
|
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
|
||||||
mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot);
|
|
||||||
|
if (prop.textureTransformSupported) {
|
||||||
|
aiUVTransform transform;
|
||||||
|
transform.mScaling.x = prop.TextureTransformExt_t.scale[0];
|
||||||
|
transform.mScaling.y = prop.TextureTransformExt_t.scale[1];
|
||||||
|
transform.mRotation = -prop.TextureTransformExt_t.rotation; // must be negated
|
||||||
|
|
||||||
|
// A change of coordinates is required to map glTF UV transformations into the space used by
|
||||||
|
// Assimp. In glTF all UV origins are at 0,1 (top left of texture) in Assimp space. In Assimp
|
||||||
|
// rotation occurs around the image center (0.5,0.5) where as in glTF rotation is around the
|
||||||
|
// texture origin. All three can be corrected for solely by a change of the translation since
|
||||||
|
// the transformations available are shape preserving. Note the importer already flips the V
|
||||||
|
// coordinate of the actual meshes during import.
|
||||||
|
const ai_real rcos(cos(-transform.mRotation));
|
||||||
|
const ai_real rsin(sin(-transform.mRotation));
|
||||||
|
transform.mTranslation.x = (0.5 * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0];
|
||||||
|
transform.mTranslation.y = ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];;
|
||||||
|
|
||||||
|
mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot);
|
||||||
|
}
|
||||||
|
|
||||||
if (prop.texture->sampler) {
|
if (prop.texture->sampler) {
|
||||||
Ref<Sampler> sampler = prop.texture->sampler;
|
Ref<Sampler> sampler = prop.texture->sampler;
|
||||||
|
@ -234,8 +247,7 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::NormalTextureInfo& prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
|
inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset &r, glTF2::NormalTextureInfo &prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) {
|
||||||
{
|
|
||||||
SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot);
|
SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot);
|
||||||
|
|
||||||
if (prop.texture && prop.texture->source) {
|
if (prop.texture && prop.texture->source) {
|
||||||
|
@ -243,8 +255,7 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::OcclusionTextureInfo& prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
|
inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset &r, glTF2::OcclusionTextureInfo &prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) {
|
||||||
{
|
|
||||||
SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot);
|
SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot);
|
||||||
|
|
||||||
if (prop.texture && prop.texture->source) {
|
if (prop.texture && prop.texture->source) {
|
||||||
|
@ -252,8 +263,7 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static aiMaterial* ImportMaterial(std::vector<int>& embeddedTexIdxs, Asset& r, Material& mat)
|
static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, Material &mat) {
|
||||||
{
|
|
||||||
aiMaterial *aimat = new aiMaterial();
|
aiMaterial *aimat = new aiMaterial();
|
||||||
|
|
||||||
if (!mat.name.empty()) {
|
if (!mat.name.empty()) {
|
||||||
|
@ -311,8 +321,7 @@ static aiMaterial* ImportMaterial(std::vector<int>& embeddedTexIdxs, Asset& r, M
|
||||||
return aimat;
|
return aimat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportMaterials(glTF2::Asset& r)
|
void glTF2Importer::ImportMaterials(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
const unsigned int numImportedMaterials = unsigned(r.materials.Size());
|
const unsigned int numImportedMaterials = unsigned(r.materials.Size());
|
||||||
Material defaultMaterial;
|
Material defaultMaterial;
|
||||||
|
|
||||||
|
@ -325,24 +334,20 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void SetFace(aiFace &face, int a) {
|
||||||
static inline void SetFace(aiFace& face, int a)
|
|
||||||
{
|
|
||||||
face.mNumIndices = 1;
|
face.mNumIndices = 1;
|
||||||
face.mIndices = new unsigned int[1];
|
face.mIndices = new unsigned int[1];
|
||||||
face.mIndices[0] = a;
|
face.mIndices[0] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SetFace(aiFace& face, int a, int b)
|
static inline void SetFace(aiFace &face, int a, int b) {
|
||||||
{
|
|
||||||
face.mNumIndices = 2;
|
face.mNumIndices = 2;
|
||||||
face.mIndices = new unsigned int[2];
|
face.mIndices = new unsigned int[2];
|
||||||
face.mIndices[0] = a;
|
face.mIndices[0] = a;
|
||||||
face.mIndices[1] = b;
|
face.mIndices[1] = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SetFace(aiFace& face, int a, int b, int c)
|
static inline void SetFace(aiFace &face, int a, int b, int c) {
|
||||||
{
|
|
||||||
face.mNumIndices = 3;
|
face.mNumIndices = 3;
|
||||||
face.mIndices = new unsigned int[3];
|
face.mIndices = new unsigned int[3];
|
||||||
face.mIndices[0] = a;
|
face.mIndices[0] = a;
|
||||||
|
@ -351,8 +356,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSIMP_BUILD_DEBUG
|
#ifdef ASSIMP_BUILD_DEBUG
|
||||||
static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
|
static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) {
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < nFaces; ++i) {
|
for (unsigned i = 0; i < nFaces; ++i) {
|
||||||
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
|
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
|
||||||
unsigned idx = faces[i].mIndices[j];
|
unsigned idx = faces[i].mIndices[j];
|
||||||
|
@ -364,8 +368,7 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign
|
||||||
}
|
}
|
||||||
#endif // ASSIMP_BUILD_DEBUG
|
#endif // ASSIMP_BUILD_DEBUG
|
||||||
|
|
||||||
void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
std::vector<aiMesh *> meshes;
|
std::vector<aiMesh *> meshes;
|
||||||
|
|
||||||
unsigned int k = 0;
|
unsigned int k = 0;
|
||||||
|
@ -406,7 +409,6 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
case PrimitiveMode_TRIANGLE_FAN:
|
case PrimitiveMode_TRIANGLE_FAN:
|
||||||
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::Primitive::Attributes &attr = prim.attributes;
|
Mesh::Primitive::Attributes &attr = prim.attributes;
|
||||||
|
@ -508,7 +510,6 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aiFace *faces = 0;
|
aiFace *faces = 0;
|
||||||
size_t nFaces = 0;
|
size_t nFaces = 0;
|
||||||
|
|
||||||
|
@ -572,13 +573,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < nFaces; ++i) {
|
for (unsigned int i = 0; i < nFaces; ++i) {
|
||||||
//The ordering is to ensure that the triangles are all drawn with the same orientation
|
//The ordering is to ensure that the triangles are all drawn with the same orientation
|
||||||
if ((i + 1) % 2 == 0)
|
if ((i + 1) % 2 == 0) {
|
||||||
{
|
|
||||||
//For even n, vertices n + 1, n, and n + 2 define triangle n
|
//For even n, vertices n + 1, n, and n + 2 define triangle n
|
||||||
SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
|
SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
//For odd n, vertices n, n+1, and n+2 define triangle n
|
//For odd n, vertices n, n+1, and n+2 define triangle n
|
||||||
SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
|
SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
|
||||||
}
|
}
|
||||||
|
@ -594,8 +592,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else { // no indices provided so directly generate from counts
|
||||||
else { // no indices provided so directly generate from counts
|
|
||||||
|
|
||||||
// use the already determined count as it includes checks
|
// use the already determined count as it includes checks
|
||||||
unsigned int count = aim->mNumVertices;
|
unsigned int count = aim->mNumVertices;
|
||||||
|
@ -614,7 +611,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
nFaces = count / 2;
|
nFaces = count / 2;
|
||||||
if (nFaces * 2 != count) {
|
if (nFaces * 2 != count) {
|
||||||
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
|
ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped.");
|
||||||
count = nFaces * 2;
|
count = (unsigned int)nFaces * 2;
|
||||||
}
|
}
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < count; i += 2) {
|
for (unsigned int i = 0; i < count; i += 2) {
|
||||||
|
@ -641,7 +638,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
nFaces = count / 3;
|
nFaces = count / 3;
|
||||||
if (nFaces * 3 != count) {
|
if (nFaces * 3 != count) {
|
||||||
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
|
ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
|
||||||
count = nFaces * 3;
|
count = (unsigned int)nFaces * 3;
|
||||||
}
|
}
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < count; i += 3) {
|
for (unsigned int i = 0; i < count; i += 3) {
|
||||||
|
@ -654,13 +651,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
faces = new aiFace[nFaces];
|
faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < nFaces; ++i) {
|
for (unsigned int i = 0; i < nFaces; ++i) {
|
||||||
//The ordering is to ensure that the triangles are all drawn with the same orientation
|
//The ordering is to ensure that the triangles are all drawn with the same orientation
|
||||||
if ((i+1) % 2 == 0)
|
if ((i + 1) % 2 == 0) {
|
||||||
{
|
|
||||||
//For even n, vertices n + 1, n, and n + 2 define triangle n
|
//For even n, vertices n + 1, n, and n + 2 define triangle n
|
||||||
SetFace(faces[i], i + 1, i, i + 2);
|
SetFace(faces[i], i + 1, i, i + 2);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
//For odd n, vertices n, n+1, and n+2 define triangle n
|
//For odd n, vertices n, n+1, and n+2 define triangle n
|
||||||
SetFace(faces[i], i, i + 1, i + 2);
|
SetFace(faces[i], i, i + 1, i + 2);
|
||||||
}
|
}
|
||||||
|
@ -686,11 +680,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
|
|
||||||
if (prim.material) {
|
if (prim.material) {
|
||||||
aim->mMaterialIndex = prim.material.GetIndex();
|
aim->mMaterialIndex = prim.material.GetIndex();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
aim->mMaterialIndex = mScene->mNumMaterials - 1;
|
aim->mMaterialIndex = mScene->mNumMaterials - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,8 +691,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
|
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportCameras(glTF2::Asset& r)
|
void glTF2Importer::ImportCameras(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
if (!r.cameras.Size()) return;
|
if (!r.cameras.Size()) return;
|
||||||
|
|
||||||
mScene->mNumCameras = r.cameras.Size();
|
mScene->mNumCameras = r.cameras.Size();
|
||||||
|
@ -732,8 +723,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportLights(glTF2::Asset& r)
|
void glTF2Importer::ImportLights(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
if (!r.lights.Size())
|
if (!r.lights.Size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -745,18 +735,19 @@ void glTF2Importer::ImportLights(glTF2::Asset& r)
|
||||||
|
|
||||||
aiLight *ail = mScene->mLights[i] = new aiLight();
|
aiLight *ail = mScene->mLights[i] = new aiLight();
|
||||||
|
|
||||||
switch (light.type)
|
switch (light.type) {
|
||||||
{
|
|
||||||
case Light::Directional:
|
case Light::Directional:
|
||||||
ail->mType = aiLightSource_DIRECTIONAL; break;
|
ail->mType = aiLightSource_DIRECTIONAL;
|
||||||
|
break;
|
||||||
case Light::Point:
|
case Light::Point:
|
||||||
ail->mType = aiLightSource_POINT; break;
|
ail->mType = aiLightSource_POINT;
|
||||||
|
break;
|
||||||
case Light::Spot:
|
case Light::Spot:
|
||||||
ail->mType = aiLightSource_SPOT; break;
|
ail->mType = aiLightSource_SPOT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ail->mType != aiLightSource_POINT)
|
if (ail->mType != aiLightSource_POINT) {
|
||||||
{
|
|
||||||
ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f);
|
ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f);
|
||||||
ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
|
ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
@ -766,14 +757,11 @@ void glTF2Importer::ImportLights(glTF2::Asset& r)
|
||||||
CopyValue(colorWithIntensity, ail->mColorDiffuse);
|
CopyValue(colorWithIntensity, ail->mColorDiffuse);
|
||||||
CopyValue(colorWithIntensity, ail->mColorSpecular);
|
CopyValue(colorWithIntensity, ail->mColorSpecular);
|
||||||
|
|
||||||
if (ail->mType == aiLightSource_DIRECTIONAL)
|
if (ail->mType == aiLightSource_DIRECTIONAL) {
|
||||||
{
|
|
||||||
ail->mAttenuationConstant = 1.0;
|
ail->mAttenuationConstant = 1.0;
|
||||||
ail->mAttenuationLinear = 0.0;
|
ail->mAttenuationLinear = 0.0;
|
||||||
ail->mAttenuationQuadratic = 0.0;
|
ail->mAttenuationQuadratic = 0.0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
//in PBR attenuation is calculated using inverse square law which can be expressed
|
//in PBR attenuation is calculated using inverse square law which can be expressed
|
||||||
//using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
|
//using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
|
||||||
//this is correct equation for the case when range (see
|
//this is correct equation for the case when range (see
|
||||||
|
@ -787,8 +775,7 @@ void glTF2Importer::ImportLights(glTF2::Asset& r)
|
||||||
ail->mAttenuationQuadratic = 1.0;
|
ail->mAttenuationQuadratic = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ail->mType == aiLightSource_SPOT)
|
if (ail->mType == aiLightSource_SPOT) {
|
||||||
{
|
|
||||||
ail->mAngleInnerCone = light.innerConeAngle;
|
ail->mAngleInnerCone = light.innerConeAngle;
|
||||||
ail->mAngleOuterCone = light.outerConeAngle;
|
ail->mAngleOuterCone = light.outerConeAngle;
|
||||||
}
|
}
|
||||||
|
@ -798,8 +785,7 @@ void glTF2Importer::ImportLights(glTF2::Asset& r)
|
||||||
static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) {
|
static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) {
|
||||||
if (node.matrix.isPresent) {
|
if (node.matrix.isPresent) {
|
||||||
CopyValue(node.matrix.value, matrix);
|
CopyValue(node.matrix.value, matrix);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (node.translation.isPresent) {
|
if (node.translation.isPresent) {
|
||||||
aiVector3D trans;
|
aiVector3D trans;
|
||||||
CopyValue(node.translation.value, trans);
|
CopyValue(node.translation.value, trans);
|
||||||
|
@ -824,8 +810,7 @@ static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector<std::vector<aiVertexWeight>>& map)
|
static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std::vector<aiVertexWeight>> &map) {
|
||||||
{
|
|
||||||
Mesh::Primitive::Attributes &attr = primitive.attributes;
|
Mesh::Primitive::Attributes &attr = primitive.attributes;
|
||||||
if (attr.weight.empty() || attr.joint.empty()) {
|
if (attr.weight.empty() || attr.joint.empty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -836,12 +821,18 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector<std
|
||||||
|
|
||||||
size_t num_vertices = attr.weight[0]->count;
|
size_t num_vertices = attr.weight[0]->count;
|
||||||
|
|
||||||
struct Weights { float values[4]; };
|
struct Weights {
|
||||||
|
float values[4];
|
||||||
|
};
|
||||||
Weights *weights = nullptr;
|
Weights *weights = nullptr;
|
||||||
attr.weight[0]->ExtractData(weights);
|
attr.weight[0]->ExtractData(weights);
|
||||||
|
|
||||||
struct Indices8 { uint8_t values[4]; };
|
struct Indices8 {
|
||||||
struct Indices16 { uint16_t values[4]; };
|
uint8_t values[4];
|
||||||
|
};
|
||||||
|
struct Indices16 {
|
||||||
|
uint16_t values[4];
|
||||||
|
};
|
||||||
Indices8 *indices8 = nullptr;
|
Indices8 *indices8 = nullptr;
|
||||||
Indices16 *indices16 = nullptr;
|
Indices16 *indices16 = nullptr;
|
||||||
if (attr.joint[0]->GetElementSize() == 4) {
|
if (attr.joint[0]->GetElementSize() == 4) {
|
||||||
|
@ -872,13 +863,11 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector<std
|
||||||
delete[] indices16;
|
delete[] indices16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetNodeName(const Node& node)
|
static std::string GetNodeName(const Node &node) {
|
||||||
{
|
|
||||||
return node.name.empty() ? node.id : node.name;
|
return node.name.empty() ? node.id : node.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
|
aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) {
|
||||||
{
|
|
||||||
Node &node = *ptr;
|
Node &node = *ptr;
|
||||||
|
|
||||||
aiNode *ainode = new aiNode(GetNodeName(node));
|
aiNode *ainode = new aiNode(GetNodeName(node));
|
||||||
|
@ -980,8 +969,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
|
||||||
|
|
||||||
//range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
|
//range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
|
||||||
//it is added to meta data of parent node, because there is no other place to put it
|
//it is added to meta data of parent node, because there is no other place to put it
|
||||||
if (node.light->range.isPresent)
|
if (node.light->range.isPresent) {
|
||||||
{
|
|
||||||
ainode->mMetaData = aiMetadata::Alloc(1);
|
ainode->mMetaData = aiMetadata::Alloc(1);
|
||||||
ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
|
ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
|
||||||
}
|
}
|
||||||
|
@ -990,8 +978,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
|
||||||
return ainode;
|
return ainode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportNodes(glTF2::Asset& r)
|
void glTF2Importer::ImportNodes(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
if (!r.scene) return;
|
if (!r.scene) return;
|
||||||
|
|
||||||
std::vector<Ref<Node>> rootNodes = r.scene->nodes;
|
std::vector<Ref<Node>> rootNodes = r.scene->nodes;
|
||||||
|
@ -1000,8 +987,7 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r)
|
||||||
unsigned int numRootNodes = unsigned(rootNodes.size());
|
unsigned int numRootNodes = unsigned(rootNodes.size());
|
||||||
if (numRootNodes == 1) { // a single root node: use it
|
if (numRootNodes == 1) { // a single root node: use it
|
||||||
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
|
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
|
||||||
}
|
} else if (numRootNodes > 1) { // more than one root node: create a fake root
|
||||||
else if (numRootNodes > 1) { // more than one root node: create a fake root
|
|
||||||
aiNode *root = new aiNode("ROOT");
|
aiNode *root = new aiNode("ROOT");
|
||||||
root->mChildren = new aiNode *[numRootNodes];
|
root->mChildren = new aiNode *[numRootNodes];
|
||||||
for (unsigned int i = 0; i < numRootNodes; ++i) {
|
for (unsigned int i = 0; i < numRootNodes; ++i) {
|
||||||
|
@ -1011,18 +997,14 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
mScene->mRootNode = root;
|
mScene->mRootNode = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!mScene->mRootNode) {
|
|
||||||
// mScene->mRootNode = new aiNode("EMPTY");
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnimationSamplers {
|
struct AnimationSamplers {
|
||||||
AnimationSamplers()
|
AnimationSamplers() :
|
||||||
: translation(nullptr)
|
translation(nullptr),
|
||||||
, rotation(nullptr)
|
rotation(nullptr),
|
||||||
, scale(nullptr)
|
scale(nullptr),
|
||||||
, weight(nullptr) {
|
weight(nullptr) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,8 +1014,7 @@ struct AnimationSamplers {
|
||||||
Animation::Sampler *weight;
|
Animation::Sampler *weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
|
aiNodeAnim *CreateNodeAnim(glTF2::Asset &r, Node &node, AnimationSamplers &samplers) {
|
||||||
{
|
|
||||||
aiNodeAnim *anim = new aiNodeAnim();
|
aiNodeAnim *anim = new aiNodeAnim();
|
||||||
anim->mNodeName = GetNodeName(node);
|
anim->mNodeName = GetNodeName(node);
|
||||||
|
|
||||||
|
@ -1112,8 +1093,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
|
||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
|
aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset &r, Node &node, AnimationSamplers &samplers) {
|
||||||
{
|
|
||||||
aiMeshMorphAnim *anim = new aiMeshMorphAnim();
|
aiMeshMorphAnim *anim = new aiMeshMorphAnim();
|
||||||
anim->mName = GetNodeName(node);
|
anim->mName = GetNodeName(node);
|
||||||
|
|
||||||
|
@ -1126,7 +1106,7 @@ aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSampl
|
||||||
samplers.weight->output->ExtractData(values);
|
samplers.weight->output->ExtractData(values);
|
||||||
anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
|
anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
|
||||||
|
|
||||||
const unsigned int numMorphs = samplers.weight->output->count / anim->mNumKeys;
|
const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
|
||||||
|
|
||||||
anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
|
anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
|
||||||
unsigned int k = 0u;
|
unsigned int k = 0u;
|
||||||
|
@ -1149,8 +1129,7 @@ aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSampl
|
||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& anim)
|
std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation &anim) {
|
||||||
{
|
|
||||||
std::unordered_map<unsigned int, AnimationSamplers> samplers;
|
std::unordered_map<unsigned int, AnimationSamplers> samplers;
|
||||||
for (unsigned int c = 0; c < anim.channels.size(); ++c) {
|
for (unsigned int c = 0; c < anim.channels.size(); ++c) {
|
||||||
Animation::Channel &channel = anim.channels[c];
|
Animation::Channel &channel = anim.channels[c];
|
||||||
|
@ -1175,8 +1154,7 @@ std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& an
|
||||||
return samplers;
|
return samplers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportAnimations(glTF2::Asset& r)
|
void glTF2Importer::ImportAnimations(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
if (!r.scene) return;
|
if (!r.scene) return;
|
||||||
|
|
||||||
mScene->mNumAnimations = r.animations.Size();
|
mScene->mNumAnimations = r.animations.Size();
|
||||||
|
@ -1278,8 +1256,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r)
|
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
|
||||||
{
|
|
||||||
embeddedTexIdxs.resize(r.images.Size(), -1);
|
embeddedTexIdxs.resize(r.images.Size(), -1);
|
||||||
|
|
||||||
int numEmbeddedTexs = 0;
|
int numEmbeddedTexs = 0;
|
||||||
|
@ -1324,8 +1301,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||||
{
|
|
||||||
// clean all member arrays
|
// clean all member arrays
|
||||||
meshOffsets.clear();
|
meshOffsets.clear();
|
||||||
embeddedTexIdxs.clear();
|
embeddedTexIdxs.clear();
|
||||||
|
@ -1358,4 +1334,3 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
|
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||||
|
|
||||||
|
|
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
mz_uint s = MZ_READ_LE32(pBuf + i);
|
||||||
|
if (s == record_sig) {
|
||||||
|
if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
|
||||||
break;
|
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);
|
||||||
|
local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
|
||||||
|
filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
|
||||||
|
ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
|
||||||
|
|
||||||
|
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)) &&
|
if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
|
||||||
(decomp_size != comp_size)) ||
|
(decomp_size != comp_size)) ||
|
||||||
(decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) ||
|
(decomp_size && !comp_size))
|
||||||
(comp_size == 0xFFFFFFFF))
|
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
|
||||||
return MZ_FALSE;
|
}
|
||||||
|
|
||||||
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)))
|
||||||
|
return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
|
||||||
|
|
||||||
|
if (comp_size != MZ_UINT32_MAX) {
|
||||||
if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
|
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)
|
MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
|
||||||
return MZ_FALSE;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,27 +77,35 @@ 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);
|
||||||
|
@ -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';
|
||||||
|
|
|
@ -20,8 +20,9 @@ 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
|
||||||
|
@ -29,232 +30,230 @@ 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.
|
||||||
|
*
|
||||||
Args:
|
* @param zip zip archive handler.
|
||||||
zip: zip archive handler.
|
* @param buf preallocated output buffer.
|
||||||
buf: preallocated output buffer.
|
* @param bufsize output buffer size (in bytes).
|
||||||
bufsize: output buffer size (in bytes).
|
*
|
||||||
|
* @note ensure supplied output buffer is large enough.
|
||||||
Note:
|
* zip_entry_size function (returns uncompressed size for the current
|
||||||
- ensure supplied output buffer is large enough.
|
* entry) can be handy to estimate how big buffer is needed. for large
|
||||||
- zip_entry_size function (returns uncompressed size for the current entry)
|
* entries, please take a look at zip_entry_extract function.
|
||||||
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).
|
||||||
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);
|
extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf,
|
||||||
|
size_t bufsize);
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Extracts the current zip entry into output file.
|
* Extracts the current zip entry into output file.
|
||||||
|
*
|
||||||
Args:
|
* @param zip zip archive handler.
|
||||||
zip: zip archive handler.
|
* @param filename output file.
|
||||||
filename: output 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_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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,6 +104,7 @@ 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));
|
||||||
|
@ -131,6 +134,7 @@ 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));
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -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
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
|
|
@ -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 |
Binary file not shown.
|
@ -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 |
|
@ -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
|
||||||
|
|
|
@ -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() );
|
||||||
|
|
Loading…
Reference in New Issue