glTF: Try to remove duplicate code.
parent
28d0300dbe
commit
7ff7a5d64e
|
@ -766,6 +766,8 @@ ADD_ASSIMP_EXPORTER( X3D
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER( GLTF
|
ADD_ASSIMP_IMPORTER( GLTF
|
||||||
|
glTF/glTFCommon.h
|
||||||
|
glTF/glTFCommon.cpp
|
||||||
glTF/glTFAsset.h
|
glTF/glTFAsset.h
|
||||||
glTF/glTFAsset.inl
|
glTF/glTFAsset.inl
|
||||||
glTF/glTFAssetWriter.h
|
glTF/glTFAssetWriter.h
|
||||||
|
|
|
@ -85,7 +85,7 @@ void BaseImporter::UpdateImporterScale( Importer* pImp )
|
||||||
double activeScale = importerScale * fileScale;
|
double activeScale = importerScale * fileScale;
|
||||||
|
|
||||||
// Set active scaling
|
// Set active scaling
|
||||||
pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, activeScale);
|
pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast<float>( activeScale) );
|
||||||
|
|
||||||
ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale );
|
ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale );
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,38 +92,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "glTF/glTFCommon.h"
|
||||||
|
|
||||||
namespace glTF
|
namespace glTF
|
||||||
{
|
{
|
||||||
#ifdef ASSIMP_API
|
using glTFCommon::shared_ptr;
|
||||||
using Assimp::IOStream;
|
using glTFCommon::IOSystem;
|
||||||
using Assimp::IOSystem;
|
using glTFCommon::IOStream;
|
||||||
using std::shared_ptr;
|
|
||||||
#else
|
|
||||||
using std::shared_ptr;
|
|
||||||
|
|
||||||
typedef std::runtime_error DeadlyImportError;
|
|
||||||
typedef std::runtime_error DeadlyExportError;
|
|
||||||
|
|
||||||
enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 };
|
|
||||||
class IOSystem;
|
|
||||||
class IOStream
|
|
||||||
{
|
|
||||||
FILE* f;
|
|
||||||
public:
|
|
||||||
IOStream(FILE* file) : f(file) {}
|
|
||||||
~IOStream() { fclose(f); f = 0; }
|
|
||||||
|
|
||||||
size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
|
|
||||||
size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
|
|
||||||
int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
|
|
||||||
size_t Tell() const { return ftell(f); }
|
|
||||||
|
|
||||||
size_t FileSize() {
|
|
||||||
long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
|
|
||||||
return size_t((Seek(p, aiOrigin_SET), len));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using rapidjson::Value;
|
using rapidjson::Value;
|
||||||
using rapidjson::Document;
|
using rapidjson::Document;
|
||||||
|
@ -136,37 +111,9 @@ namespace glTF
|
||||||
struct Light;
|
struct Light;
|
||||||
struct Skin;
|
struct Skin;
|
||||||
|
|
||||||
|
using glTFCommon::vec3;
|
||||||
// Vec/matrix types, as raw float arrays
|
using glTFCommon::vec4;
|
||||||
typedef float (vec3)[3];
|
using glTFCommon::mat4;
|
||||||
typedef float (vec4)[4];
|
|
||||||
typedef float (mat4)[16];
|
|
||||||
|
|
||||||
|
|
||||||
namespace Util
|
|
||||||
{
|
|
||||||
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
|
|
||||||
|
|
||||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
|
||||||
|
|
||||||
inline size_t DecodeBase64(const char* in, uint8_t*& out)
|
|
||||||
{
|
|
||||||
return DecodeBase64(in, strlen(in), out);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DataURI
|
|
||||||
{
|
|
||||||
const char* mediaType;
|
|
||||||
const char* charset;
|
|
||||||
bool base64;
|
|
||||||
const char* data;
|
|
||||||
size_t dataLength;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Check if a uri is a data URI
|
|
||||||
inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! Magic number for GLB files
|
//! Magic number for GLB files
|
||||||
#define AI_GLB_MAGIC_NUMBER "glTF"
|
#define AI_GLB_MAGIC_NUMBER "glTF"
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2019, assimp team
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -52,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
using namespace glTFCommon;
|
||||||
|
|
||||||
namespace glTF {
|
namespace glTF {
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ inline void Buffer::Read(Value& obj, Asset& r)
|
||||||
|
|
||||||
const char* uri = it->GetString();
|
const char* uri = it->GetString();
|
||||||
|
|
||||||
Util::DataURI dataURI;
|
glTFCommon::Util::DataURI dataURI;
|
||||||
if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
|
if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
|
||||||
if (dataURI.base64) {
|
if (dataURI.base64) {
|
||||||
uint8_t* data = 0;
|
uint8_t* data = 0;
|
||||||
|
@ -654,12 +654,12 @@ inline void Image::Read(Value& obj, Asset& r)
|
||||||
if (Value* uri = FindString(obj, "uri")) {
|
if (Value* uri = FindString(obj, "uri")) {
|
||||||
const char* uristr = uri->GetString();
|
const char* uristr = uri->GetString();
|
||||||
|
|
||||||
Util::DataURI dataURI;
|
glTFCommon::Util::DataURI dataURI;
|
||||||
if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
|
if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
|
||||||
mimeType = dataURI.mediaType;
|
mimeType = dataURI.mediaType;
|
||||||
if (dataURI.base64) {
|
if (dataURI.base64) {
|
||||||
uint8_t *ptr = nullptr;
|
uint8_t *ptr = nullptr;
|
||||||
mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
|
mDataLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
|
||||||
mData.reset(ptr);
|
mData.reset(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1474,190 +1474,4 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
|
|
||||||
if ( NULL == const_uri ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const_uri[0] != 0x10) { // we already parsed this uri?
|
|
||||||
if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set defaults
|
|
||||||
out.mediaType = "text/plain";
|
|
||||||
out.charset = "US-ASCII";
|
|
||||||
out.base64 = false;
|
|
||||||
|
|
||||||
char* uri = const_cast<char*>(const_uri);
|
|
||||||
if (uri[0] != 0x10) {
|
|
||||||
uri[0] = 0x10;
|
|
||||||
uri[1] = uri[2] = uri[3] = uri[4] = 0;
|
|
||||||
|
|
||||||
size_t i = 5, j;
|
|
||||||
if (uri[i] != ';' && uri[i] != ',') { // has media type?
|
|
||||||
uri[1] = char(i);
|
|
||||||
for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
|
||||||
// nothing to do!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (uri[i] == ';' && i < uriLen) {
|
|
||||||
uri[i++] = '\0';
|
|
||||||
for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
|
||||||
// nothing to do!
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( strncmp( uri + j, "charset=", 8 ) == 0 ) {
|
|
||||||
uri[2] = char(j + 8);
|
|
||||||
} else if ( strncmp( uri + j, "base64", 6 ) == 0 ) {
|
|
||||||
uri[3] = char(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i < uriLen) {
|
|
||||||
uri[i++] = '\0';
|
|
||||||
uri[4] = char(i);
|
|
||||||
} else {
|
|
||||||
uri[1] = uri[2] = uri[3] = 0;
|
|
||||||
uri[4] = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( uri[ 1 ] != 0 ) {
|
|
||||||
out.mediaType = uri + uri[ 1 ];
|
|
||||||
}
|
|
||||||
if ( uri[ 2 ] != 0 ) {
|
|
||||||
out.charset = uri + uri[ 2 ];
|
|
||||||
}
|
|
||||||
if ( uri[ 3 ] != 0 ) {
|
|
||||||
out.base64 = true;
|
|
||||||
}
|
|
||||||
out.data = uri + uri[4];
|
|
||||||
out.dataLength = (uri + uriLen) - out.data;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool B>
|
|
||||||
struct DATA
|
|
||||||
{
|
|
||||||
static const uint8_t tableDecodeBase64[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
template<bool B>
|
|
||||||
const uint8_t DATA<B>::tableDecodeBase64[128] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
|
|
||||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
|
||||||
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
inline char EncodeCharBase64(uint8_t b)
|
|
||||||
{
|
|
||||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t DecodeCharBase64(char c)
|
|
||||||
{
|
|
||||||
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; // '-' */
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
|
|
||||||
{
|
|
||||||
ai_assert(inLength % 4 == 0);
|
|
||||||
|
|
||||||
if (inLength < 4) {
|
|
||||||
out = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nEquals = int(in[inLength - 1] == '=') +
|
|
||||||
int(in[inLength - 2] == '=');
|
|
||||||
|
|
||||||
size_t outLength = (inLength * 3) / 4 - nEquals;
|
|
||||||
out = new uint8_t[outLength];
|
|
||||||
memset(out, 0, outLength);
|
|
||||||
|
|
||||||
size_t i, j = 0;
|
|
||||||
|
|
||||||
for (i = 0; i + 4 < inLength; i += 4) {
|
|
||||||
uint8_t b0 = DecodeCharBase64(in[i]);
|
|
||||||
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
|
||||||
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
|
||||||
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
|
||||||
|
|
||||||
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
|
||||||
out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
|
||||||
out[j++] = (uint8_t)((b2 << 6) | b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t b0 = DecodeCharBase64(in[i]);
|
|
||||||
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
|
||||||
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
|
||||||
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
|
||||||
|
|
||||||
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
|
||||||
if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
|
||||||
if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void EncodeBase64(
|
|
||||||
const uint8_t* in, size_t inLength,
|
|
||||||
std::string& out)
|
|
||||||
{
|
|
||||||
size_t outLength = ((inLength + 2) / 3) * 4;
|
|
||||||
|
|
||||||
size_t j = out.size();
|
|
||||||
out.resize(j + outLength);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < inLength; i += 3) {
|
|
||||||
uint8_t b = (in[i] & 0xFC) >> 2;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = (in[i] & 0x03) << 4;
|
|
||||||
if (i + 1 < inLength) {
|
|
||||||
b |= (in[i + 1] & 0xF0) >> 4;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = (in[i + 1] & 0x0F) << 2;
|
|
||||||
if (i + 2 < inLength) {
|
|
||||||
b |= (in[i + 2] & 0xC0) >> 6;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = in[i + 2] & 0x3F;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
out[j++] = '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
out[j++] = '=';
|
|
||||||
out[j++] = '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // ns glTF
|
} // ns glTF
|
||||||
|
|
|
@ -215,7 +215,7 @@ namespace glTF {
|
||||||
else if (img.HasData()) {
|
else if (img.HasData()) {
|
||||||
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
|
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
|
||||||
uri += ";base64,";
|
uri += ";base64,";
|
||||||
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
|
glTFCommon::Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = img.uri;
|
uri = img.uri;
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#include "glTF/glTFCommon.h"
|
||||||
|
|
||||||
|
namespace glTFCommon {
|
||||||
|
|
||||||
|
using namespace glTFCommon::Util;
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out) {
|
||||||
|
ai_assert(inLength % 4 == 0);
|
||||||
|
|
||||||
|
if (inLength < 4) {
|
||||||
|
out = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nEquals = int(in[inLength - 1] == '=') +
|
||||||
|
int(in[inLength - 2] == '=');
|
||||||
|
|
||||||
|
size_t outLength = (inLength * 3) / 4 - nEquals;
|
||||||
|
out = new uint8_t[outLength];
|
||||||
|
memset(out, 0, outLength);
|
||||||
|
|
||||||
|
size_t i, j = 0;
|
||||||
|
|
||||||
|
for (i = 0; i + 4 < inLength; i += 4) {
|
||||||
|
uint8_t b0 = DecodeCharBase64(in[i]);
|
||||||
|
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
||||||
|
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
||||||
|
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
||||||
|
|
||||||
|
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
||||||
|
out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
||||||
|
out[j++] = (uint8_t)((b2 << 6) | b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t b0 = DecodeCharBase64(in[i]);
|
||||||
|
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
||||||
|
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
||||||
|
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
||||||
|
|
||||||
|
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
||||||
|
if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
||||||
|
if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out) {
|
||||||
|
size_t outLength = ((inLength + 2) / 3) * 4;
|
||||||
|
|
||||||
|
size_t j = out.size();
|
||||||
|
out.resize(j + outLength);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < inLength; i += 3) {
|
||||||
|
uint8_t b = (in[i] & 0xFC) >> 2;
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
|
||||||
|
b = (in[i] & 0x03) << 4;
|
||||||
|
if (i + 1 < inLength) {
|
||||||
|
b |= (in[i + 1] & 0xF0) >> 4;
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
|
||||||
|
b = (in[i + 1] & 0x0F) << 2;
|
||||||
|
if (i + 2 < inLength) {
|
||||||
|
b |= (in[i + 2] & 0xC0) >> 6;
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
|
||||||
|
b = in[i + 2] & 0x3F;
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
out[j++] = '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out[j++] = EncodeCharBase64(b);
|
||||||
|
out[j++] = '=';
|
||||||
|
out[j++] = '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
|
||||||
|
if (nullptr == const_uri) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const_uri[0] != 0x10) { // we already parsed this uri?
|
||||||
|
if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set defaults
|
||||||
|
out.mediaType = "text/plain";
|
||||||
|
out.charset = "US-ASCII";
|
||||||
|
out.base64 = false;
|
||||||
|
|
||||||
|
char* uri = const_cast<char*>(const_uri);
|
||||||
|
if (uri[0] != 0x10) {
|
||||||
|
uri[0] = 0x10;
|
||||||
|
uri[1] = uri[2] = uri[3] = uri[4] = 0;
|
||||||
|
|
||||||
|
size_t i = 5, j;
|
||||||
|
if (uri[i] != ';' && uri[i] != ',') { // has media type?
|
||||||
|
uri[1] = char(i);
|
||||||
|
for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
||||||
|
// nothing to do!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (uri[i] == ';' && i < uriLen) {
|
||||||
|
uri[i++] = '\0';
|
||||||
|
for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
||||||
|
// nothing to do!
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(uri + j, "charset=", 8) == 0) {
|
||||||
|
uri[2] = char(j + 8);
|
||||||
|
}
|
||||||
|
else if (strncmp(uri + j, "base64", 6) == 0) {
|
||||||
|
uri[3] = char(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < uriLen) {
|
||||||
|
uri[i++] = '\0';
|
||||||
|
uri[4] = char(i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uri[1] = uri[2] = uri[3] = 0;
|
||||||
|
uri[4] = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri[1] != 0) {
|
||||||
|
out.mediaType = uri + uri[1];
|
||||||
|
}
|
||||||
|
if (uri[2] != 0) {
|
||||||
|
out.charset = uri + uri[2];
|
||||||
|
}
|
||||||
|
if (uri[3] != 0) {
|
||||||
|
out.base64 = true;
|
||||||
|
}
|
||||||
|
out.data = uri + uri[4];
|
||||||
|
out.dataLength = (uri + uriLen) - out.data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019, assimp team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the
|
||||||
|
following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef AI_GLFTCOMMON_H_INC
|
||||||
|
#define AI_GLFTCOMMON_H_INC
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||||
|
|
||||||
|
#include <assimp/Exceptional.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#define RAPIDJSON_HAS_STDSTRING 1
|
||||||
|
#include <rapidjson/rapidjson.h>
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <rapidjson/error/en.h>
|
||||||
|
|
||||||
|
#ifdef ASSIMP_API
|
||||||
|
# include <memory>
|
||||||
|
# include <assimp/DefaultIOSystem.h>
|
||||||
|
# include <assimp/ByteSwapper.h>
|
||||||
|
#else
|
||||||
|
# include <memory>
|
||||||
|
# define AI_SWAP4(p)
|
||||||
|
# define ai_assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if _MSC_VER > 1500 || (defined __GNUC___)
|
||||||
|
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||||
|
# else
|
||||||
|
# define gltf_unordered_map map
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
|
||||||
|
# include <unordered_map>
|
||||||
|
# if _MSC_VER > 1600
|
||||||
|
# define gltf_unordered_map unordered_map
|
||||||
|
# else
|
||||||
|
# define gltf_unordered_map tr1::unordered_map
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace glTFCommon {
|
||||||
|
|
||||||
|
#ifdef ASSIMP_API
|
||||||
|
using Assimp::IOStream;
|
||||||
|
using Assimp::IOSystem;
|
||||||
|
using std::shared_ptr;
|
||||||
|
#else
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
|
typedef std::runtime_error DeadlyImportError;
|
||||||
|
typedef std::runtime_error DeadlyExportError;
|
||||||
|
|
||||||
|
enum aiOrigin {
|
||||||
|
aiOrigin_SET = 0,
|
||||||
|
aiOrigin_CUR = 1,
|
||||||
|
aiOrigin_END = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
class IOSystem;
|
||||||
|
|
||||||
|
class IOStream {
|
||||||
|
public:
|
||||||
|
IOStream(FILE* file) : f(file) {}
|
||||||
|
~IOStream() { fclose(f); f = 0; }
|
||||||
|
|
||||||
|
size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
|
||||||
|
size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
|
||||||
|
int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
|
||||||
|
size_t Tell() const { return ftell(f); }
|
||||||
|
|
||||||
|
size_t FileSize() {
|
||||||
|
long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
|
||||||
|
return size_t((Seek(p, aiOrigin_SET), len));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* f;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Vec/matrix types, as raw float arrays
|
||||||
|
typedef float(vec3)[3];
|
||||||
|
typedef float(vec4)[4];
|
||||||
|
typedef float(mat4)[16];
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec3& v, aiColor4D& out) {
|
||||||
|
out.r = v[0];
|
||||||
|
out.g = v[1];
|
||||||
|
out.b = v[2];
|
||||||
|
out.a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec4& v, aiColor4D& out) {
|
||||||
|
out.r = v[0];
|
||||||
|
out.g = v[1];
|
||||||
|
out.b = v[2];
|
||||||
|
out.a = v[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec4& v, aiColor3D& out) {
|
||||||
|
out.r = v[0];
|
||||||
|
out.g = v[1];
|
||||||
|
out.b = v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec3& v, aiColor3D& out) {
|
||||||
|
out.r = v[0];
|
||||||
|
out.g = v[1];
|
||||||
|
out.b = v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec3& v, aiVector3D& out) {
|
||||||
|
out.x = v[0];
|
||||||
|
out.y = v[1];
|
||||||
|
out.z = v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::vec4& v, aiQuaternion& out) {
|
||||||
|
out.x = v[0];
|
||||||
|
out.y = v[1];
|
||||||
|
out.z = v[2];
|
||||||
|
out.w = v[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CopyValue(const glTFCommon::mat4& v, aiMatrix4x4& o) {
|
||||||
|
o.a1 = v[0]; o.b1 = v[1]; o.c1 = v[2]; o.d1 = v[3];
|
||||||
|
o.a2 = v[4]; o.b2 = v[5]; o.c2 = v[6]; o.d2 = v[7];
|
||||||
|
o.a3 = v[8]; o.b3 = v[9]; o.c3 = v[10]; o.d3 = v[11];
|
||||||
|
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
|
||||||
|
|
||||||
|
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
||||||
|
|
||||||
|
inline
|
||||||
|
size_t DecodeBase64(const char* in, uint8_t*& out) {
|
||||||
|
return DecodeBase64(in, strlen(in), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DataURI {
|
||||||
|
const char* mediaType;
|
||||||
|
const char* charset;
|
||||||
|
bool base64;
|
||||||
|
const char* data;
|
||||||
|
size_t dataLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Check if a uri is a data URI
|
||||||
|
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out);
|
||||||
|
|
||||||
|
template<bool B>
|
||||||
|
struct DATA {
|
||||||
|
static const uint8_t tableDecodeBase64[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
template<bool B>
|
||||||
|
const uint8_t DATA<B>::tableDecodeBase64[128] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
|
||||||
|
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||||
|
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
char EncodeCharBase64(uint8_t b) {
|
||||||
|
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
uint8_t DecodeCharBase64(char c) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||||
|
|
||||||
|
#endif // AI_GLFTCOMMON_H_INC
|
|
@ -115,39 +115,6 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyValue(const glTF::vec4& v, aiColor4D& out) {
|
|
||||||
out.r = v[0];
|
|
||||||
out.g = v[1];
|
|
||||||
out.b = v[2];
|
|
||||||
out.a = v[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CopyValue(const glTF::vec4& v, aiColor3D& out) {
|
|
||||||
out.r = v[0];
|
|
||||||
out.g = v[1];
|
|
||||||
out.b = v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CopyValue(const glTF::vec3& v, aiVector3D& out) {
|
|
||||||
out.x = v[0];
|
|
||||||
out.y = v[1];
|
|
||||||
out.z = v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CopyValue(const glTF::vec4& v, aiQuaternion& out) {
|
|
||||||
out.x = v[0];
|
|
||||||
out.y = v[1];
|
|
||||||
out.z = v[2];
|
|
||||||
out.w = v[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o) {
|
|
||||||
o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
|
|
||||||
o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
|
|
||||||
o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
|
|
||||||
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat,
|
void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat,
|
||||||
aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) {
|
aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) {
|
||||||
|
|
|
@ -95,38 +95,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <assimp/StringUtils.h>
|
#include <assimp/StringUtils.h>
|
||||||
|
|
||||||
|
#include "glTF/glTFCommon.h"
|
||||||
|
|
||||||
namespace glTF2
|
namespace glTF2
|
||||||
{
|
{
|
||||||
#ifdef ASSIMP_API
|
using glTFCommon::shared_ptr;
|
||||||
using Assimp::IOStream;
|
using glTFCommon::IOSystem;
|
||||||
using Assimp::IOSystem;
|
using glTFCommon::IOStream;
|
||||||
using std::shared_ptr;
|
|
||||||
#else
|
|
||||||
using std::shared_ptr;
|
|
||||||
|
|
||||||
typedef std::runtime_error DeadlyImportError;
|
|
||||||
typedef std::runtime_error DeadlyExportError;
|
|
||||||
|
|
||||||
enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 };
|
|
||||||
class IOSystem;
|
|
||||||
class IOStream
|
|
||||||
{
|
|
||||||
FILE* f;
|
|
||||||
public:
|
|
||||||
IOStream(FILE* file) : f(file) {}
|
|
||||||
~IOStream() { fclose(f); f = 0; }
|
|
||||||
|
|
||||||
size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
|
|
||||||
size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
|
|
||||||
int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
|
|
||||||
size_t Tell() const { return ftell(f); }
|
|
||||||
|
|
||||||
size_t FileSize() {
|
|
||||||
long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
|
|
||||||
return size_t((Seek(p, aiOrigin_SET), len));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using rapidjson::Value;
|
using rapidjson::Value;
|
||||||
using rapidjson::Document;
|
using rapidjson::Document;
|
||||||
|
@ -138,35 +113,9 @@ namespace glTF2
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct Skin;
|
struct Skin;
|
||||||
|
|
||||||
// Vec/matrix types, as raw float arrays
|
using glTFCommon::vec3;
|
||||||
typedef float (vec3)[3];
|
using glTFCommon::vec4;
|
||||||
typedef float (vec4)[4];
|
using glTFCommon::mat4;
|
||||||
typedef float (mat4)[16];
|
|
||||||
|
|
||||||
namespace Util
|
|
||||||
{
|
|
||||||
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
|
|
||||||
|
|
||||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
|
||||||
|
|
||||||
inline size_t DecodeBase64(const char* in, uint8_t*& out)
|
|
||||||
{
|
|
||||||
return DecodeBase64(in, strlen(in), out);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DataURI
|
|
||||||
{
|
|
||||||
const char* mediaType;
|
|
||||||
const char* charset;
|
|
||||||
bool base64;
|
|
||||||
const char* data;
|
|
||||||
size_t dataLength;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Check if a uri is a data URI
|
|
||||||
inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! Magic number for GLB files
|
//! Magic number for GLB files
|
||||||
#define AI_GLB_MAGIC_NUMBER "glTF"
|
#define AI_GLB_MAGIC_NUMBER "glTF"
|
||||||
|
@ -552,7 +501,7 @@ namespace glTF2
|
||||||
/// but in real life you'll get:
|
/// but in real life you'll get:
|
||||||
/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
|
/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
|
||||||
/// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
|
/// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
|
||||||
/// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
|
/// And when before you start to read data of current mesh (with encoded data of course) you must decode region of "bufferView", after read finished
|
||||||
/// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
|
/// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
|
||||||
///
|
///
|
||||||
/// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
|
/// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
|
||||||
|
|
|
@ -282,9 +282,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
|
||||||
template<class T>
|
template<class T>
|
||||||
Ref<T> LazyDict<T>::Get(unsigned int i)
|
Ref<T> LazyDict<T>::Get(unsigned int i)
|
||||||
{
|
{
|
||||||
|
|
||||||
return Ref<T>(mObjs, i);
|
return Ref<T>(mObjs, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -361,11 +359,11 @@ inline void Buffer::Read(Value& obj, Asset& r)
|
||||||
|
|
||||||
const char* uri = it->GetString();
|
const char* uri = it->GetString();
|
||||||
|
|
||||||
Util::DataURI dataURI;
|
glTFCommon::Util::DataURI dataURI;
|
||||||
if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
|
if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
|
||||||
if (dataURI.base64) {
|
if (dataURI.base64) {
|
||||||
uint8_t* data = 0;
|
uint8_t* data = 0;
|
||||||
this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
|
this->byteLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
|
||||||
this->mData.reset(data, std::default_delete<uint8_t[]>());
|
this->mData.reset(data, std::default_delete<uint8_t[]>());
|
||||||
|
|
||||||
if (statedLength > 0 && this->byteLength != statedLength) {
|
if (statedLength > 0 && this->byteLength != statedLength) {
|
||||||
|
@ -717,12 +715,12 @@ inline void Image::Read(Value& obj, Asset& r)
|
||||||
if (Value* uri = FindString(obj, "uri")) {
|
if (Value* uri = FindString(obj, "uri")) {
|
||||||
const char* uristr = uri->GetString();
|
const char* uristr = uri->GetString();
|
||||||
|
|
||||||
Util::DataURI dataURI;
|
glTFCommon::Util::DataURI dataURI;
|
||||||
if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
|
if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
|
||||||
mimeType = dataURI.mediaType;
|
mimeType = dataURI.mediaType;
|
||||||
if (dataURI.base64) {
|
if (dataURI.base64) {
|
||||||
uint8_t *ptr = nullptr;
|
uint8_t *ptr = nullptr;
|
||||||
mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
|
mDataLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
|
||||||
mData.reset(ptr);
|
mData.reset(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1515,190 +1513,4 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Util {
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
|
|
||||||
if ( NULL == const_uri ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const_uri[0] != 0x10) { // we already parsed this uri?
|
|
||||||
if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set defaults
|
|
||||||
out.mediaType = "text/plain";
|
|
||||||
out.charset = "US-ASCII";
|
|
||||||
out.base64 = false;
|
|
||||||
|
|
||||||
char* uri = const_cast<char*>(const_uri);
|
|
||||||
if (uri[0] != 0x10) {
|
|
||||||
uri[0] = 0x10;
|
|
||||||
uri[1] = uri[2] = uri[3] = uri[4] = 0;
|
|
||||||
|
|
||||||
size_t i = 5, j;
|
|
||||||
if (uri[i] != ';' && uri[i] != ',') { // has media type?
|
|
||||||
uri[1] = char(i);
|
|
||||||
for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
|
||||||
// nothing to do!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (uri[i] == ';' && i < uriLen) {
|
|
||||||
uri[i++] = '\0';
|
|
||||||
for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
|
|
||||||
// nothing to do!
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( strncmp( uri + j, "charset=", 8 ) == 0 ) {
|
|
||||||
uri[2] = char(j + 8);
|
|
||||||
} else if ( strncmp( uri + j, "base64", 6 ) == 0 ) {
|
|
||||||
uri[3] = char(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i < uriLen) {
|
|
||||||
uri[i++] = '\0';
|
|
||||||
uri[4] = char(i);
|
|
||||||
} else {
|
|
||||||
uri[1] = uri[2] = uri[3] = 0;
|
|
||||||
uri[4] = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( uri[ 1 ] != 0 ) {
|
|
||||||
out.mediaType = uri + uri[ 1 ];
|
|
||||||
}
|
|
||||||
if ( uri[ 2 ] != 0 ) {
|
|
||||||
out.charset = uri + uri[ 2 ];
|
|
||||||
}
|
|
||||||
if ( uri[ 3 ] != 0 ) {
|
|
||||||
out.base64 = true;
|
|
||||||
}
|
|
||||||
out.data = uri + uri[4];
|
|
||||||
out.dataLength = (uri + uriLen) - out.data;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool B>
|
|
||||||
struct DATA
|
|
||||||
{
|
|
||||||
static const uint8_t tableDecodeBase64[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
template<bool B>
|
|
||||||
const uint8_t DATA<B>::tableDecodeBase64[128] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
|
|
||||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
|
||||||
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
inline char EncodeCharBase64(uint8_t b)
|
|
||||||
{
|
|
||||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t DecodeCharBase64(char c)
|
|
||||||
{
|
|
||||||
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; // '-' */
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
|
|
||||||
{
|
|
||||||
ai_assert(inLength % 4 == 0);
|
|
||||||
|
|
||||||
if (inLength < 4) {
|
|
||||||
out = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nEquals = int(in[inLength - 1] == '=') +
|
|
||||||
int(in[inLength - 2] == '=');
|
|
||||||
|
|
||||||
size_t outLength = (inLength * 3) / 4 - nEquals;
|
|
||||||
out = new uint8_t[outLength];
|
|
||||||
memset(out, 0, outLength);
|
|
||||||
|
|
||||||
size_t i, j = 0;
|
|
||||||
|
|
||||||
for (i = 0; i + 4 < inLength; i += 4) {
|
|
||||||
uint8_t b0 = DecodeCharBase64(in[i]);
|
|
||||||
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
|
||||||
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
|
||||||
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
|
||||||
|
|
||||||
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
|
||||||
out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
|
||||||
out[j++] = (uint8_t)((b2 << 6) | b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t b0 = DecodeCharBase64(in[i]);
|
|
||||||
uint8_t b1 = DecodeCharBase64(in[i + 1]);
|
|
||||||
uint8_t b2 = DecodeCharBase64(in[i + 2]);
|
|
||||||
uint8_t b3 = DecodeCharBase64(in[i + 3]);
|
|
||||||
|
|
||||||
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
|
||||||
if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
|
||||||
if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void EncodeBase64(
|
|
||||||
const uint8_t* in, size_t inLength,
|
|
||||||
std::string& out)
|
|
||||||
{
|
|
||||||
size_t outLength = ((inLength + 2) / 3) * 4;
|
|
||||||
|
|
||||||
size_t j = out.size();
|
|
||||||
out.resize(j + outLength);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < inLength; i += 3) {
|
|
||||||
uint8_t b = (in[i] & 0xFC) >> 2;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = (in[i] & 0x03) << 4;
|
|
||||||
if (i + 1 < inLength) {
|
|
||||||
b |= (in[i + 1] & 0xF0) >> 4;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = (in[i + 1] & 0x0F) << 2;
|
|
||||||
if (i + 2 < inLength) {
|
|
||||||
b |= (in[i + 2] & 0xC0) >> 6;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
|
|
||||||
b = in[i + 2] & 0x3F;
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
out[j++] = '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out[j++] = EncodeCharBase64(b);
|
|
||||||
out[j++] = '=';
|
|
||||||
out[j++] = '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // ns glTF
|
} // ns glTF
|
||||||
|
|
|
@ -218,7 +218,7 @@ namespace glTF2 {
|
||||||
if (img.HasData()) {
|
if (img.HasData()) {
|
||||||
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
|
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
|
||||||
uri += ";base64,";
|
uri += ";base64,";
|
||||||
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
|
glTFCommon::Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uri = img.uri;
|
uri = img.uri;
|
||||||
|
|
|
@ -64,6 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
using namespace glTF2;
|
using namespace glTF2;
|
||||||
|
using namespace glTFCommon;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// generate bi-tangents from normals and tangents according to spec
|
// generate bi-tangents from normals and tangents according to spec
|
||||||
|
@ -140,22 +141,23 @@ static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
|
/*static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
|
||||||
{
|
{
|
||||||
out.r = v[0]; out.g = v[1]; out.b = v[2];
|
out.r = v[0]; out.g = v[1]; out.b = v[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
|
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
|
||||||
{
|
{
|
||||||
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
|
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
|
/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
|
||||||
{
|
{
|
||||||
out.r = v[0]; out.g = v[1]; out.b = v[2];
|
out.r = v[0]; out.g = v[1]; out.b = v[2];
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
|
/*static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
|
||||||
{
|
{
|
||||||
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
|
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
|
||||||
}
|
}
|
||||||
|
@ -168,15 +170,15 @@ static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
|
||||||
static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
|
static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
|
||||||
{
|
{
|
||||||
out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
|
out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
|
/*static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
|
||||||
{
|
{
|
||||||
o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
|
o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
|
||||||
o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
|
o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
|
||||||
o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
|
o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -188,7 +190,7 @@ inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat,
|
||||||
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;
|
||||||
CopyValue(prop, col);
|
glTFCommon::CopyValue(prop, col);
|
||||||
mat->AddProperty(&col, 1, pKey, type, idx);
|
mat->AddProperty(&col, 1, pKey, type, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,7 +989,12 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnimationSamplers {
|
struct AnimationSamplers {
|
||||||
AnimationSamplers() : translation(nullptr), rotation(nullptr), scale(nullptr) {}
|
AnimationSamplers()
|
||||||
|
: translation(nullptr)
|
||||||
|
, rotation(nullptr)
|
||||||
|
, scale(nullptr) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
Animation::Sampler* translation;
|
Animation::Sampler* translation;
|
||||||
Animation::Sampler* rotation;
|
Animation::Sampler* rotation;
|
||||||
|
|
Loading…
Reference in New Issue