mData)
+ if (!acc->mData) {
acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource);
+ }
}
// For continued primitives, the given count does not come all in one , but only one primitive per
@@ -1884,11 +1886,13 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n
ai_assert((baseOffset + numOffsets - 1) < indices.size());
// extract per-vertex channels using the global per-vertex offset
- for (std::vector::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it)
+ for (std::vector::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
+ }
// and extract per-index channels using there specified offset
- for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
+ for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
+ }
// store the vertex-data index for later assignment of bone vertex weights
pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
@@ -1912,8 +1916,9 @@ void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset,
// Extracts a single object from an input channel and stores it in the appropriate mesh data array
void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh &pMesh) {
// ignore vertex referrer - we handle them that separate
- if (pInput.mType == IT_Vertex)
+ if (pInput.mType == IT_Vertex) {
return;
+ }
const Accessor &acc = *pInput.mResolved;
if (pLocalIndex >= acc.mCount) {
@@ -1926,86 +1931,93 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
// assemble according to the accessors component sub-offset list. We don't care, yet,
// what kind of object exactly we're extracting here
ai_real obj[4];
- for (size_t c = 0; c < 4; ++c)
+ for (size_t c = 0; c < 4; ++c) {
obj[c] = dataObject[acc.mSubOffset[c]];
+ }
// now we reinterpret it according to the type we're reading here
switch (pInput.mType) {
- case IT_Position: // ignore all position streams except 0 - there can be only one position
- if (pInput.mIndex == 0)
- pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
- else
- ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
- break;
- case IT_Normal:
- // pad to current vertex count if necessary
- if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
- pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
-
- // ignore all normal streams except 0 - there can be only one normal
- if (pInput.mIndex == 0)
- pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
- else
- ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
- break;
- case IT_Tangent:
- // pad to current vertex count if necessary
- if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
- pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
-
- // ignore all tangent streams except 0 - there can be only one tangent
- if (pInput.mIndex == 0)
- pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
- else
- ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
- break;
- case IT_Bitangent:
- // pad to current vertex count if necessary
- if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1)
- pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
-
- // ignore all bitangent streams except 0 - there can be only one bitangent
- if (pInput.mIndex == 0)
- pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
- else
- ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
- break;
- case IT_Texcoord:
- // up to 4 texture coord sets are fine, ignore the others
- if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
- // pad to current vertex count if necessary
- if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
- pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
- pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
-
- pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
- if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
- pMesh.mNumUVComponents[pInput.mIndex] = 3;
- } else {
- ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
- }
- break;
- case IT_Color:
- // up to 4 color sets are fine, ignore the others
- if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
- // pad to current vertex count if necessary
- if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
- pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
- pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
-
- aiColor4D result(0, 0, 0, 1);
- for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
- result[static_cast(i)] = obj[pInput.mResolved->mSubOffset[i]];
+ case IT_Position: // ignore all position streams except 0 - there can be only one position
+ if (pInput.mIndex == 0) {
+ pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+ } else {
+ ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
}
- pMesh.mColors[pInput.mIndex].push_back(result);
- } else {
- ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
- }
+ break;
+ case IT_Normal:
+ // pad to current vertex count if necessary
+ if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
+ pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
- break;
- default:
- // IT_Invalid and IT_Vertex
- ai_assert(false && "shouldn't ever get here");
+ // ignore all normal streams except 0 - there can be only one normal
+ if (pInput.mIndex == 0) {
+ pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+ } else {
+ ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
+ }
+ break;
+ case IT_Tangent:
+ // pad to current vertex count if necessary
+ if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
+ pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
+
+ // ignore all tangent streams except 0 - there can be only one tangent
+ if (pInput.mIndex == 0) {
+ pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+ } else {
+ ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
+ }
+ break;
+ case IT_Bitangent:
+ // pad to current vertex count if necessary
+ if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
+ pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
+ }
+
+ // ignore all bitangent streams except 0 - there can be only one bitangent
+ if (pInput.mIndex == 0) {
+ pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+ } else {
+ ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
+ }
+ break;
+ case IT_Texcoord:
+ // up to 4 texture coord sets are fine, ignore the others
+ if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+ // pad to current vertex count if necessary
+ if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
+ pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
+ pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
+
+ pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
+ if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
+ pMesh.mNumUVComponents[pInput.mIndex] = 3;
+ }
+ } else {
+ ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
+ }
+ break;
+ case IT_Color:
+ // up to 4 color sets are fine, ignore the others
+ if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
+ // pad to current vertex count if necessary
+ if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
+ pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
+ pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
+
+ aiColor4D result(0, 0, 0, 1);
+ for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
+ result[static_cast(i)] = obj[pInput.mResolved->mSubOffset[i]];
+ }
+ pMesh.mColors[pInput.mIndex].push_back(result);
+ } else {
+ ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
+ }
+
+ break;
+ default:
+ // IT_Invalid and IT_Vertex
+ ai_assert(false && "shouldn't ever get here");
}
}
diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp
index 9fe4ce5be..6997388b8 100644
--- a/code/AssetLib/FBX/FBXMaterial.cpp
+++ b/code/AssetLib/FBX/FBXMaterial.cpp
@@ -54,18 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
#include
-#include // std::transform
#include "FBXUtil.h"
namespace Assimp {
namespace FBX {
- using namespace Util;
+using namespace Util;
// ------------------------------------------------------------------------------------------------
-Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-{
+Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
+ Object(id,element,name) {
const Scope& sc = GetRequiredScope(element);
const Element* const ShadingModel = sc["ShadingModel"];
@@ -77,23 +75,21 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
if(ShadingModel) {
shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0));
- }
- else {
+ } else {
DOMWarning("shading mode not specified, assuming phong",&element);
shading = "phong";
}
- std::string templateName;
-
// lower-case shading because Blender (for example) writes "Phong"
- std::transform(shading.data(), shading.data() + shading.size(), std::addressof(shading[0]), Assimp::ToLower);
+ for (size_t i = 0; i < shading.length(); ++i) {
+ shading[i] = static_cast(tolower(shading[i]));
+ }
+ std::string templateName;
if(shading == "phong") {
templateName = "Material.FbxSurfacePhong";
- }
- else if(shading == "lambert") {
+ } else if(shading == "lambert") {
templateName = "Material.FbxSurfaceLambert";
- }
- else {
+ } else {
DOMWarning("shading mode not recognized: " + shading,&element);
}
@@ -102,20 +98,19 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
// resolve texture links
const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID());
for(const Connection* con : conns) {
-
// texture link to properties, not objects
- if (!con->PropertyName().length()) {
+ if ( 0 == con->PropertyName().length()) {
continue;
}
const Object* const ob = con->SourceObject();
- if(!ob) {
+ if(nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element);
continue;
}
const Texture* const tex = dynamic_cast(ob);
- if(!tex) {
+ if(nullptr == tex) {
const LayeredTexture* const layeredTexture = dynamic_cast(ob);
if(!layeredTexture) {
DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
@@ -128,9 +123,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
layeredTextures[prop] = layeredTexture;
((LayeredTexture*)layeredTexture)->fillTexture(doc);
- }
- else
- {
+ } else {
const std::string& prop = con->PropertyName();
if (textures.find(prop) != textures.end()) {
DOMWarning("duplicate texture link: " + prop,&element);
@@ -138,23 +131,20 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
textures[prop] = tex;
}
-
}
}
// ------------------------------------------------------------------------------------------------
-Material::~Material()
-{
+Material::~Material() {
+ // empty
}
-
// ------------------------------------------------------------------------------------------------
-Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, uvScaling(1.0f,1.0f)
-, media(0)
-{
+Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
+ Object(id,element,name),
+ uvScaling(1.0f,1.0f),
+ media(0) {
const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"];
@@ -194,8 +184,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1));
crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2));
crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3));
- }
- else {
+ } else {
// vc8 doesn't support the crop() syntax in initialization lists
// (and vc9 WARNS about the new (i.e. compliant) behaviour).
crop[0] = crop[1] = crop[2] = crop[3] = 0;
@@ -226,7 +215,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID());
for(const Connection* con : conns) {
const Object* const ob = con->SourceObject();
- if(!ob) {
+ if (nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element);
continue;
}
@@ -240,46 +229,38 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
}
-Texture::~Texture()
-{
-
+Texture::~Texture() {
+ // empty
}
-LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
-: Object(id,element,name)
-,blendMode(BlendMode_Modulate)
-,alpha(1)
-{
+LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) :
+ Object(id,element,name),
+ blendMode(BlendMode_Modulate),
+ alpha(1) {
const Scope& sc = GetRequiredScope(element);
const Element* const BlendModes = sc["BlendModes"];
const Element* const Alphas = sc["Alphas"];
-
- if(BlendModes!=0)
- {
+ if (nullptr != BlendModes) {
blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
}
- if(Alphas!=0)
- {
+ if (nullptr != Alphas) {
alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
}
}
-LayeredTexture::~LayeredTexture()
-{
-
+LayeredTexture::~LayeredTexture() {
+ // empty
}
-void LayeredTexture::fillTexture(const Document& doc)
-{
+void LayeredTexture::fillTexture(const Document& doc) {
const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID());
- for(size_t i = 0; i < conns.size();++i)
- {
+ for(size_t i = 0; i < conns.size();++i) {
const Connection* con = conns.at(i);
const Object* const ob = con->SourceObject();
- if(!ob) {
+ if (nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element);
continue;
}
@@ -290,13 +271,11 @@ void LayeredTexture::fillTexture(const Document& doc)
}
}
-
// ------------------------------------------------------------------------------------------------
-Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, contentLength(0)
-, content(0)
-{
+Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
+ Object(id,element,name),
+ contentLength(0),
+ content(0) {
const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"];
@@ -324,52 +303,43 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
if (!token.IsBinary()) {
if (*data != '"') {
DOMError("embedded content is not surrounded by quotation marks", &element);
- }
- else {
+ } else {
size_t targetLength = 0;
auto numTokens = Content->Tokens().size();
// First time compute size (it could be large like 64Gb and it is good to allocate it once)
- for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
- {
+ for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) {
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1;
const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
- if (outLength == 0)
- {
+ if (outLength == 0) {
DOMError("Corrupted embedded content found", &element);
}
targetLength += outLength;
}
- if (targetLength == 0)
- {
+ if (targetLength == 0) {
DOMError("Corrupted embedded content found", &element);
}
content = new uint8_t[targetLength];
contentLength = static_cast(targetLength);
size_t dst_offset = 0;
- for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
- {
+ for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) {
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1;
dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
}
- if (targetLength != dst_offset)
- {
+ if (targetLength != dst_offset) {
delete[] content;
contentLength = 0;
DOMError("Corrupted embedded content found", &element);
}
}
- }
- else if (static_cast(token.end() - data) < 5) {
+ } else if (static_cast(token.end() - data) < 5) {
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
- }
- else if (*data != 'R') {
+ } else if (*data != 'R') {
DOMWarning("video content is not raw binary data, ignoring", &element);
- }
- else {
+ } else {
// read number of elements
uint32_t len = 0;
::memcpy(&len, data + 1, sizeof(len));
@@ -380,8 +350,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
content = new uint8_t[len];
::memcpy(content, data + 5, len);
}
- } catch (const runtime_error& runtimeError)
- {
+ } catch (const runtime_error& runtimeError) {
//we don't need the content data for contents that has already been loaded
ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
runtimeError.what());
@@ -392,14 +361,11 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
}
-Video::~Video()
-{
- if(content) {
- delete[] content;
- }
+Video::~Video() {
+ delete[] content;
}
} //!FBX
} //!Assimp
-#endif
+#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
diff --git a/code/AssetLib/IFC/IFCGeometry.cpp b/code/AssetLib/IFC/IFCGeometry.cpp
index 7e8a06bbb..d6d069fc4 100644
--- a/code/AssetLib/IFC/IFCGeometry.cpp
+++ b/code/AssetLib/IFC/IFCGeometry.cpp
@@ -656,7 +656,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
}
}
- if( openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings)) ) {
+ if( openings && (sides_with_openings == 1 || sides_with_v_openings == 2 ) ) {
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
}
diff --git a/code/AssetLib/IFC/IFCOpenings.cpp b/code/AssetLib/IFC/IFCOpenings.cpp
index e15691957..4bf74c0d3 100644
--- a/code/AssetLib/IFC/IFCOpenings.cpp
+++ b/code/AssetLib/IFC/IFCOpenings.cpp
@@ -1189,20 +1189,9 @@ bool GenerateOpenings(std::vector& openings,
TempMesh* profile_data = opening.profileMesh.get();
bool is_2d_source = false;
if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
-
- if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
- // horizontal extrusion
- if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- profile_data = opening.profileMesh2D.get();
- is_2d_source = true;
- }
- }
- else {
- // vertical extrusion
- if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- profile_data = opening.profileMesh2D.get();
- is_2d_source = true;
- }
+ if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
+ profile_data = opening.profileMesh2D.get();
+ is_2d_source = true;
}
}
std::vector profile_verts = profile_data->mVerts;
diff --git a/code/AssetLib/M3D/m3d.h b/code/AssetLib/M3D/m3d.h
index c25c633ba..dfc30aec3 100644
--- a/code/AssetLib/M3D/m3d.h
+++ b/code/AssetLib/M3D/m3d.h
@@ -1642,7 +1642,7 @@ static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette
static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) {
unsigned char palette[1024], pal_img_n = 0;
unsigned char has_trans = 0, tc[3] = {};
- _m3dstbi__uint16 tc16[3];
+ _m3dstbi__uint16 tc16[3] = {};
_m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
int first = 1, k, interlace = 0, color = 0;
_m3dstbi__context *s = z->s;
diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp
index 283735912..bf1b70c90 100644
--- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp
+++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp
@@ -122,8 +122,8 @@ void ObjFileMtlImporter::load() {
{
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient);
- } else if (*m_DataIt == 'd') // Diffuse color
- {
+ } else if (*m_DataIt == 'd') {
+ // Diffuse color
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse);
} else if (*m_DataIt == 's') {
@@ -144,7 +144,9 @@ void ObjFileMtlImporter::load() {
} else if (*m_DataIt == 'r') {
// Material transmission alpha value
++m_DataIt;
- getFloatValue(m_pModel->m_pCurrentMaterial->alpha);
+ ai_real d;
+ getFloatValue(d);
+ m_pModel->m_pCurrentMaterial->alpha = static_cast(1.0) - d;
}
m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine);
} break;
diff --git a/code/AssetLib/STL/STLExporter.cpp b/code/AssetLib/STL/STLExporter.cpp
index fd4c41033..890ee166f 100644
--- a/code/AssetLib/STL/STLExporter.cpp
+++ b/code/AssetLib/STL/STLExporter.cpp
@@ -147,7 +147,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
WriteMesh(pScene->mMeshes[ i ]);
}
- mOutput << EndSolidToken << name << endl;
+ mOutput << EndSolidToken << " " << name << endl;
}
}
diff --git a/code/AssetLib/glTF/glTFCommon.cpp b/code/AssetLib/glTF/glTFCommon.cpp
index 01ba31209..8a4b8927d 100644
--- a/code/AssetLib/glTF/glTFCommon.cpp
+++ b/code/AssetLib/glTF/glTFCommon.cpp
@@ -54,7 +54,7 @@ size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out) {
}
if (inLength < 4) {
- out = 0;
+ out = nullptr;
return 0;
}
diff --git a/code/AssetLib/glTF/glTFCommon.h b/code/AssetLib/glTF/glTFCommon.h
index 6d402b0e3..cd5b552f5 100644
--- a/code/AssetLib/glTF/glTFCommon.h
+++ b/code/AssetLib/glTF/glTFCommon.h
@@ -107,7 +107,6 @@ public:
f(file) {}
~IOStream() {
fclose(f);
- f = 0;
}
size_t Read(void *b, size_t sz, size_t n) { return fread(b, sz, n, f); }
diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h
index 94cbef2cd..95bd5ad4b 100644
--- a/code/AssetLib/glTF2/glTF2Asset.h
+++ b/code/AssetLib/glTF2/glTF2Asset.h
@@ -376,87 +376,6 @@ struct Object {
// Classes for each glTF top-level object type
//
-//! A typed view into a BufferView. A BufferView contains raw binary data.
-//! An accessor provides a typed view into a BufferView or a subset of a BufferView
-//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
-struct Accessor : public Object {
- struct Sparse;
-
- Ref bufferView; //!< The ID of the bufferView. (required)
- size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
- ComponentType componentType; //!< The datatype of components in the attribute. (required)
- size_t count; //!< The number of attributes referenced by this accessor. (required)
- AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
- std::vector max; //!< Maximum value of each component in this attribute.
- std::vector min; //!< Minimum value of each component in this attribute.
- std::unique_ptr sparse;
-
- unsigned int GetNumComponents();
- unsigned int GetBytesPerComponent();
- unsigned int GetElementSize();
-
- inline uint8_t *GetPointer();
-
- template
- void ExtractData(T *&outData);
-
- void WriteData(size_t count, const void *src_buffer, size_t src_stride);
- void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
- void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride);
-
- //! Helper class to iterate the data
- class Indexer {
- friend struct Accessor;
-
- // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
- // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
- protected:
- Accessor &accessor;
-
- private:
- uint8_t *data;
- size_t elemSize, stride;
-
- Indexer(Accessor &acc);
-
- public:
- //! Accesses the i-th value as defined by the accessor
- template
- T GetValue(int i);
-
- //! Accesses the i-th value as defined by the accessor
- inline unsigned int GetUInt(int i) {
- return GetValue(i);
- }
-
- inline bool IsValid() const {
- return data != 0;
- }
- };
-
- inline Indexer GetIndexer() {
- return Indexer(*this);
- }
-
- Accessor() {}
- void Read(Value &obj, Asset &r);
-
- //sparse
- struct Sparse {
- size_t count;
- ComponentType indicesType;
- Ref indices;
- size_t indicesByteOffset;
- Ref values;
- size_t valuesByteOffset;
-
- std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it.
-
- void PopulateData(size_t numBytes, uint8_t *bytes);
- void PatchData(unsigned int elementSize);
- };
-};
-
//! A buffer points to binary geometry, animation, or skins.
struct Buffer : public Object {
/********************* Types *********************/
@@ -594,6 +513,90 @@ struct BufferView : public Object {
uint8_t *GetPointer(size_t accOffset);
};
+//! A typed view into a BufferView. A BufferView contains raw binary data.
+//! An accessor provides a typed view into a BufferView or a subset of a BufferView
+//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
+struct Accessor : public Object {
+ struct Sparse;
+
+ Ref bufferView; //!< The ID of the bufferView. (required)
+ size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
+ ComponentType componentType; //!< The datatype of components in the attribute. (required)
+ size_t count; //!< The number of attributes referenced by this accessor. (required)
+ AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
+ std::vector max; //!< Maximum value of each component in this attribute.
+ std::vector min; //!< Minimum value of each component in this attribute.
+ std::unique_ptr sparse;
+ std::unique_ptr decodedBuffer; // Packed decoded data, returned instead of original bufferView if present
+
+ unsigned int GetNumComponents();
+ unsigned int GetBytesPerComponent();
+ unsigned int GetElementSize();
+
+ inline uint8_t *GetPointer();
+ inline size_t GetStride();
+ inline size_t GetMaxByteSize();
+
+ template
+ void ExtractData(T *&outData);
+
+ void WriteData(size_t count, const void *src_buffer, size_t src_stride);
+ void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
+ void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride);
+
+ //! Helper class to iterate the data
+ class Indexer {
+ friend struct Accessor;
+
+ // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
+ // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
+ protected:
+ Accessor &accessor;
+
+ private:
+ uint8_t *data;
+ size_t elemSize, stride;
+
+ Indexer(Accessor &acc);
+
+ public:
+ //! Accesses the i-th value as defined by the accessor
+ template
+ T GetValue(int i);
+
+ //! Accesses the i-th value as defined by the accessor
+ inline unsigned int GetUInt(int i) {
+ return GetValue(i);
+ }
+
+ inline bool IsValid() const {
+ return data != nullptr;
+ }
+ };
+
+ inline Indexer GetIndexer() {
+ return Indexer(*this);
+ }
+
+ Accessor() {}
+ void Read(Value &obj, Asset &r);
+
+ //sparse
+ struct Sparse {
+ size_t count;
+ ComponentType indicesType;
+ Ref indices;
+ size_t indicesByteOffset;
+ Ref values;
+ size_t valuesByteOffset;
+
+ std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it.
+
+ void PopulateData(size_t numBytes, uint8_t *bytes);
+ void PatchData(unsigned int elementSize);
+ };
+};
+
struct Camera : public Object {
enum Type {
Perspective,
@@ -846,7 +849,7 @@ struct CustomExtension : public Object {
CustomExtension() = default;
- CustomExtension(const CustomExtension& other)
+ CustomExtension(const CustomExtension &other)
: Object(other)
, mStringValue(other.mStringValue)
, mDoubleValue(other.mDoubleValue)
@@ -1092,6 +1095,7 @@ public:
bool KHR_materials_sheen;
bool KHR_materials_clearcoat;
bool KHR_materials_transmission;
+ bool KHR_draco_mesh_compression;
} extensionsUsed;
//! Keeps info about the required extensions
@@ -1100,7 +1104,7 @@ public:
} extensionsRequired;
AssetMetadata asset;
- Value* extras = nullptr;
+ Value *extras = nullptr;
// Dictionaries for each type of object
@@ -1122,7 +1126,7 @@ public:
Ref scene;
public:
- Asset(IOSystem *io = 0) :
+ Asset(IOSystem *io = nullptr) :
mIOSystem(io),
asset(),
accessors(*this, "accessors"),
diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl
index 0e265efef..b234fd0bf 100644
--- a/code/AssetLib/glTF2/glTF2Asset.inl
+++ b/code/AssetLib/glTF2/glTF2Asset.inl
@@ -42,9 +42,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssetLib/glTF/glTFCommon.h"
+#include
#include
#include
-#include
+
+#ifdef ASSIMP_ENABLE_DRACO
+
+// Google draco library headers spew many warnings. Bad Google, no cookie
+#if _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4018) // Signed/unsigned mismatch
+#pragma warning(disable : 4804) // Unsafe use of type 'bool'
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-compare"
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wbool-compare"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#endif
+
+#include "draco/compression/decode.h"
+#include "draco/core/decoder_buffer.h"
+
+#if _MSC_VER
+#pragma warning(pop)
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+#ifndef DRACO_MESH_COMPRESSION_SUPPORTED
+#error glTF: KHR_draco_mesh_compression: draco library must have DRACO_MESH_COMPRESSION_SUPPORTED
+#endif
+#endif
using namespace Assimp;
@@ -146,35 +177,155 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
inline Value *FindMember(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd()) ? &it->value : 0;
+ return (it != val.MemberEnd()) ? &it->value : nullptr;
}
inline Value *FindString(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
+ return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : nullptr;
}
inline Value *FindNumber(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
+ return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : nullptr;
}
inline Value *FindUInt(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd() && it->value.IsUint()) ? &it->value : 0;
+ return (it != val.MemberEnd() && it->value.IsUint()) ? &it->value : nullptr;
}
inline Value *FindArray(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0;
+ return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : nullptr;
}
inline Value *FindObject(Value &val, const char *id) {
Value::MemberIterator it = val.FindMember(id);
- return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0;
+ return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : nullptr;
+}
+
+inline Value *FindExtension(Value &val, const char *extensionId) {
+ if (Value *extensionList = FindObject(val, "extensions")) {
+ if (Value *extension = FindObject(*extensionList, extensionId)) {
+ return extension;
+ }
+ }
+ return nullptr;
}
} // namespace
+#ifdef ASSIMP_ENABLE_DRACO
+
+template
+inline void CopyFaceIndex_Draco(Buffer &decodedIndexBuffer, const draco::Mesh &draco_mesh) {
+ const size_t faceStride = sizeof(T) * 3;
+ for (draco::FaceIndex f(0); f < draco_mesh.num_faces(); ++f) {
+ const draco::Mesh::Face &face = draco_mesh.face(f);
+ T indices[3] = { static_cast(face[0].value()), static_cast(face[1].value()), static_cast(face[2].value()) };
+ memcpy(decodedIndexBuffer.GetPointer() + (f.value() * faceStride), &indices[0], faceStride);
+ }
+}
+
+inline void SetDecodedIndexBuffer_Draco(const draco::Mesh &dracoMesh, Mesh::Primitive &prim) {
+ if (!prim.indices || dracoMesh.num_faces() == 0)
+ return;
+
+ // Create a decoded Index buffer (if there is one)
+ size_t componentBytes = prim.indices->GetBytesPerComponent();
+
+ std::unique_ptr decodedIndexBuffer(new Buffer());
+ decodedIndexBuffer->Grow(dracoMesh.num_faces() * 3 * componentBytes);
+
+ // If accessor uses the same size as draco implementation, copy the draco buffer directly
+
+ // Usually uint32_t but shouldn't assume
+ if (sizeof(dracoMesh.face(draco::FaceIndex(0))[0]) == componentBytes) {
+ memcpy(decodedIndexBuffer->GetPointer(), &dracoMesh.face(draco::FaceIndex(0))[0], decodedIndexBuffer->byteLength);
+ return;
+ }
+
+ // Not same size, convert
+ switch (componentBytes) {
+ case sizeof(uint32_t):
+ CopyFaceIndex_Draco(*decodedIndexBuffer, dracoMesh);
+ break;
+ case sizeof(uint16_t):
+ CopyFaceIndex_Draco(*decodedIndexBuffer, dracoMesh);
+ break;
+ case sizeof(uint8_t):
+ CopyFaceIndex_Draco(*decodedIndexBuffer, dracoMesh);
+ break;
+ default:
+ ai_assert(false);
+ break;
+ }
+
+ // Assign this alternate data buffer to the accessor
+ prim.indices->decodedBuffer.swap(decodedIndexBuffer);
+}
+
+template
+static bool GetAttributeForAllPoints_Draco(const draco::Mesh &dracoMesh,
+ const draco::PointAttribute &dracoAttribute,
+ Buffer &outBuffer) {
+ size_t byteOffset = 0;
+ T values[4] = { 0, 0, 0, 0 };
+ for (draco::PointIndex i(0); i < dracoMesh.num_points(); ++i) {
+ const draco::AttributeValueIndex val_index = dracoAttribute.mapped_index(i);
+ if (!dracoAttribute.ConvertValue(val_index, dracoAttribute.num_components(), values)) {
+ return false;
+ }
+
+ memcpy(outBuffer.GetPointer() + byteOffset, &values[0], sizeof(T) * dracoAttribute.num_components());
+ byteOffset += sizeof(T) * dracoAttribute.num_components();
+ }
+
+ return true;
+}
+
+inline void SetDecodedAttributeBuffer_Draco(const draco::Mesh &dracoMesh, uint32_t dracoAttribId, Accessor &accessor) {
+ // Create decoded buffer
+ const draco::PointAttribute *pDracoAttribute = dracoMesh.GetAttributeByUniqueId(dracoAttribId);
+ if (pDracoAttribute == nullptr) {
+ throw DeadlyImportError("GLTF: Invalid draco attribute id: ", dracoAttribId);
+ }
+
+ size_t componentBytes = accessor.GetBytesPerComponent();
+
+ std::unique_ptr decodedAttribBuffer(new Buffer());
+ decodedAttribBuffer->Grow(dracoMesh.num_points() * pDracoAttribute->num_components() * componentBytes);
+
+ switch (accessor.componentType) {
+ case ComponentType_BYTE:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ case ComponentType_UNSIGNED_BYTE:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ case ComponentType_SHORT:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ case ComponentType_UNSIGNED_SHORT:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ case ComponentType_UNSIGNED_INT:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ case ComponentType_FLOAT:
+ GetAttributeForAllPoints_Draco(dracoMesh, *pDracoAttribute, *decodedAttribBuffer);
+ break;
+ default:
+ ai_assert(false);
+ break;
+ }
+
+ // Assign this alternate data buffer to the accessor
+ accessor.decodedBuffer.swap(decodedAttribBuffer);
+}
+
+#endif // ASSIMP_ENABLE_DRACO
+
//
// LazyDict methods
//
@@ -197,7 +348,7 @@ inline LazyDict::~LazyDict() {
template
inline void LazyDict::AttachToDocument(Document &doc) {
- Value *container = 0;
+ Value *container = nullptr;
if (mExtId) {
if (Value *exts = FindObject(doc, "extensions")) {
@@ -214,7 +365,7 @@ inline void LazyDict::AttachToDocument(Document &doc) {
template
inline void LazyDict::DetachFromDocument() {
- mDict = 0;
+ mDict = nullptr;
}
template
@@ -382,18 +533,18 @@ inline void Buffer::Read(Value &obj, Asset &r) {
glTFCommon::Util::DataURI dataURI;
if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
if (dataURI.base64) {
- uint8_t *data = 0;
+ uint8_t *data = nullptr;
this->byteLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
this->mData.reset(data, std::default_delete());
if (statedLength > 0 && this->byteLength != statedLength) {
throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
- " bytes, but found ", to_string(dataURI.dataLength));
+ " bytes, but found ", to_string(dataURI.dataLength));
}
} else { // assume raw data
if (statedLength != dataURI.dataLength) {
throw DeadlyImportError("GLTF: buffer \"", id, "\", expected ", to_string(statedLength),
- " bytes, but found ", to_string(dataURI.dataLength));
+ " bytes, but found ", to_string(dataURI.dataLength));
}
this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete());
@@ -401,10 +552,7 @@ inline void Buffer::Read(Value &obj, Asset &r) {
}
} else { // Local file
if (byteLength > 0) {
- std::string dir = !r.mCurrentAssetDir.empty() ? (
- r.mCurrentAssetDir.back() == '/' ?
- r.mCurrentAssetDir : r.mCurrentAssetDir + '/'
- ) : "";
+ std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir.back() == '/' ? r.mCurrentAssetDir : r.mCurrentAssetDir + '/') : "";
IOStream *file = r.OpenFile(dir + uri, "rb");
if (file) {
@@ -575,9 +723,9 @@ inline void BufferView::Read(Value &obj, Asset &r) {
}
inline uint8_t *BufferView::GetPointer(size_t accOffset) {
- if (!buffer) return 0;
+ if (!buffer) return nullptr;
uint8_t *basePtr = buffer->GetPointer();
- if (!basePtr) return 0;
+ if (!basePtr) return nullptr;
size_t offset = accOffset + byteOffset;
if (buffer->EncodedRegion_Current != nullptr) {
@@ -709,12 +857,15 @@ inline unsigned int Accessor::GetElementSize() {
}
inline uint8_t *Accessor::GetPointer() {
+ if (decodedBuffer)
+ return decodedBuffer->GetPointer();
+
if (sparse)
return sparse->data.data();
- if (!bufferView || !bufferView->buffer) return 0;
+ if (!bufferView || !bufferView->buffer) return nullptr;
uint8_t *basePtr = bufferView->buffer->GetPointer();
- if (!basePtr) return 0;
+ if (!basePtr) return nullptr;
size_t offset = byteOffset + bufferView->byteOffset;
@@ -730,6 +881,22 @@ inline uint8_t *Accessor::GetPointer() {
return basePtr + offset;
}
+inline size_t Accessor::GetStride() {
+ // Decoded buffer is always packed
+ if (decodedBuffer)
+ return GetElementSize();
+
+ // Sparse and normal bufferView
+ return (bufferView && bufferView->byteStride ? bufferView->byteStride : GetElementSize());
+}
+
+inline size_t Accessor::GetMaxByteSize() {
+ if (decodedBuffer)
+ return decodedBuffer->byteLength;
+
+ return (bufferView ? bufferView->byteLength : sparse->data.size());
+}
+
namespace {
inline void CopyData(size_t count,
const uint8_t *src, size_t src_stride,
@@ -761,7 +928,7 @@ void Accessor::ExtractData(T *&outData) {
const size_t elemSize = GetElementSize();
const size_t totalSize = elemSize * count;
- const size_t stride = bufferView && bufferView->byteStride ? bufferView->byteStride : elemSize;
+ const size_t stride = GetStride();
const size_t targetElemSize = sizeof(T);
@@ -769,8 +936,8 @@ void Accessor::ExtractData(T *&outData) {
throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
}
- const size_t maxSize = (bufferView ? bufferView->byteLength : sparse->data.size());
- if (count*stride > maxSize) {
+ const size_t maxSize = GetMaxByteSize();
+ if (count * stride > maxSize) {
throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
}
@@ -828,14 +995,14 @@ inline Accessor::Indexer::Indexer(Accessor &acc) :
accessor(acc),
data(acc.GetPointer()),
elemSize(acc.GetElementSize()),
- stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) {
+ stride(acc.GetStride()) {
}
//! Accesses the i-th value as defined by the accessor
template
T Accessor::Indexer::GetValue(int i) {
ai_assert(data);
- ai_assert(i * stride < accessor.bufferView->byteLength);
+ ai_assert(i * stride < accessor.GetMaxByteSize());
// Ensure that the memcpy doesn't overwrite the local.
const size_t sizeToCopy = std::min(elemSize, sizeof(T));
T value = T();
@@ -872,8 +1039,7 @@ inline void Image::Read(Value &obj, Asset &r) {
if (Value *mtype = FindString(obj, "mimeType")) {
this->mimeType = mtype->GetString();
}
- if (!this->bufferView || this->mimeType.empty())
- {
+ if (!this->bufferView || this->mimeType.empty()) {
throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " does not have a URI, so it must have a valid bufferView and mimetype");
}
@@ -884,10 +1050,8 @@ inline void Image::Read(Value &obj, Asset &r) {
this->mData.reset(new uint8_t[this->mDataLength]);
memcpy(this->mData.get(), buffer->GetPointer() + this->bufferView->byteOffset, this->mDataLength);
- }
- else
- {
- throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " should have either a URI of a bufferView and mimetype" );
+ } else {
+ throw DeadlyImportError("GLTF2: ", getContextForErrorMessages(id, name), " should have either a URI of a bufferView and mimetype");
}
}
}
@@ -946,28 +1110,26 @@ inline void Texture::Read(Value &obj, Asset &r) {
namespace {
inline void SetTextureProperties(Asset &r, Value *prop, TextureInfo &out) {
if (r.extensionsUsed.KHR_texture_transform) {
- if (Value *extensions = FindObject(*prop, "extensions")) {
+ if (Value *pKHR_texture_transform = FindExtension(*prop, "KHR_texture_transform")) {
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 (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 (!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 *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;
}
}
}
@@ -1043,8 +1205,7 @@ inline void Material::Read(Value &material, Asset &r) {
}
}
- if (r.extensionsUsed.KHR_texture_transform) {
- }
+ // Extension KHR_texture_transform is handled in ReadTextureProperty
if (r.extensionsUsed.KHR_materials_sheen) {
if (Value *curMaterialSheen = FindObject(*extensions, "KHR_materials_sheen")) {
@@ -1106,12 +1267,12 @@ void SetVector(vec3 &v, const float (&in)[3]) {
inline void Material::SetDefaults() {
//pbr materials
SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor);
- pbrMetallicRoughness.metallicFactor = 1.0;
- pbrMetallicRoughness.roughnessFactor = 1.0;
+ pbrMetallicRoughness.metallicFactor = 1.0f;
+ pbrMetallicRoughness.roughnessFactor = 1.0f;
SetVector(emissiveFactor, defaultEmissiveFactor);
alphaMode = "OPAQUE";
- alphaCutoff = 0.5;
+ alphaCutoff = 0.5f;
doubleSided = false;
unlit = false;
}
@@ -1120,7 +1281,7 @@ inline void PbrSpecularGlossiness::SetDefaults() {
//pbrSpecularGlossiness properties
SetVector(diffuseFactor, defaultDiffuseFactor);
SetVector(specularFactor, defaultSpecularFactor);
- glossinessFactor = 1.0;
+ glossinessFactor = 1.0f;
}
inline void MaterialSheen::SetDefaults() {
@@ -1192,6 +1353,14 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
Primitive &prim = this->primitives[i];
prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES);
+ if (Value *indices = FindUInt(primitive, "indices")) {
+ prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
+ }
+
+ if (Value *material = FindUInt(primitive, "material")) {
+ prim.material = pAsset_Root.materials.Retrieve(material->GetUint());
+ }
+
if (Value *attrs = FindObject(primitive, "attributes")) {
for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
if (!it->value.IsUint()) continue;
@@ -1200,11 +1369,12 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
// and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
int undPos = 0;
- Mesh::AccessorList *vec = 0;
+ Mesh::AccessorList *vec = nullptr;
if (GetAttribVector(prim, attr, vec, undPos)) {
size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
if ((*vec).size() != idx) {
- throw DeadlyImportError("GLTF: Invalid attribute: ", attr, ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
+ throw DeadlyImportError("GLTF: Invalid attribute in mesh: ", name, " primitive: ", i, "attrib: ", attr,
+ ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
}
(*vec).resize(idx + 1);
(*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
@@ -1212,6 +1382,69 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
}
}
+#ifdef ASSIMP_ENABLE_DRACO
+ // KHR_draco_mesh_compression spec: Draco can only be used for glTF Triangles or Triangle Strips
+ if (pAsset_Root.extensionsUsed.KHR_draco_mesh_compression && (prim.mode == PrimitiveMode_TRIANGLES || prim.mode == PrimitiveMode_TRIANGLE_STRIP)) {
+ // Look for draco mesh compression extension and bufferView
+ // Skip if any missing
+ if (Value *dracoExt = FindExtension(primitive, "KHR_draco_mesh_compression")) {
+ if (Value *bufView = FindUInt(*dracoExt, "bufferView")) {
+ // Attempt to load indices and attributes using draco compression
+ auto bufferView = pAsset_Root.bufferViews.Retrieve(bufView->GetUint());
+ // Attempt to perform the draco decode on the buffer data
+ const char *bufferViewData = reinterpret_cast(bufferView->buffer->GetPointer() + bufferView->byteOffset);
+ draco::DecoderBuffer decoderBuffer;
+ decoderBuffer.Init(bufferViewData, bufferView->byteLength);
+ draco::Decoder decoder;
+ auto decodeResult = decoder.DecodeMeshFromBuffer(&decoderBuffer);
+ if (!decodeResult.ok()) {
+ // A corrupt Draco isn't actually fatal if the primitive data is also provided in a standard buffer, but does anyone do that?
+ throw DeadlyImportError("GLTF: Invalid Draco mesh compression in mesh: ", name, " primitive: ", i, ": ", decodeResult.status().error_msg_string());
+ }
+
+ // Now we have a draco mesh
+ const std::unique_ptr &pDracoMesh = decodeResult.value();
+
+ // Redirect the accessors to the decoded data
+
+ // Indices
+ SetDecodedIndexBuffer_Draco(*pDracoMesh, prim);
+
+ // Vertex attributes
+ if (Value *attrs = FindObject(*dracoExt, "attributes")) {
+ for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
+ if (!it->value.IsUint()) continue;
+ const char *attr = it->name.GetString();
+
+ int undPos = 0;
+ Mesh::AccessorList *vec = nullptr;
+ if (GetAttribVector(prim, attr, vec, undPos)) {
+ size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
+ if (idx >= (*vec).size()) {
+ throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr,
+ ". All indices for indexed attribute semantics must start with 0 and be continuous positive integers: TEXCOORD_0, TEXCOORD_1, etc.");
+ }
+
+ if (!(*vec)[idx]) {
+ throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr,
+ ". All draco-encoded attributes must also define an accessor.");
+ }
+
+ Accessor &attribAccessor = *(*vec)[idx];
+ if (attribAccessor.count == 0)
+ throw DeadlyImportError("GLTF: Invalid draco attribute in mesh: ", name, " primitive: ", i, " attrib: ", attr);
+
+ // Redirect this accessor to the appropriate Draco vertex attribute data
+ const uint32_t dracoAttribId = it->value.GetUint();
+ SetDecodedAttributeBuffer_Draco(*pDracoMesh, dracoAttribId, attribAccessor);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
Value *targetsArray = FindArray(primitive, "targets");
if (nullptr != targetsArray) {
prim.targets.resize(targetsArray->Size());
@@ -1227,7 +1460,7 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
const char *attr = it->name.GetString();
// Valid attribute semantics include POSITION, NORMAL, TANGENT
int undPos = 0;
- Mesh::AccessorList *vec = 0;
+ Mesh::AccessorList *vec = nullptr;
if (GetAttribTargetVector(prim, j, attr, vec, undPos)) {
size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
if ((*vec).size() <= idx) {
@@ -1238,14 +1471,6 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
}
}
}
-
- if (Value *indices = FindUInt(primitive, "indices")) {
- prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
- }
-
- if (Value *material = FindUInt(primitive, "material")) {
- prim.material = pAsset_Root.materials.Retrieve(material->GetUint());
- }
}
}
@@ -1331,25 +1556,22 @@ inline void Light::Read(Value &obj, Asset & /*r*/) {
}
}
-inline CustomExtension ReadExtensions(const char *name, Value& obj) {
+inline CustomExtension ReadExtensions(const char *name, Value &obj) {
CustomExtension ret;
ret.name = name;
if (obj.IsObject()) {
ret.mValues.isPresent = true;
for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
- auto& val = it->value;
+ auto &val = it->value;
ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val));
}
- }
- else if (obj.IsArray()) {
+ } else if (obj.IsArray()) {
ret.mValues.value.reserve(obj.Size());
ret.mValues.isPresent = true;
- for (unsigned int i = 0; i < obj.Size(); ++i)
- {
+ for (unsigned int i = 0; i < obj.Size(); ++i) {
ret.mValues.value.push_back(ReadExtensions(name, obj[i]));
}
- }
- else if (obj.IsNumber()) {
+ } else if (obj.IsNumber()) {
if (obj.IsUint64()) {
ret.mUint64Value.value = obj.GetUint64();
ret.mUint64Value.isPresent = true;
@@ -1360,12 +1582,10 @@ inline CustomExtension ReadExtensions(const char *name, Value& obj) {
ret.mDoubleValue.value = obj.GetDouble();
ret.mDoubleValue.isPresent = true;
}
- }
- else if (obj.IsString()) {
+ } else if (obj.IsString()) {
ReadValue(obj, ret.mStringValue);
ret.mStringValue.isPresent = true;
- }
- else if (obj.IsBool()) {
+ } else if (obj.IsBool()) {
ret.mBoolValue.value = obj.GetBool();
ret.mBoolValue.isPresent = true;
}
@@ -1411,7 +1631,7 @@ inline void Node::Read(Value &obj, Asset &r) {
}
}
- // Do not retrieve a skin here, just take a reference, to avoid infinite recursion
+ // Do not retrieve a skin here, just take a reference, to avoid infinite recursion
// Skins will be properly loaded later
Value *curSkin = FindUInt(obj, "skin");
if (nullptr != curSkin) {
@@ -1641,7 +1861,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
if (0 != strncmp(pFile.c_str(), AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
mCurrentAssetDir = glTFCommon::getCurrentAssetDir(pFile);
}
-
+
shared_ptr stream(OpenFile(pFile.c_str(), "rb", true));
if (!stream) {
throw DeadlyImportError("GLTF: Could not open file for reading");
@@ -1693,10 +1913,12 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
ReadExtensionsUsed(doc);
ReadExtensionsRequired(doc);
- // Currently Draco is not supported
+#ifndef ASSIMP_ENABLE_DRACO
+ // Is Draco required?
if (extensionsRequired.KHR_draco_mesh_compression) {
- throw DeadlyImportError("GLTF: Draco mesh compression not currently supported.");
+ throw DeadlyImportError("GLTF: Draco mesh compression not supported.");
}
+#endif
// Prepare the dictionaries
for (size_t i = 0; i < mDicts.size(); ++i) {
@@ -1784,6 +2006,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
CHECK_EXT(KHR_materials_sheen);
CHECK_EXT(KHR_materials_clearcoat);
CHECK_EXT(KHR_materials_transmission);
+ CHECK_EXT(KHR_draco_mesh_compression);
#undef CHECK_EXT
}
@@ -1792,12 +2015,12 @@ inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool /*abso
#ifdef ASSIMP_API
return mIOSystem->Open(path, mode);
#else
- if (path.size() < 2) return 0;
+ if (path.size() < 2) return nullptr;
if (!absolute && path[1] != ':' && path[0] != '/') { // relative?
path = mCurrentAssetDir + path;
}
FILE *f = fopen(path.c_str(), mode);
- return f ? new IOStream(f) : 0;
+ return f ? new IOStream(f) : nullptr;
#endif
}
@@ -1831,7 +2054,7 @@ inline std::string Asset::FindUniqueID(const std::string &str, const char *suffi
}
#if _MSC_VER
-# pragma warning(pop)
+#pragma warning(pop)
#endif // _MSC_VER
} // namespace glTF2
diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl
index 65fddaec5..ab30e418a 100644
--- a/code/AssetLib/glTF2/glTF2AssetWriter.inl
+++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl
@@ -571,7 +571,6 @@ namespace glTF2 {
inline void Write(Value& obj, Node& n, AssetWriter& w)
{
-
if (n.matrix.isPresent) {
Value val;
obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl);
@@ -597,14 +596,13 @@ namespace glTF2 {
obj.AddMember("mesh", n.meshes[0]->index, w.mAl);
}
- AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
-
if (n.skin) {
obj.AddMember("skin", n.skin->index, w.mAl);
}
-
- if (!n.jointName.empty()) {
- obj.AddMember("jointName", n.jointName, w.mAl);
+
+ //gltf2 spec does not support "skeletons" under node
+ if(n.skeletons.size()) {
+ AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
}
}
diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp
index 565117ddb..e34125258 100644
--- a/code/AssetLib/glTF2/glTF2Exporter.cpp
+++ b/code/AssetLib/glTF2/glTF2Exporter.cpp
@@ -1095,6 +1095,7 @@ void glTF2Exporter::ExportMeshes()
//----------------------------------------
// Finish the skin
// Create the Accessor for skinRef->inverseBindMatrices
+ bool bAddCustomizedProperty = this->mProperties->HasPropertyBool("GLTF2_CUSTOMIZE_PROPERTY");
if (createSkin) {
mat4* invBindMatrixData = new mat4[inverseBindMatricesData.size()];
for ( unsigned int idx_joint = 0; idx_joint < inverseBindMatricesData.size(); ++idx_joint) {
@@ -1110,7 +1111,7 @@ void glTF2Exporter::ExportMeshes()
// Identity Matrix =====> skinRef->bindShapeMatrix
// Temporary. Hard-coded identity matrix here
- skinRef->bindShapeMatrix.isPresent = true;
+ skinRef->bindShapeMatrix.isPresent = bAddCustomizedProperty;
IdentityMatrix4(skinRef->bindShapeMatrix.value);
// Find nodes that contain a mesh with bones and add "skeletons" and "skin" attributes to those nodes.
@@ -1131,7 +1132,8 @@ void glTF2Exporter::ExportMeshes()
std::string meshID = mesh->id;
FindMeshNode(rootNode, meshNode, meshID);
Ref rootJoint = FindSkeletonRootJoint(skinRef);
- meshNode->skeletons.push_back(rootJoint);
+ if(bAddCustomizedProperty)
+ meshNode->skeletons.push_back(rootJoint);
meshNode->skin = skinRef;
}
delete[] invBindMatrixData;
@@ -1229,7 +1231,7 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent)
node->name = name;
if (!n->mTransformation.IsIdentity()) {
- if (mScene->mNumAnimations > 0) {
+ if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) {
aiQuaternion quaternion;
n->mTransformation.Decompose(*reinterpret_cast(&node->scale.value), quaternion, *reinterpret_cast(&node->translation.value));
@@ -1386,6 +1388,7 @@ void glTF2Exporter::ExportAnimations()
nameAnim = anim->mName.C_Str();
}
Ref animRef = mAsset->animations.Create(nameAnim);
+ animRef->name = nameAnim;
for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) {
const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex];
diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp
index ac3b7144e..78ee446e2 100644
--- a/code/AssetLib/glTF2/glTF2Importer.cpp
+++ b/code/AssetLib/glTF2/glTF2Importer.cpp
@@ -383,6 +383,22 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign
}
#endif // ASSIMP_BUILD_DEBUG
+template
+aiColor4D* GetVertexColorsForType(glTF2::Ref input) {
+ float max = std::numeric_limits::max();
+ aiColor4t* colors;
+ input->ExtractData(colors);
+ auto output = new aiColor4D[input->count];
+ for (size_t i = 0; i < input->count; i++) {
+ output[i] = aiColor4D(
+ colors[i].r / max, colors[i].g / max,
+ colors[i].b / max, colors[i].a / max
+ );
+ }
+ delete[] colors;
+ return output;
+}
+
void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
ASSIMP_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes");
std::vector> meshes;
@@ -436,24 +452,32 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
if (attr.normal.size() > 0 && attr.normal[0]) {
- attr.normal[0]->ExtractData(aim->mNormals);
+ if (attr.normal[0]->count != aim->mNumVertices) {
+ DefaultLogger::get()->warn("Normal count in mesh \"" + mesh.name + "\" does not match the vertex count, normals ignored.");
+ } else {
+ attr.normal[0]->ExtractData(aim->mNormals);
- // only extract tangents if normals are present
- if (attr.tangent.size() > 0 && attr.tangent[0]) {
- // generate bitangents from normals and tangents according to spec
- Tangent *tangents = nullptr;
+ // only extract tangents if normals are present
+ if (attr.tangent.size() > 0 && attr.tangent[0]) {
+ if (attr.tangent[0]->count != aim->mNumVertices) {
+ DefaultLogger::get()->warn("Tangent count in mesh \"" + mesh.name + "\" does not match the vertex count, tangents ignored.");
+ } else {
+ // generate bitangents from normals and tangents according to spec
+ Tangent *tangents = nullptr;
- attr.tangent[0]->ExtractData(tangents);
+ attr.tangent[0]->ExtractData(tangents);
- aim->mTangents = new aiVector3D[aim->mNumVertices];
- aim->mBitangents = new aiVector3D[aim->mNumVertices];
+ aim->mTangents = new aiVector3D[aim->mNumVertices];
+ aim->mBitangents = new aiVector3D[aim->mNumVertices];
- for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
- aim->mTangents[i] = tangents[i].xyz;
- aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w;
+ for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
+ aim->mTangents[i] = tangents[i].xyz;
+ aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w;
+ }
+
+ delete[] tangents;
+ }
}
-
- delete[] tangents;
}
}
@@ -463,7 +487,17 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
"\" does not match the vertex count");
continue;
}
- attr.color[c]->ExtractData(aim->mColors[c]);
+
+ auto componentType = attr.color[c]->componentType;
+ if (componentType == glTF2::ComponentType_FLOAT) {
+ attr.color[c]->ExtractData(aim->mColors[c]);
+ } else {
+ if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
+ aim->mColors[c] = GetVertexColorsForType(attr.color[c]);
+ } else if (componentType == glTF2::ComponentType_UNSIGNED_SHORT) {
+ aim->mColors[c] = GetVertexColorsForType(attr.color[c]);
+ }
+ }
}
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
if (!attr.texcoord[tc]) {
diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt
index bbcad86e5..dc5e0523a 100644
--- a/code/CMakeLists.txt
+++ b/code/CMakeLists.txt
@@ -43,7 +43,7 @@
# 3) Add libassimp using the file lists (eliminates duplication of file names between
# source groups and library command)
#
-cmake_minimum_required( VERSION 3.0 )
+cmake_minimum_required( VERSION 3.10 )
SET( HEADER_PATH ../include/assimp )
if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
@@ -665,6 +665,10 @@ if (NOT ASSIMP_NO_EXPORT)
AssetLib/3MF/D3MFExporter.h
AssetLib/3MF/D3MFExporter.cpp)
+ ADD_ASSIMP_EXPORTER( PBRT
+ Pbrt/PbrtExporter.h
+ Pbrt/PbrtExporter.cpp)
+
ADD_ASSIMP_EXPORTER( ASSJSON
AssetLib/Assjson/cencode.c
AssetLib/Assjson/cencode.h
@@ -1117,6 +1121,11 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
INCLUDE_DIRECTORIES(${C4D_INCLUDES})
ENDIF ()
+IF (ASSIMP_BUILD_DRACO)
+ INCLUDE_DIRECTORIES(${draco_INCLUDE_DIRS})
+ ADD_DEFINITIONS( -DASSIMP_ENABLE_DRACO )
+ENDIF()
+
ADD_LIBRARY( assimp ${assimp_src} )
ADD_LIBRARY(assimp::assimp ALIAS assimp)
@@ -1148,8 +1157,15 @@ IF(ASSIMP_HUNTER_ENABLED)
zip::zip
pugixml
)
+
+ if (ASSIMP_BUILD_DRACO)
+ target_link_libraries(assimp PUBLIC ${draco_LIBRARIES})
+ endif()
ELSE()
- TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
+ TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES})
+ if (ASSIMP_BUILD_DRACO)
+ target_link_libraries(assimp ${draco_LIBRARIES})
+ endif()
ENDIF()
if(ASSIMP_ANDROID_JNIIOSYSTEM)
diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp
index 207b93fc7..5f78a897c 100644
--- a/code/Common/Exporter.cpp
+++ b/code/Common/Exporter.cpp
@@ -138,6 +138,9 @@ void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportPropert
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
#endif
+#ifndef ASSIMP_BUILD_NO_PBRT_EXPORTER
+void ExportScenePbrt(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
static void setupExporterArray(std::vector &exporters) {
(void)exporters;
@@ -221,6 +224,10 @@ static void setupExporterArray(std::vector &exporte
exporters.push_back(Exporter::ExportFormatEntry("3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0));
#endif
+#ifndef ASSIMP_BUILD_NO_PBRT_EXPORTER
+ exporters.push_back(Exporter::ExportFormatEntry("pbrt", "pbrt-v4 scene description file", "pbrt", &ExportScenePbrt, aiProcess_Triangulate | aiProcess_SortByPType));
+#endif
+
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
exporters.push_back(Exporter::ExportFormatEntry("assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0));
#endif
diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp
index 38eb63f40..ccd664d91 100644
--- a/code/Common/Importer.cpp
+++ b/code/Common/Importer.cpp
@@ -78,6 +78,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
#include
+#include
#include
#include
#include
diff --git a/code/Common/Importer.h b/code/Common/Importer.h
index eb70bc38f..d07a67030 100644
--- a/code/Common/Importer.h
+++ b/code/Common/Importer.h
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_IMPORTER_H
#define INCLUDED_AI_IMPORTER_H
+#include
#include