Merge branch 'master' into master

This commit is contained in:
Kim Kulling
2022-08-16 20:53:45 +02:00
committed by GitHub
282 changed files with 11167 additions and 39668 deletions
+1
View File
@@ -262,6 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
unsigned int iWire = 1;
mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
[[fallthrough]];
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
+2 -1
View File
@@ -1284,7 +1284,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
switch (chunk.Flag) {
case Discreet3DS::CHUNK_LINRGBF:
bGamma = true;
// fallthrough
case Discreet3DS::CHUNK_RGBF:
if (sizeof(float) * 3 > diff) {
*out = clrError;
@@ -1297,6 +1297,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
case Discreet3DS::CHUNK_LINRGBB:
bGamma = true;
// fallthrough
case Discreet3DS::CHUNK_RGBB: {
if (sizeof(char) * 3 > diff) {
*out = clrError;
+2
View File
@@ -74,6 +74,8 @@ namespace XmlTag {
const char* const pid = "pid";
const char* const pindex = "pindex";
const char* const p1 = "p1";
const char *const p2 = "p2";
const char *const p3 = "p3";
const char* const name = "name";
const char* const type = "type";
const char* const build = "build";
+3
View File
@@ -186,6 +186,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream);
delete mZipArchive;
for (auto tex : mEmbeddedTextures) {
delete tex;
}
}
IOStream *D3MFOpcPackage::RootStream() const {
+32 -9
View File
@@ -64,7 +64,7 @@ bool validateColorString(const char *color) {
return true;
}
aiFace ReadTriangle(XmlNode &node) {
aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) {
aiFace face;
face.mNumIndices = 3;
@@ -73,6 +73,11 @@ aiFace ReadTriangle(XmlNode &node) {
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
texId0 = texId1 = texId2 = -1;
XmlParser::getIntAttribute(node, XmlTag::p1, texId0);
XmlParser::getIntAttribute(node, XmlTag::p2, texId1);
XmlParser::getIntAttribute(node, XmlTag::p3, texId2);
return face;
}
@@ -106,7 +111,7 @@ bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &va
return false;
}
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
// split the string
std::vector<float> numbers;
std::string currentNumber;
@@ -412,6 +417,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
int texId[3];
Texture2DGroup *group = nullptr;
aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]);
if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) {
@@ -420,23 +428,34 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
if (mesh->mTextureCoords[0] == nullptr) {
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
mesh->mNumUVComponents[0] = 2;
for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
mesh->mNumUVComponents[i] = 0;
}
group = static_cast<Texture2DGroup *>(it->second);
const std::string name = ai_to_string(group->mTexId);
for (size_t i = 0; i < mMaterials.size(); ++i) {
if (name == mMaterials[i]->GetName().C_Str()) {
mesh->mMaterialIndex = static_cast<unsigned int>(i);
}
}
mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
}
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
}
}
}
}
aiFace face = ReadTriangle(currentNode);
// Load texture coordinates into mesh, when any
if (group != nullptr) {
size_t i0 = face.mIndices[0];
size_t i1 = face.mIndices[1];
size_t i2 = face.mIndices[2];
mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f);
mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f);
mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f);
}
faces.push_back(face);
}
}
@@ -578,11 +597,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
}
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
if (nullptr == scene || mMaterials.empty()) {
if (nullptr == scene) {
return;
}
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
if (scene->mNumMaterials == 0) {
return;
}
scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (size_t i = 0; i < mMaterials.size(); ++i) {
scene->mMaterials[i] = mMaterials[i];
+1
View File
@@ -870,6 +870,7 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
unsigned int iWire = 1;
mat.pcInstance->AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
}
// fallthrough
case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud;
break;
+9 -4
View File
@@ -74,7 +74,7 @@ using namespace Assimp::ASE;
return; \
} \
} \
else if ('\0' == *filePtr) { \
if ('\0' == *filePtr) { \
return; \
} \
if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \
@@ -420,6 +420,8 @@ void Parser::ParseLV1SoftSkinBlock() {
}
}
}
if (*filePtr == '\0')
return;
++filePtr;
SkipSpacesAndLineEnd(&filePtr);
}
@@ -646,10 +648,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) {
}
// get a reference to the material
Material &sMat = mat.avSubMaterials[iIndex];
if (iIndex < mat.avSubMaterials.size()) {
Material &sMat = mat.avSubMaterials[iIndex];
// parse the material block
ParseLV2MaterialBlock(sMat);
}
// parse the material block
ParseLV2MaterialBlock(sMat);
continue;
}
}
+1 -1
View File
@@ -365,7 +365,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
ioprintf(io, "\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%u\"",
prop->mKey.data, sz,
::TextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
::aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
if (prop->mType == aiPTI_Float) {
ioprintf(io, " size=\"%i\">\n\t\t\t\t",
+4 -4
View File
@@ -325,10 +325,10 @@ void SectionParser ::Next() {
stream.SetCurrentPos(current.start + current.size);
const char tmp[] = {
(const char)stream.GetI1(),
(const char)stream.GetI1(),
(const char)stream.GetI1(),
(const char)stream.GetI1()
(char)stream.GetI1(),
(char)stream.GetI1(),
(char)stream.GetI1(),
(char)stream.GetI1()
};
current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1);
+2 -2
View File
@@ -281,7 +281,7 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr<Collection> collection, ConversionData &conv_data) {
void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Collection>& collection, ConversionData &conv_data) {
std::deque<Object *> root_objects;
// Count number of objects
@@ -986,7 +986,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
// key is material number, value is the TextureUVMapping for the material
typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
MaterialTextureUVMappings matTexUvMappings;
const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
const uint32_t maxMat = static_cast<uint32_t>(mesh->mat.size());
for (uint32_t m = 0; m < maxMat; ++m) {
// get material by index
const std::shared_ptr<Material> pMat = mesh->mat[m];
+1 -1
View File
@@ -117,7 +117,7 @@ protected:
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr<IOStream> stream);
void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
void ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr<Blender::Collection> collection, Blender::ConversionData &conv_data);
void ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Blender::Collection>& collection, Blender::ConversionData &conv_data);
void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
private:
+5
View File
@@ -621,6 +621,11 @@ struct Animation {
for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
Animation *anim = *it;
// Assign the first animation name to the parent if empty.
// This prevents the animation name from being lost when animations are combined
if (mName.empty()) {
mName = anim->mName;
}
CombineSingleChannelAnimationsRecursively(anim);
if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
+6 -3
View File
@@ -102,6 +102,7 @@ ColladaLoader::ColladaLoader() :
mTextures(),
mAnims(),
noSkeletonMesh(false),
removeEmptyBones(false),
ignoreUpDirection(false),
useColladaName(false),
mNodeNameCounter(0) {
@@ -130,6 +131,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
// ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer *pImp) {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
}
@@ -798,9 +800,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0;
for (const auto & dstBone : dstBones) {
if (!dstBone.empty()) {
++numRemainingBones;
if (dstBone.empty() && removeEmptyBones) {
continue;
}
++numRemainingBones;
}
// create bone array and copy bone weights one by one
@@ -809,7 +812,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
size_t boneCount = 0;
for (size_t a = 0; a < numBones; ++a) {
// omit bones without weights
if (dstBones[a].empty()) {
if (dstBones[a].empty() && removeEmptyBones) {
continue;
}
+1
View File
@@ -237,6 +237,7 @@ protected:
std::vector<aiAnimation *> mAnims;
bool noSkeletonMesh;
bool removeEmptyBones;
bool ignoreUpDirection;
bool useColladaName;
+2 -1
View File
@@ -1616,6 +1616,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str();
vcount.reserve(numPrimitives);
SkipSpacesAndLineEnd(&content);
for (unsigned int a = 0; a < numPrimitives; a++) {
if (*content == 0) {
throw DeadlyImportError("Expected more values while reading <vcount> contents.");
@@ -2057,7 +2058,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
XmlParser::getStdStrAttribute(currentNode, "id", child->mID);
}
if (XmlParser::hasAttribute(currentNode, "sid")) {
XmlParser::getStdStrAttribute(currentNode, "id", child->mSID);
XmlParser::getStdStrAttribute(currentNode, "sid", child->mSID);
}
if (XmlParser::hasAttribute(currentNode, "name")) {
XmlParser::getStdStrAttribute(currentNode, "name", child->mName);
+3 -1
View File
@@ -368,7 +368,9 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
// XXX this would be the place to implement recursive expansion if needed.
const DXF::Block& bl_src = *(*it).second;
for (std::shared_ptr<const DXF::PolyLine> pl_in : bl_src.lines) {
const size_t size = bl_src.lines.size(); // the size may increase in the loop
for (size_t i = 0; i < size; ++i) {
std::shared_ptr<const DXF::PolyLine> pl_in = bl_src.lines[i];
if (!pl_in) {
ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
continue;
-21
View File
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -87,11 +86,6 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::s
}
}
// ------------------------------------------------------------------------------------------------
AnimationCurve::~AnimationCurve() {
// empty
}
// ------------------------------------------------------------------------------------------------
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
@@ -147,11 +141,6 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, cons
props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
}
// ------------------------------------------------------------------------------------------------
AnimationCurveNode::~AnimationCurveNode() {
// empty
}
// ------------------------------------------------------------------------------------------------
const AnimationCurveMap &AnimationCurveNode::Curves() const {
if (curves.empty()) {
@@ -193,11 +182,6 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::s
props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
}
// ------------------------------------------------------------------------------------------------
AnimationLayer::~AnimationLayer() {
// empty
}
// ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
size_t whitelist_size /*= 0*/) const {
@@ -279,11 +263,6 @@ AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::s
}
}
// ------------------------------------------------------------------------------------------------
AnimationStack::~AnimationStack() {
// empty
}
} // namespace FBX
} // namespace Assimp
+1 -1
View File
@@ -472,7 +472,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
}
catch (const DeadlyImportError& e)
{
if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
if (!is64bits && (length > std::numeric_limits<uint32_t>::max())) {
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
}
throw;
+2 -1
View File
@@ -50,7 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
static constexpr size_t NumNullRecords = 25;
const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
'\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'
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
-1
View File
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
+116 -62
View File
@@ -65,12 +65,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <memory>
#include <sstream>
#include <tuple>
#include <vector>
namespace Assimp {
namespace FBX {
@@ -187,8 +184,7 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
/// This struct manages nodes which may or may not end up in the node hierarchy.
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
struct FBXConverter::PotentialNode
{
struct FBXConverter::PotentialNode {
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
aiNode* operator->() { return mNode; }
@@ -231,7 +227,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
if (nullptr != model) {
nodes_chain.clear();
post_nodes_chain.clear();
aiMatrix4x4 new_abs_transform = parent->mTransformation;
std::string node_name = FixNodeName(model->Name());
// even though there is only a single input node, the design of
@@ -266,8 +261,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
child->mParent = last_parent;
last_parent = child.mNode;
new_abs_transform *= child->mTransformation;
}
// attach geometry
@@ -290,8 +283,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
postnode->mParent = last_parent;
last_parent = postnode.mNode;
new_abs_transform *= postnode->mTransformation;
}
} else {
// free the nodes we allocated as we don't need them
@@ -452,7 +443,7 @@ void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueNam
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
unsigned int &i = it_pair.first->second;
while (!it_pair.second) {
i++;
++i;
std::ostringstream ext;
ext << name << std::setfill('0') << std::setw(3) << i;
uniqueName = ext.str();
@@ -651,9 +642,8 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
const PropertyTable &props = model.Props();
bool ok;
const float zero_epsilon = ai_epsilon;
const auto zero_epsilon = ai_epsilon;
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
const TransformationComp comp = static_cast<TransformationComp>(i);
@@ -665,6 +655,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
bool ok = true;
const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
if (ok && scale_compare) {
if ((v - all_ones).SquareLength() > zero_epsilon) {
@@ -899,20 +890,17 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
}
}
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &absolute_transform) {
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
const std::vector<const Geometry *> &geos = model.GetGeometry();
std::vector<unsigned int> meshes;
meshes.reserve(geos.size());
for (const Geometry *geo : geos) {
const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
if (mesh) {
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node,
absolute_transform);
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node, absolute_transform);
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
} else if (line) {
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
@@ -933,8 +921,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
}
std::vector<unsigned int>
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &absolute_transform) {
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
std::vector<unsigned int> temp;
MeshMap::const_iterator it = meshes_converted.find(&mesh);
@@ -957,7 +944,7 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
const MatIndexArray::value_type base = mindices[0];
for (MatIndexArray::value_type index : mindices) {
if (index != base) {
return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform);
return ConvertMeshMultiMaterial(mesh, model, absolute_transform, parent, root_node);
}
}
}
@@ -1031,9 +1018,36 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
return out_mesh;
}
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
const aiMatrix4x4 &absolute_transform, aiNode *parent,
aiNode *) {
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
return nullptr;
}
aiSkeleton *skeleton = new aiSkeleton;
for (auto *mesh : sbc.MeshArray) {
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
continue;
}
SkeletonBoneArray *ba = it->second;
if (ba == nullptr) {
continue;
}
skeleton->mNumBones = static_cast<unsigned int>(ba->size());
skeleton->mBones = new aiSkeletonBone*[skeleton->mNumBones];
size_t index = 0;
for (auto bone : (* ba)) {
skeleton->mBones[index] = bone;
++index;
}
}
return skeleton;
}
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
aiNode *parent, aiNode *) {
const MatIndexArray &mindices = mesh.GetMaterialIndices();
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
@@ -1151,8 +1165,15 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
}
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && !doc.Settings().useSkeleton) {
ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr);
} else if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && doc.Settings().useSkeleton) {
SkeletonBoneContainer sbc;
ConvertWeightsToSkeleton(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr, sbc);
aiSkeleton *skeleton = createAiSkeleton(sbc);
if (skeleton != nullptr) {
mSkeletons.emplace_back(skeleton);
}
}
std::vector<aiAnimMesh *> animMeshes;
@@ -1199,9 +1220,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
}
std::vector<unsigned int>
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
aiNode *root_node,
const aiMatrix4x4 &absolute_transform) {
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent,
aiNode *root_node) {
const MatIndexArray &mindices = mesh.GetMaterialIndices();
ai_assert(mindices.size());
@@ -1211,7 +1231,7 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
for (MatIndexArray::value_type index : mindices) {
if (had.find(index) == had.end()) {
indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform));
indices.push_back(ConvertMeshMultiMaterial(mesh, model, absolute_transform, index, parent, root_node));
had.insert(index);
}
}
@@ -1219,10 +1239,8 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
return indices;
}
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
MatIndexArray::value_type index,
aiNode *parent, aiNode *,
const aiMatrix4x4 &absolute_transform) {
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
MatIndexArray::value_type index, aiNode *parent, aiNode *) {
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
const MatIndexArray &mindices = mesh.GetMaterialIndices();
@@ -1435,20 +1453,47 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
return static_cast<unsigned int>(mMeshes.size() - 1);
}
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
const aiMatrix4x4 &absolute_transform,
static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *skeletonBone ) {
skeletonBone->mNumnWeights = bone->mNumWeights;
skeletonBone->mWeights = bone->mWeights;
skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
skeletonBone->mMeshId = mesh;
skeletonBone->mNode = bone->mNode;
skeletonBone->mParent = -1;
}
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
return;
}
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
skeletonContainer.MeshArray.emplace_back(out);
SkeletonBoneArray *ba = new SkeletonBoneArray;
for (size_t i = 0; i < out->mNumBones; ++i) {
aiBone *bone = out->mBones[i];
if (bone == nullptr) {
continue;
}
aiSkeletonBone *skeletonBone = new aiSkeletonBone;
copyBoneToSkeletonBone(out, bone, skeletonBone);
ba->emplace_back(skeletonBone);
}
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
}
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent, unsigned int materialIndex,
std::vector<unsigned int> *outputVertStartIndices) {
ai_assert(geo.DeformerSkin());
std::vector<size_t> out_indices;
std::vector<size_t> index_out_indices;
std::vector<size_t> count_out_indices;
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
const Skin &sk = *geo.DeformerSkin();
std::vector<aiBone *> bones;
std::vector<aiBone*> bones;
const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
ai_assert(no_mat_check || outputVertStartIndices);
@@ -1521,26 +1566,20 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
out->mBones = nullptr;
out->mNumBones = 0;
return;
} else {
out->mBones = new aiBone *[bones.size()]();
out->mNumBones = static_cast<unsigned int>(bones.size());
}
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
}
out->mBones = new aiBone *[bones.size()]();
out->mNumBones = static_cast<unsigned int>(bones.size());
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
}
const aiNode *GetNodeByName(aiNode *current_node) {
aiNode *iter = current_node;
//printf("Child count: %d", iter->mNumChildren);
return iter;
}
void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const Cluster *cluster,
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
std::vector<size_t> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
aiNode *) {
ai_assert(cl); // make sure cluster valid
std::string deformer_name = cl->TargetNode()->Name();
ai_assert(cluster != nullptr); // make sure cluster valid
std::string deformer_name = cluster->TargetNode()->Name();
aiString bone_name = aiString(FixNodeName(deformer_name));
aiBone *bone = nullptr;
@@ -1553,14 +1592,16 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
bone = new aiBone();
bone->mName = bone_name;
bone->mOffsetMatrix = cluster->Transform();
// store local transform link for post processing
bone->mOffsetMatrix = cl->TransformLink();
/*
bone->mOffsetMatrix = cluster->TransformLink();
bone->mOffsetMatrix.Inverse();
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
*/
//
// Now calculate the aiVertexWeights
//
@@ -1571,7 +1612,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
const WeightArray &weights = cl->GetWeights();
const WeightArray &weights = cluster->GetWeights();
const size_t c = index_out_indices.size();
for (size_t i = 0; i < c; ++i) {
@@ -2161,6 +2202,9 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
const float ShininessExponent = PropertyGet<float>(props, "ShininessExponent", ok);
if (ok) {
out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS);
// Match Blender behavior to extract roughness when only shininess is present
const float roughness = 1.0f - (sqrt(ShininessExponent) / 10.0f);
out_mat->AddProperty(&roughness, 1, AI_MATKEY_ROUGHNESS_FACTOR);
}
// TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
@@ -2613,7 +2657,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
meshMorphAnim->mNumKeys = numKeys;
meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
unsigned int j = 0;
for (auto animIt : *animData) {
for (auto &animIt : *animData) {
morphKeyData *keyData = animIt.second;
unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
@@ -3188,7 +3232,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
bool ok = false;
const float zero_epsilon = ai_epsilon;
const auto zero_epsilon = ai_epsilon;
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
if (ok && preRotation.SquareLength() > zero_epsilon) {
@@ -3326,13 +3370,17 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
float vc = curve->GetValues().at(1);
for (size_t n = 1; n < count; n++) {
while (std::abs(vc - vp) >= 180.0f) {
float step = std::floor(float(tc - tp) / (vc - vp) * 179.0f);
double step = std::floor(double(tc - tp) / std::abs(vc - vp) * 179.0f);
int64_t tnew = tp + int64_t(step);
float vnew = vp + (vc - vp) * step / float(tc - tp);
float vnew = vp + (vc - vp) * float(step / (tc - tp));
if (tnew >= adj_start && tnew <= adj_stop) {
Keys->push_back(tnew);
Values->push_back(vnew);
}
else {
// Something broke
break;
}
tp = tnew;
vp = vnew;
}
@@ -3633,6 +3681,12 @@ void FBXConverter::TransferDataToScene() {
std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
}
if (!mSkeletons.empty()) {
mSceneOut->mSkeletons = new aiSkeleton *[mSkeletons.size()];
mSceneOut->mNumSkeletons = static_cast<unsigned int>(mSkeletons.size());
std::swap_ranges(mSkeletons.begin(), mSkeletons.end(), mSceneOut->mSkeletons);
}
}
void FBXConverter::ConvertOrphanedEmbeddedTextures() {
+29 -16
View File
@@ -75,7 +75,18 @@ typedef std::map<int64_t, morphKeyData*> morphAnimData;
namespace Assimp {
namespace FBX {
class MeshGeometry;
using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
struct SkeletonBoneContainer {
std::vector<aiMesh *> MeshArray;
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
};
class Document;
/**
* Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated
@@ -180,14 +191,12 @@ private:
void SetupNodeMetadata(const Model& model, aiNode& nd);
// ------------------------------------------------------------------------------------------------
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &absolute_transform);
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
std::vector<unsigned int>
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &absolute_transform);
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
// ------------------------------------------------------------------------------------------------
std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
@@ -196,18 +205,16 @@ private:
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
// ------------------------------------------------------------------------------------------------
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
const aiMatrix4x4 &absolute_transform, aiNode *parent,
aiNode *root_node);
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
std::vector<unsigned int>
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
const aiMatrix4x4 &absolute_transform);
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, MatIndexArray::value_type index,
aiNode *parent, aiNode *root_node);
// ------------------------------------------------------------------------------------------------
static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
@@ -220,15 +227,19 @@ private:
* - outputVertStartIndices is only used when a material index is specified, it gives for
* each output vertex the DOM index it maps to.
*/
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent = nullptr,
unsigned int materialIndex = NO_MATERIAL_SEPARATION,
std::vector<unsigned int> *outputVertStartIndices = nullptr);
// ------------------------------------------------------------------------------------------------
void ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
aiNode *parent, unsigned int materialIndex, std::vector<unsigned int> *outputVertStartIndices,
SkeletonBoneContainer &skeletonContainer);
// ------------------------------------------------------------------------------------------------
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
aiNode *parent );
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent);
// ------------------------------------------------------------------------------------------------
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@@ -301,7 +312,8 @@ private:
void ConvertAnimationStack(const AnimationStack& st);
// ------------------------------------------------------------------------------------------------
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas,
const BlendShapeChannel* bsc, const AnimationCurveNode* node);
// ------------------------------------------------------------------------------------------------
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
@@ -450,6 +462,7 @@ private:
double anim_fps;
std::vector<aiSkeleton *> mSkeletons;
aiScene* const mSceneOut;
const FBX::Document& doc;
bool mRemoveEmptyBones;
+2 -5
View File
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -58,16 +57,14 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: Object(id,element,name)
{
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
Object(id,element,name) {
const Scope& sc = GetRequiredScope(element);
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
}
// ------------------------------------------------------------------------------------------------
Deformer::~Deformer()
{
+2 -2
View File
@@ -67,7 +67,7 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
doc(doc), element(element), id(id), flags() {
// empty
}
@@ -544,7 +544,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
ai_assert( count != 0 );
ai_assert( count <= MAX_CLASSNAMES);
size_t lengths[MAX_CLASSNAMES];
size_t lengths[MAX_CLASSNAMES] = {};
const size_t c = count;
for (size_t i = 0; i < c; ++i) {
+10 -10
View File
@@ -164,7 +164,7 @@ class NodeAttribute : public Object {
public:
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~NodeAttribute();
virtual ~NodeAttribute() = default;
const PropertyTable& Props() const {
ai_assert(props.get());
@@ -180,7 +180,7 @@ class CameraSwitcher : public NodeAttribute {
public:
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~CameraSwitcher();
virtual ~CameraSwitcher() = default;
int CameraID() const {
return cameraId;
@@ -225,7 +225,7 @@ class Camera : public NodeAttribute {
public:
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Camera();
virtual ~Camera() = default;
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
@@ -250,21 +250,21 @@ public:
class Null : public NodeAttribute {
public:
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Null();
virtual ~Null() = default;
};
/** DOM base class for FBX limb node markers attached to a node */
class LimbNode : public NodeAttribute {
public:
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~LimbNode();
virtual ~LimbNode() = default;
};
/** DOM base class for FBX lights attached to a node */
class Light : public NodeAttribute {
public:
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Light();
virtual ~Light() = default;
enum Type {
Type_Point,
@@ -690,7 +690,7 @@ using KeyValueList = std::vector<float>;
class AnimationCurve : public Object {
public:
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationCurve();
virtual ~AnimationCurve() = default;
/** get list of keyframe positions (time).
* Invariant: |GetKeys()| > 0 */
@@ -731,7 +731,7 @@ public:
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
virtual ~AnimationCurveNode();
virtual ~AnimationCurveNode() = default;
const PropertyTable& Props() const {
ai_assert(props.get());
@@ -776,7 +776,7 @@ using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
class AnimationLayer : public Object {
public:
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationLayer();
virtual ~AnimationLayer() = default;
const PropertyTable& Props() const {
ai_assert(props.get());
@@ -799,7 +799,7 @@ using AnimationLayerList = std::vector<const AnimationLayer*>;
class AnimationStack : public Object {
public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack();
virtual ~AnimationStack() = default;
fbx_simple_property(LocalStart, int64_t, 0L)
fbx_simple_property(LocalStop, int64_t, 0L)
+3 -6
View File
@@ -59,14 +59,12 @@ namespace Util {
// ------------------------------------------------------------------------------------------------
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
void DOMError(const std::string& message, const Token& token)
{
void DOMError(const std::string& message, const Token& token) {
throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
}
// ------------------------------------------------------------------------------------------------
void DOMError(const std::string& message, const Element* element /*= nullptr*/)
{
void DOMError(const std::string& message, const Element* element /*= nullptr*/) {
if(element) {
DOMError(message,element->KeyToken());
}
@@ -76,8 +74,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
// ------------------------------------------------------------------------------------------------
// print warning, do return
void DOMWarning(const std::string& message, const Token& token)
{
void DOMWarning(const std::string& message, const Token& token) {
if(DefaultLogger::get()) {
ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
}
+5 -7
View File
@@ -74,13 +74,11 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
// ------------------------------------------------------------------------------------------------
template <typename T>
inline
const T* ProcessSimpleConnection(const Connection& con,
bool is_object_property_conn,
const char* name,
const Element& element,
const char** propNameOut = nullptr)
{
inline const T* ProcessSimpleConnection(const Connection& con,
bool is_object_property_conn,
const char* name,
const Element& element,
const char** propNameOut = nullptr) {
if (is_object_property_conn && !con.PropertyName().length()) {
DOMWarning("expected incoming " + std::string(name) +
" link to be an object-object connection, ignoring",
+1 -1
View File
@@ -255,7 +255,7 @@ void FBXExporter::WriteBinaryHeader()
void FBXExporter::WriteBinaryFooter()
{
outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
outfile->Write(NULL_RECORD, NumNullRecords, 1);
outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
+6
View File
@@ -60,6 +60,7 @@ struct ImportSettings {
readLights(true),
readAnimations(true),
readWeights(true),
useSkeleton(false),
preservePivots(true),
optimizeEmptyAnimationCurves(true),
useLegacyEmbeddedTextureNaming(false),
@@ -112,6 +113,11 @@ struct ImportSettings {
* Default value is true. */
bool readWeights;
/** will convert all animation data into a skeleton (experimental)
* Default value is false.
*/
bool useSkeleton;
/** preserve transformation pivots and offsets. Since these can
* not directly be represented in assimp, additional dummy
* nodes will be generated. Note that settings this to false
+22 -25
View File
@@ -90,12 +90,9 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by #Importer
FBXImporter::FBXImporter() {
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FBXImporter::~FBXImporter() {
FBXImporter::FBXImporter() :
mSettings() {
// empty
}
// ------------------------------------------------------------------------------------------------
@@ -115,20 +112,21 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void FBXImporter::SetupProperties(const Importer *pImp) {
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
}
// ------------------------------------------------------------------------------------------------
@@ -155,7 +153,7 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
contents[contents.size() - 1] = 0;
const char *const begin = &*contents.begin();
// broadphase tokenizing pass in which we identify the core
// broad-phase tokenized pass in which we identify the core
// syntax elements of FBX (brackets, commas, key:value mappings)
TokenList tokens;
try {
@@ -173,15 +171,14 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
Parser parser(tokens, is_binary);
// take the raw parse-tree and convert it to a FBX DOM
Document doc(parser, settings);
Document doc(parser, mSettings);
// convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
// size relative to cm
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
if (size_relative_to_cm == 0.0)
{
if (size_relative_to_cm == 0.0) {
// BaseImporter later asserts that fileScale is non-zero.
ThrowException("The UnitScaleFactor must be non-zero");
}
+7 -6
View File
@@ -69,13 +69,14 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
// -------------------------------------------------------------------------------------------
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
public:
/// @brief The class constructor.
FBXImporter();
~FBXImporter() override;
// --------------------
bool CanRead(const std::string &pFile,
IOSystem *pIOHandler,
bool checkSig) const override;
/// @brief The class destructor, default implementation.
~FBXImporter() override = default;
/// @brief Will check the file for readability.
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
protected:
// --------------------
@@ -90,7 +91,7 @@ protected:
IOSystem *pIOHandler) override;
private:
FBX::ImportSettings settings;
FBX::ImportSettings mSettings;
}; // !class FBXImporter
} // end of namespace Assimp
+4 -20
View File
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -54,18 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
namespace Assimp {
namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name)
, skin()
{
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) :
Object(id, element, name), skin() {
const std::vector<const Connection*> &conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
for(const Connection* con : conns) {
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
if(sk) {
@@ -78,12 +74,6 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
}
}
// ------------------------------------------------------------------------------------------------
Geometry::~Geometry()
{
// empty
}
// ------------------------------------------------------------------------------------------------
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
return blendShapes;
@@ -183,18 +173,12 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
if(doc.Settings().readAllLayers || index == 0) {
const Scope& layer = GetRequiredScope(*(*it).second);
ReadLayer(layer);
}
else {
} else {
FBXImporter::LogWarn("ignoring additional geometry layers");
}
}
}
// ------------------------------------------------------------------------------------------------
MeshGeometry::~MeshGeometry() {
// empty
}
// ------------------------------------------------------------------------------------------------
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
return m_vertices;
+12 -9
View File
@@ -55,22 +55,25 @@ namespace FBX {
/**
* DOM base class for all kinds of FBX geometry
*/
class Geometry : public Object
{
class Geometry : public Object {
public:
/// @brief The class constructor with all parameters.
/// @param id The id.
/// @param element
/// @param name
/// @param doc
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
virtual ~Geometry();
virtual ~Geometry() = default;
/** Get the Skin attached to this geometry or nullptr */
/// Get the Skin attached to this geometry or nullptr
const Skin* DeformerSkin() const;
/** Get the BlendShape attached to this geometry or nullptr */
/// Get the BlendShape attached to this geometry or nullptr
const std::vector<const BlendShape*>& GetBlendShapes() const;
private:
const Skin* skin;
std::vector<const BlendShape*> blendShapes;
};
typedef std::vector<int> MatIndexArray;
@@ -79,14 +82,13 @@ typedef std::vector<int> MatIndexArray;
/**
* DOM class for FBX geometry of type "Mesh"
*/
class MeshGeometry : public Geometry
{
class MeshGeometry : public Geometry {
public:
/** The class constructor */
MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
/** The class destructor */
virtual ~MeshGeometry();
virtual ~MeshGeometry() = default;
/** Get a list of all vertex points, non-unique*/
const std::vector<aiVector3D>& GetVertices() const;
@@ -130,6 +132,7 @@ public:
/** Determine the face to which a particular output vertex index belongs.
* This mapping is always unique. */
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
private:
void ReadLayer( const Scope& layer );
void ReadLayerElement( const Scope& layerElement );
+28 -77
View File
@@ -57,114 +57,65 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: Object(id,element,name)
, props()
{
const Scope& sc = GetRequiredScope(element);
NodeAttribute::NodeAttribute(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
Object(id, element, name), props() {
const Scope &sc = GetRequiredScope(element);
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
const std::string &classname = ParseTokenAsString(GetRequiredToken(element, 2));
// hack on the deriving type but Null/LimbNode attributes are the only case in which
// the property table is by design absent and no warning should be generated
// for it.
const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
props = GetPropertyTable(doc, "NodeAttribute.Fbx" + classname, element, sc, is_null_or_limb);
}
// ------------------------------------------------------------------------------------------------
NodeAttribute::~NodeAttribute()
{
// empty
}
CameraSwitcher::CameraSwitcher(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
NodeAttribute(id, element, doc, name) {
const Scope &sc = GetRequiredScope(element);
const Element *const CameraId = sc["CameraId"];
const Element *const CameraName = sc["CameraName"];
const Element *const CameraIndexName = sc["CameraIndexName"];
// ------------------------------------------------------------------------------------------------
CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
const Scope& sc = GetRequiredScope(element);
const Element* const CameraId = sc["CameraId"];
const Element* const CameraName = sc["CameraName"];
const Element* const CameraIndexName = sc["CameraIndexName"];
if(CameraId) {
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
if (CameraId) {
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId, 0));
}
if(CameraName) {
cameraName = GetRequiredToken(*CameraName,0).StringContents();
if (CameraName) {
cameraName = GetRequiredToken(*CameraName, 0).StringContents();
}
if(CameraIndexName && CameraIndexName->Tokens().size()) {
cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
if (CameraIndexName && CameraIndexName->Tokens().size()) {
cameraIndexName = GetRequiredToken(*CameraIndexName, 0).StringContents();
}
}
// ------------------------------------------------------------------------------------------------
CameraSwitcher::~CameraSwitcher()
{
Camera::Camera(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
NodeAttribute(id, element, doc, name) {
// empty
}
// ------------------------------------------------------------------------------------------------
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
Light::Light(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
NodeAttribute(id, element, doc, name) {
// empty
}
// ------------------------------------------------------------------------------------------------
Camera::~Camera()
{
Null::Null(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
NodeAttribute(id, element, doc, name) {
// empty
}
// ------------------------------------------------------------------------------------------------
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
LimbNode::LimbNode(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
NodeAttribute(id, element, doc, name) {
// empty
}
} // namespace FBX
} // namespace Assimp
// ------------------------------------------------------------------------------------------------
Light::~Light()
{
}
// ------------------------------------------------------------------------------------------------
Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
}
// ------------------------------------------------------------------------------------------------
Null::~Null()
{
}
// ------------------------------------------------------------------------------------------------
LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name)
{
}
// ------------------------------------------------------------------------------------------------
LimbNode::~LimbNode()
{
}
}
}
#endif
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
+1 -15
View File
@@ -162,12 +162,6 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
}
// ------------------------------------------------------------------------------------------------
Element::~Element()
{
// no need to delete tokens, they are owned by the parser
}
// ------------------------------------------------------------------------------------------------
Scope::Scope(Parser& parser,bool topLevel)
{
@@ -226,12 +220,6 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
root.reset(new Scope(*this,true));
}
// ------------------------------------------------------------------------------------------------
Parser::~Parser()
{
// empty
}
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken()
{
@@ -961,8 +949,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
// ------------------------------------------------------------------------------------------------
// read an array of uints
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
{
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) {
out.resize( 0 );
const TokenList& tok = el.Tokens();
if(tok.empty()) {
@@ -1186,7 +1173,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
return result;
}
// ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsString() with ParseError handling
std::string ParseTokenAsString(const Token& t)
+2 -2
View File
@@ -87,7 +87,7 @@ class Element
{
public:
Element(const Token& key_token, Parser& parser);
~Element();
~Element() = default;
const Scope* Compound() const {
return compound.get();
@@ -160,7 +160,7 @@ public:
/** Parse given a token list. Does not take ownership of the tokens -
* the objects must persist during the entire parser lifetime */
Parser (const TokenList& tokens,bool is_binary);
~Parser();
~Parser() = default;
const Scope& GetRootScope() const {
return *root.get();
+4 -2
View File
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -51,7 +50,6 @@ namespace Assimp {
namespace IFC {
namespace {
// --------------------------------------------------------------------------------
// Conic is the base class for Circle and Ellipse
// --------------------------------------------------------------------------------
@@ -546,8 +544,10 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
}
#ifndef __INTEL_LLVM_COMPILER
ai_assert( min_diff[ 0 ] != inf );
ai_assert( min_diff[ 1 ] != inf );
#endif // __INTEL_LLVM_COMPILER
if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
return min_point[0];
}
@@ -606,8 +606,10 @@ bool BoundedCurve::IsClosed() const {
// ------------------------------------------------------------------------------------------------
void BoundedCurve::SampleDiscrete(TempMesh& out) const {
const ParamRange& range = GetParametricRange();
#ifndef __INTEL_LLVM_COMPILER
ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
#endif // __INTEL_LLVM_COMPILER
return SampleDiscrete(out,range.first,range.second);
}
+5 -5
View File
@@ -1428,7 +1428,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
return true;
}
std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
IfcVector3 planeNor,IfcFloat planeOffset,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first,bool& ok) {
std::vector<IfcVector2> contour;
@@ -1476,7 +1476,7 @@ std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMa
return contour;
}
const float close{ ai_epsilon };
const ai_real close{ ai_epsilon };
static bool isClose(IfcVector2 first,IfcVector2 second) {
auto diff = (second - first);
@@ -1491,7 +1491,7 @@ static void logSegment(std::pair<IfcVector2,IfcVector2> segment) {
IFCImporter::LogInfo(msg2.str().c_str());
}
std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
IfcFloat planeOffset) {
{
@@ -1676,7 +1676,7 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMe
std::stringstream msg;
msg << "GetContoursInPlane3D: found " << contours.size() << " contours:\n";
for(auto c : contours) {
for(const auto& c : contours) {
msg << " Contour: \n";
for(auto p : c) {
msg << " " << p.x << " " << p.y << " \n";
@@ -1690,7 +1690,7 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMe
return contours;
}
std::vector<std::vector<IfcVector2>> GetContoursInPlane(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
std::vector<std::vector<IfcVector2>> GetContoursInPlane(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
IfcVector3 planeNor,IfcFloat planeOffset,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first) {
+1 -1
View File
@@ -874,7 +874,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Batch loader used to load external models
BatchLoader batch(pIOHandler);
// batch.SetBasePath(pFile);
//batch.SetBasePath(pFile);
cameras.reserve(5);
lights.reserve(5);
+2 -2
View File
@@ -287,7 +287,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
if (UINT_MAX == iDefaultSurface) {
pSorted.erase(pSorted.end() - 1);
}
for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) {
for (unsigned int j = 0; j < mSurfaces->size(); ++j) {
SortedRep &sorted = pSorted[j];
if (sorted.empty())
continue;
@@ -425,7 +425,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
} else {
ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
}
++p;
}
}
@@ -1541,6 +1540,7 @@ void LWOImporter::LoadLWO2File() {
break;
}
// --- intentionally no break here
// fallthrough
case AI_LWO_VMAP: {
if (skip)
break;
+3
View File
@@ -313,6 +313,9 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
std::string::size_type t = src.path.substr(s).find_last_of('.');
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
if (nd->mName.length > MAXLEN) {
nd->mName.length = MAXLEN;
}
return;
}
}
+1 -3
View File
@@ -57,9 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Assimp specific M3D configuration. Comment out these defines to remove functionality
//#define ASSIMP_USE_M3D_READFILECB
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
#define STBI_ONLY_PNG
#include <stb/stb_image.h>
#include "Common/StbCommon.h"
#include "m3d.h"
+3
View File
@@ -449,6 +449,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
unsigned int iWidth,
unsigned int iHeight) {
std::unique_ptr<aiTexture> pcNew;
if (szCurrent == nullptr) {
return;
}
// get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF);
+21 -14
View File
@@ -52,9 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
#include <fstream>
#include <iomanip>
#include <memory>
#include <sstream>
static const aiImporterDesc desc = { "MMD Importer",
"",
@@ -102,26 +103,32 @@ const aiImporterDesc *MMDImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------
// MMD import implementation
void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
IOSystem * /*pIOHandler*/) {
// Read file by istream
std::filebuf fb;
if (!fb.open(file, std::ios::in | std::ios::binary)) {
IOSystem* pIOHandler) {
auto streamCloser = [&](IOStream *pStream) {
pIOHandler->Close(pStream);
};
static const std::string mode = "rb";
const std::unique_ptr<IOStream, decltype(streamCloser)> fileStream(pIOHandler->Open(file, mode), streamCloser);
if (fileStream == nullptr) {
throw DeadlyImportError("Failed to open file ", file, ".");
}
std::istream fileStream(&fb);
// Get the file-size and validate it, throwing an exception when fails
fileStream.seekg(0, fileStream.end);
size_t fileSize = static_cast<size_t>(fileStream.tellg());
fileStream.seekg(0, fileStream.beg);
if (fileSize < sizeof(pmx::PmxModel)) {
const size_t fileSize = fileStream->FileSize();
if (fileSize < sizeof(pmx::PmxModel))
{
throw DeadlyImportError(file, " is too small.");
}
std::vector<char> contents(fileStream->FileSize());
fileStream->Read(contents.data(), 1, contents.size());
std::istringstream iss(std::string(contents.begin(), contents.end()));
pmx::PmxModel model;
model.Read(&fileStream);
model.Read(&iss);
CreateDataFromImport(&model, pScene);
}
+2
View File
@@ -357,6 +357,8 @@ namespace pmx
{
public:
void virtual Read(std::istream *stream, PmxSetting *setting) = 0;
virtual ~PmxMorphOffset() = default;
};
class PmxMorphVertexOffset : public PmxMorphOffset
+3 -1
View File
@@ -136,7 +136,9 @@ void NDOImporter::InternReadFile( const std::string& pFile,
ASSIMP_LOG_INFO("NDO file format is 1.2");
}
else {
ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6));
char buff[4] = {0};
memcpy(buff, head+6, 3);
ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", buff);
}
reader.IncPtr(2); /* skip flags */
+45 -46
View File
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2022, assimp team
All rights reserved.
@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/types.h>
#include <map>
#include <vector>
#include "Common/Maybe.h"
namespace Assimp {
namespace ObjFile {
@@ -63,7 +64,7 @@ struct Face {
using IndexArray = std::vector<unsigned int>;
//! Primitive type
aiPrimitiveType m_PrimitiveType;
aiPrimitiveType mPrimitiveType;
//! Vertex indices
IndexArray m_vertices;
//! Normal indices
@@ -75,14 +76,12 @@ struct Face {
//! \brief Default constructor
Face(aiPrimitiveType pt = aiPrimitiveType_POLYGON) :
m_PrimitiveType(pt), m_vertices(), m_normals(), m_texturCoords(), m_pMaterial(0L) {
mPrimitiveType(pt), m_vertices(), m_normals(), m_texturCoords(), m_pMaterial(nullptr) {
// empty
}
//! \brief Destructor
~Face() {
// empty
}
~Face() = default;
};
// ------------------------------------------------------------------------------------------------
@@ -183,15 +182,15 @@ struct Material {
aiColor3D transparent;
//! PBR Roughness
ai_real roughness;
Maybe<ai_real> roughness;
//! PBR Metallic
ai_real metallic;
Maybe<ai_real> metallic;
//! PBR Metallic
aiColor3D sheen;
Maybe<aiColor3D> sheen;
//! PBR Clearcoat Thickness
ai_real clearcoat_thickness;
Maybe<ai_real> clearcoat_thickness;
//! PBR Clearcoat Rougness
ai_real clearcoat_roughness;
Maybe<ai_real> clearcoat_roughness;
//! PBR Anisotropy
ai_real anisotropy;
@@ -206,11 +205,11 @@ struct Material {
illumination_model(1),
ior(ai_real(1.0)),
transparent(ai_real(1.0), ai_real(1.0), ai_real(1.0)),
roughness(ai_real(1.0)),
metallic(ai_real(0.0)),
sheen(ai_real(1.0), ai_real(1.0), ai_real(1.0)),
clearcoat_thickness(ai_real(0.0)),
clearcoat_roughness(ai_real(0.0)),
roughness(),
metallic(),
sheen(),
clearcoat_thickness(),
clearcoat_roughness(),
anisotropy(ai_real(0.0)),
bump_multiplier(ai_real(1.0)) {
std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
@@ -229,7 +228,7 @@ struct Mesh {
/// The name for the mesh
std::string m_name;
/// Array with pointer to all stored faces
std::vector<Face *> m_Faces;
std::vector<Face*> m_Faces;
/// Assigned material
Material *m_pMaterial;
/// Number of stored indices.
@@ -272,65 +271,65 @@ struct Model {
using ConstGroupMapIt = std::map<std::string, std::vector<unsigned int> *>::const_iterator;
//! Model name
std::string m_ModelName;
std::string mModelName;
//! List ob assigned objects
std::vector<Object *> m_Objects;
std::vector<Object *> mObjects;
//! Pointer to current object
ObjFile::Object *m_pCurrent;
ObjFile::Object *mCurrentObject;
//! Pointer to current material
ObjFile::Material *m_pCurrentMaterial;
ObjFile::Material *mCurrentMaterial;
//! Pointer to default material
ObjFile::Material *m_pDefaultMaterial;
ObjFile::Material *mDefaultMaterial;
//! Vector with all generated materials
std::vector<std::string> m_MaterialLib;
std::vector<std::string> mMaterialLib;
//! Vector with all generated vertices
std::vector<aiVector3D> m_Vertices;
std::vector<aiVector3D> mVertices;
//! vector with all generated normals
std::vector<aiVector3D> m_Normals;
std::vector<aiVector3D> mNormals;
//! vector with all vertex colors
std::vector<aiVector3D> m_VertexColors;
std::vector<aiVector3D> mVertexColors;
//! Group map
GroupMap m_Groups;
GroupMap mGroups;
//! Group to face id assignment
std::vector<unsigned int> *m_pGroupFaceIDs;
std::vector<unsigned int> *mGroupFaceIDs;
//! Active group
std::string m_strActiveGroup;
std::string mActiveGroup;
//! Vector with generated texture coordinates
std::vector<aiVector3D> m_TextureCoord;
std::vector<aiVector3D> mTextureCoord;
//! Maximum dimension of texture coordinates
unsigned int m_TextureCoordDim;
unsigned int mTextureCoordDim;
//! Current mesh instance
Mesh *m_pCurrentMesh;
Mesh *mCurrentMesh;
//! Vector with stored meshes
std::vector<Mesh *> m_Meshes;
std::vector<Mesh *> mMeshes;
//! Material map
std::map<std::string, Material *> m_MaterialMap;
std::map<std::string, Material*> mMaterialMap;
//! \brief The default class constructor
Model() :
m_ModelName(),
m_pCurrent(nullptr),
m_pCurrentMaterial(nullptr),
m_pDefaultMaterial(nullptr),
m_pGroupFaceIDs(nullptr),
m_strActiveGroup(),
m_TextureCoordDim(0),
m_pCurrentMesh(nullptr) {
mModelName(),
mCurrentObject(nullptr),
mCurrentMaterial(nullptr),
mDefaultMaterial(nullptr),
mGroupFaceIDs(nullptr),
mActiveGroup(),
mTextureCoordDim(0),
mCurrentMesh(nullptr) {
// empty
}
//! \brief The class destructor
~Model() {
for (auto & it : m_Objects) {
for (auto & it : mObjects) {
delete it;
}
for (auto & Meshe : m_Meshes) {
for (auto & Meshe : mMeshes) {
delete Meshe;
}
for (auto & Group : m_Groups) {
for (auto & Group : mGroups) {
delete Group.second;
}
for (auto & it : m_MaterialMap) {
for (auto & it : mMaterialMap) {
delete it.second;
}
}
+57 -52
View File
@@ -163,20 +163,20 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
// Create the root node of the scene
pScene->mRootNode = new aiNode;
if (!pModel->m_ModelName.empty()) {
if (!pModel->mModelName.empty()) {
// Set the name of the scene
pScene->mRootNode->mName.Set(pModel->m_ModelName);
pScene->mRootNode->mName.Set(pModel->mModelName);
} else {
// This is a fatal error, so break down the application
ai_assert(false);
}
if (!pModel->m_Objects.empty()) {
if (!pModel->mObjects.empty()) {
unsigned int meshCount = 0;
unsigned int childCount = 0;
for (auto object : pModel->m_Objects) {
for (auto object : pModel->mObjects) {
if (object) {
++childCount;
meshCount += (unsigned int)object->m_Meshes.size();
@@ -189,8 +189,8 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
// Create nodes for the whole scene
std::vector<aiMesh *> MeshArray;
MeshArray.reserve(meshCount);
for (size_t index = 0; index < pModel->m_Objects.size(); ++index) {
createNodes(pModel, pModel->m_Objects[index], pScene->mRootNode, pScene, MeshArray);
for (size_t index = 0; index < pModel->mObjects.size(); ++index) {
createNodes(pModel, pModel->mObjects[index], pScene->mRootNode, pScene, MeshArray);
}
ai_assert(pScene->mRootNode->mNumChildren == childCount);
@@ -206,31 +206,31 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
// Create all materials
createMaterials(pModel, pScene);
} else {
if (pModel->m_Vertices.empty()) {
if (pModel->mVertices.empty()) {
return;
}
std::unique_ptr<aiMesh> mesh(new aiMesh);
mesh->mPrimitiveTypes = aiPrimitiveType_POINT;
unsigned int n = (unsigned int)pModel->m_Vertices.size();
unsigned int n = (unsigned int)pModel->mVertices.size();
mesh->mNumVertices = n;
mesh->mVertices = new aiVector3D[n];
memcpy(mesh->mVertices, pModel->m_Vertices.data(), n * sizeof(aiVector3D));
memcpy(mesh->mVertices, pModel->mVertices.data(), n * sizeof(aiVector3D));
if (!pModel->m_Normals.empty()) {
if (!pModel->mNormals.empty()) {
mesh->mNormals = new aiVector3D[n];
if (pModel->m_Normals.size() < n) {
if (pModel->mNormals.size() < n) {
throw DeadlyImportError("OBJ: vertex normal index out of range");
}
memcpy(mesh->mNormals, pModel->m_Normals.data(), n * sizeof(aiVector3D));
memcpy(mesh->mNormals, pModel->mNormals.data(), n * sizeof(aiVector3D));
}
if (!pModel->m_VertexColors.empty()) {
if (!pModel->mVertexColors.empty()) {
mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
for (unsigned int i = 0; i < n; ++i) {
if (i < pModel->m_VertexColors.size()) {
const aiVector3D &color = pModel->m_VertexColors[i];
if (i < pModel->mVertexColors.size()) {
const aiVector3D &color = pModel->mVertexColors[i];
mesh->mColors[0][i] = aiColor4D(color.x, color.y, color.z, 1.0);
} else {
throw DeadlyImportError("OBJ: vertex color index out of range");
@@ -315,7 +315,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
}
// Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex];
ObjFile::Mesh *pObjMesh = pModel->mMeshes[meshIndex];
if (!pObjMesh) {
return nullptr;
}
@@ -330,13 +330,13 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
}
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
ObjFile::Face *const inp = pObjMesh->m_Faces[index];
ai_assert(nullptr != inp);
const ObjFile::Face *inp = pObjMesh->m_Faces[index];
//ai_assert(nullptr != inp);
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
} else if (inp->mPrimitiveType == aiPrimitiveType_POINT) {
pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size());
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
} else {
@@ -360,15 +360,15 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
// Copy all data from all stored meshes
for (auto &face : pObjMesh->m_Faces) {
ObjFile::Face *const inp = face;
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
const ObjFile::Face *inp = face;
if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
for (size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
aiFace &f = pMesh->mFaces[outIndex++];
uiIdxCount += f.mNumIndices = 2;
f.mIndices = new unsigned int[2];
}
continue;
} else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
} else if (inp->mPrimitiveType == aiPrimitiveType_POINT) {
for (size_t i = 0; i < inp->m_vertices.size(); ++i) {
aiFace &f = pMesh->mFaces[outIndex++];
uiIdxCount += f.mNumIndices = 1;
@@ -407,7 +407,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
return;
// Get current mesh
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex];
ObjFile::Mesh *pObjMesh = pModel->mMeshes[uiMeshIndex];
if (nullptr == pObjMesh || pObjMesh->m_uiNumIndices < 1) {
return;
}
@@ -422,16 +422,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
// Allocate buffer for normal vectors
if (!pModel->m_Normals.empty() && pObjMesh->m_hasNormals)
if (!pModel->mNormals.empty() && pObjMesh->m_hasNormals)
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
// Allocate buffer for vertex-color vectors
if (!pModel->m_VertexColors.empty())
if (!pModel->mVertexColors.empty())
pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
// Allocate buffer for texture coordinates
if (!pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0]) {
pMesh->mNumUVComponents[0] = pModel->m_TextureCoordDim;
if (!pModel->mTextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0]) {
pMesh->mNumUVComponents[0] = pModel->mTextureCoordDim;
pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
}
@@ -442,7 +442,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
// Copy all index arrays
for (size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < sourceFace->m_vertices.size(); vertexIndex++) {
const unsigned int vertex = sourceFace->m_vertices.at(vertexIndex);
if (vertex >= pModel->m_Vertices.size()) {
if (vertex >= pModel->mVertices.size()) {
throw DeadlyImportError("OBJ: vertex index out of range");
}
@@ -450,32 +450,32 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
throw DeadlyImportError("OBJ: bad vertex index");
}
pMesh->mVertices[newIndex] = pModel->m_Vertices[vertex];
pMesh->mVertices[newIndex] = pModel->mVertices[vertex];
// Copy all normals
if (normalsok && !pModel->m_Normals.empty() && vertexIndex < sourceFace->m_normals.size()) {
if (normalsok && !pModel->mNormals.empty() && vertexIndex < sourceFace->m_normals.size()) {
const unsigned int normal = sourceFace->m_normals.at(vertexIndex);
if (normal >= pModel->m_Normals.size()) {
if (normal >= pModel->mNormals.size()) {
normalsok = false;
} else {
pMesh->mNormals[newIndex] = pModel->m_Normals[normal];
pMesh->mNormals[newIndex] = pModel->mNormals[normal];
}
}
// Copy all vertex colors
if (vertex < pModel->m_VertexColors.size()) {
const aiVector3D &color = pModel->m_VertexColors[vertex];
if (vertex < pModel->mVertexColors.size()) {
const aiVector3D &color = pModel->mVertexColors[vertex];
pMesh->mColors[0][newIndex] = aiColor4D(color.x, color.y, color.z, 1.0);
}
// Copy all texture coordinates
if (uvok && !pModel->m_TextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size()) {
if (uvok && !pModel->mTextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size()) {
const unsigned int tex = sourceFace->m_texturCoords.at(vertexIndex);
if (tex >= pModel->m_TextureCoord.size()) {
if (tex >= pModel->mTextureCoord.size()) {
uvok = false;
} else {
const aiVector3D &coord3d = pModel->m_TextureCoord[tex];
const aiVector3D &coord3d = pModel->mTextureCoord[tex];
pMesh->mTextureCoords[0][newIndex] = aiVector3D(coord3d.x, coord3d.y, coord3d.z);
}
}
@@ -484,15 +484,15 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
aiFace *pDestFace = &pMesh->mFaces[outIndex];
const bool last = (vertexIndex == sourceFace->m_vertices.size() - 1);
if (sourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
if (sourceFace->mPrimitiveType != aiPrimitiveType_LINE || !last) {
pDestFace->mIndices[outVertexIndex] = newIndex;
outVertexIndex++;
}
if (sourceFace->m_PrimitiveType == aiPrimitiveType_POINT) {
if (sourceFace->mPrimitiveType == aiPrimitiveType_POINT) {
outIndex++;
outVertexIndex = 0;
} else if (sourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
} else if (sourceFace->mPrimitiveType == aiPrimitiveType_LINE) {
outVertexIndex = 0;
if (!last)
@@ -501,10 +501,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
if (vertexIndex) {
if (!last) {
pMesh->mVertices[newIndex + 1] = pMesh->mVertices[newIndex];
if (!sourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
if (!sourceFace->m_normals.empty() && !pModel->mNormals.empty()) {
pMesh->mNormals[newIndex + 1] = pMesh->mNormals[newIndex];
}
if (!pModel->m_TextureCoord.empty()) {
if (!pModel->mTextureCoord.empty()) {
for (size_t i = 0; i < pMesh->GetNumUVChannels(); i++) {
pMesh->mTextureCoords[i][newIndex + 1] = pMesh->mTextureCoords[i][newIndex];
}
@@ -565,9 +565,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
return;
}
const unsigned int numMaterials = (unsigned int)pModel->m_MaterialLib.size();
const unsigned int numMaterials = (unsigned int)pModel->mMaterialLib.size();
pScene->mNumMaterials = 0;
if (pModel->m_MaterialLib.empty()) {
if (pModel->mMaterialLib.empty()) {
ASSIMP_LOG_DEBUG("OBJ: no materials specified");
return;
}
@@ -576,10 +576,10 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
for (unsigned int matIndex = 0; matIndex < numMaterials; matIndex++) {
// Store material name
std::map<std::string, ObjFile::Material *>::const_iterator it;
it = pModel->m_MaterialMap.find(pModel->m_MaterialLib[matIndex]);
it = pModel->mMaterialMap.find(pModel->mMaterialLib[matIndex]);
// No material found, use the default material
if (pModel->m_MaterialMap.end() == it)
if (pModel->mMaterialMap.end() == it)
continue;
aiMaterial *mat = new aiMaterial;
@@ -616,11 +616,16 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
mat->AddProperty(&pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS);
mat->AddProperty(&pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY);
mat->AddProperty(&pCurrentMaterial->transparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
mat->AddProperty(&pCurrentMaterial->roughness, 1, AI_MATKEY_ROUGHNESS_FACTOR);
mat->AddProperty(&pCurrentMaterial->metallic, 1, AI_MATKEY_METALLIC_FACTOR);
mat->AddProperty(&pCurrentMaterial->sheen, 1, AI_MATKEY_SHEEN_COLOR_FACTOR);
mat->AddProperty(&pCurrentMaterial->clearcoat_thickness, 1, AI_MATKEY_CLEARCOAT_FACTOR);
mat->AddProperty(&pCurrentMaterial->clearcoat_roughness, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
if (pCurrentMaterial->roughness)
mat->AddProperty(&pCurrentMaterial->roughness.Get(), 1, AI_MATKEY_ROUGHNESS_FACTOR);
if (pCurrentMaterial->metallic)
mat->AddProperty(&pCurrentMaterial->metallic.Get(), 1, AI_MATKEY_METALLIC_FACTOR);
if (pCurrentMaterial->sheen)
mat->AddProperty(&pCurrentMaterial->sheen.Get(), 1, AI_MATKEY_SHEEN_COLOR_FACTOR);
if (pCurrentMaterial->clearcoat_thickness)
mat->AddProperty(&pCurrentMaterial->clearcoat_thickness.Get(), 1, AI_MATKEY_CLEARCOAT_FACTOR);
if (pCurrentMaterial->clearcoat_roughness)
mat->AddProperty(&pCurrentMaterial->clearcoat_roughness.Get(), 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
mat->AddProperty(&pCurrentMaterial->anisotropy, 1, AI_MATKEY_ANISOTROPY_FACTOR);
// Adding refraction index
+84 -52
View File
@@ -99,9 +99,9 @@ ObjFileMtlImporter::ObjFileMtlImporter(std::vector<char> &buffer,
ai_assert(nullptr != m_pModel);
m_buffer.resize(BUFFERSIZE);
std::fill(m_buffer.begin(), m_buffer.end(), '\0');
if (nullptr == m_pModel->m_pDefaultMaterial) {
m_pModel->m_pDefaultMaterial = new ObjFile::Material;
m_pModel->m_pDefaultMaterial->MaterialName.Set("default");
if (nullptr == m_pModel->mDefaultMaterial) {
m_pModel->mDefaultMaterial = new ObjFile::Material;
m_pModel->mDefaultMaterial->MaterialName.Set("default");
}
load();
}
@@ -126,17 +126,21 @@ void ObjFileMtlImporter::load() {
if (*m_DataIt == 'a') // Ambient color
{
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->mCurrentMaterial->ambient);
} else if (*m_DataIt == 'd') {
// Diffuse color
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->mCurrentMaterial->diffuse);
} else if (*m_DataIt == 's') {
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->specular);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->mCurrentMaterial->specular);
} else if (*m_DataIt == 'e') {
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->mCurrentMaterial->emissive);
}
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
@@ -145,13 +149,15 @@ void ObjFileMtlImporter::load() {
// Material transmission color
if (*m_DataIt == 'f') {
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->mCurrentMaterial->transparent);
} else if (*m_DataIt == 'r') {
// Material transmission alpha value
++m_DataIt;
ai_real d;
getFloatValue(d);
m_pModel->m_pCurrentMaterial->alpha = static_cast<ai_real>(1.0) - d;
if (m_pModel->mCurrentMaterial != nullptr)
m_pModel->mCurrentMaterial->alpha = static_cast<ai_real>(1.0) - d;
}
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
@@ -162,7 +168,8 @@ void ObjFileMtlImporter::load() {
} else {
// Alpha value
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->alpha);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->alpha);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
}
} break;
@@ -173,11 +180,13 @@ void ObjFileMtlImporter::load() {
switch (*m_DataIt) {
case 's': // Specular exponent
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->shineness);
break;
case 'i': // Index Of refraction
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->ior);
break;
case 'e': // New material
createMaterial();
@@ -197,23 +206,28 @@ void ObjFileMtlImporter::load() {
{
case 'r':
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->roughness);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->roughness);
break;
case 'm':
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->metallic);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->metallic);
break;
case 's':
++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->sheen);
if (m_pModel->mCurrentMaterial != nullptr)
getColorRGBA(m_pModel->mCurrentMaterial->sheen);
break;
case 'c':
++m_DataIt;
if (*m_DataIt == 'r') {
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_roughness);
} else {
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness);
if (m_pModel->mCurrentMaterial != nullptr)
getFloatValue(m_pModel->mCurrentMaterial->clearcoat_thickness);
}
break;
}
@@ -232,15 +246,17 @@ void ObjFileMtlImporter::load() {
case 'i': // Illumination model
{
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model);
if (m_pModel->mCurrentMaterial != nullptr)
getIlluminationModel(m_pModel->mCurrentMaterial->illumination_model);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
case 'a': // Anisotropy
{
++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
getFloatValue(m_pModel->mCurrentMaterial->anisotropy);
if (m_pModel->mCurrentMaterial != nullptr)
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break;
default: {
@@ -268,6 +284,12 @@ void ObjFileMtlImporter::getColorRGBA(aiColor3D *pColor) {
pColor->b = b;
}
void ObjFileMtlImporter::getColorRGBA(Maybe<aiColor3D> &value) {
aiColor3D v;
getColorRGBA(&v);
value = Maybe<aiColor3D>(v);
}
// -------------------------------------------------------------------
// Loads the kind of illumination model.
void ObjFileMtlImporter::getIlluminationModel(int &illum_model) {
@@ -275,6 +297,7 @@ void ObjFileMtlImporter::getIlluminationModel(int &illum_model) {
illum_model = atoi(&m_buffer[0]);
}
// -------------------------------------------------------------------
// Loads a single float value.
void ObjFileMtlImporter::getFloatValue(ai_real &value) {
@@ -284,10 +307,19 @@ void ObjFileMtlImporter::getFloatValue(ai_real &value) {
value = 0.0f;
return;
}
value = (ai_real)fast_atof(&m_buffer[0]);
}
void ObjFileMtlImporter::getFloatValue(Maybe<ai_real> &value) {
m_DataIt = CopyNextWord<DataArrayIt>(m_DataIt, m_DataItEnd, &m_buffer[0], BUFFERSIZE);
size_t len = std::strlen(&m_buffer[0]);
if (len)
value = Maybe<ai_real>(fast_atof(&m_buffer[0]));
else
value = Maybe<ai_real>();
}
// -------------------------------------------------------------------
// Creates a material from loaded data.
void ObjFileMtlImporter::createMaterial() {
@@ -313,20 +345,20 @@ void ObjFileMtlImporter::createMaterial() {
name = trim_whitespaces(name);
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->m_MaterialMap.find(name);
if (m_pModel->m_MaterialMap.end() == it) {
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->mMaterialMap.find(name);
if (m_pModel->mMaterialMap.end() == it) {
// New Material created
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set(name);
m_pModel->m_MaterialLib.push_back(name);
m_pModel->m_MaterialMap[name] = m_pModel->m_pCurrentMaterial;
m_pModel->mCurrentMaterial = new ObjFile::Material();
m_pModel->mCurrentMaterial->MaterialName.Set(name);
m_pModel->mMaterialLib.push_back(name);
m_pModel->mMaterialMap[name] = m_pModel->mCurrentMaterial;
if (m_pModel->m_pCurrentMesh) {
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
if (m_pModel->mCurrentMesh) {
m_pModel->mCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->mMaterialLib.size() - 1);
}
} else {
// Use older material
m_pModel->m_pCurrentMaterial = (*it).second;
m_pModel->mCurrentMaterial = (*it).second;
}
}
@@ -339,38 +371,38 @@ void ObjFileMtlImporter::getTexture() {
const char *pPtr(&(*m_DataIt));
if (!ASSIMP_strincmp(pPtr, DiffuseTexture.c_str(), static_cast<unsigned int>(DiffuseTexture.size()))) {
// Diffuse texture
out = &m_pModel->m_pCurrentMaterial->texture;
out = &m_pModel->mCurrentMaterial->texture;
clampIndex = ObjFile::Material::TextureDiffuseType;
} else if (!ASSIMP_strincmp(pPtr, AmbientTexture.c_str(), static_cast<unsigned int>(AmbientTexture.size()))) {
// Ambient texture
out = &m_pModel->m_pCurrentMaterial->textureAmbient;
out = &m_pModel->mCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType;
} else if (!ASSIMP_strincmp(pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()))) {
// Specular texture
out = &m_pModel->m_pCurrentMaterial->textureSpecular;
out = &m_pModel->mCurrentMaterial->textureSpecular;
clampIndex = ObjFile::Material::TextureSpecularType;
} else if (!ASSIMP_strincmp(pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size())) ||
!ASSIMP_strincmp(pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()))) {
// Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp;
out = &m_pModel->mCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType;
} else if (!ASSIMP_strincmp(pPtr, OpacityTexture.c_str(), static_cast<unsigned int>(OpacityTexture.size()))) {
// Opacity texture
out = &m_pModel->m_pCurrentMaterial->textureOpacity;
out = &m_pModel->mCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType;
} else if (!ASSIMP_strincmp(pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size())) ||
!ASSIMP_strincmp(pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.size()))) {
// Emissive texture
out = &m_pModel->m_pCurrentMaterial->textureEmissive;
out = &m_pModel->mCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType;
} else if (!ASSIMP_strincmp(pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size())) ||
!ASSIMP_strincmp(pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()))) {
// Bump texture
out = &m_pModel->m_pCurrentMaterial->textureBump;
out = &m_pModel->mCurrentMaterial->textureBump;
clampIndex = ObjFile::Material::TextureBumpType;
} else if (!ASSIMP_strincmp(pPtr, NormalTextureV1.c_str(), static_cast<unsigned int>(NormalTextureV1.size())) || !ASSIMP_strincmp(pPtr, NormalTextureV2.c_str(), static_cast<unsigned int>(NormalTextureV2.size()))) {
// Normal map
out = &m_pModel->m_pCurrentMaterial->textureNormal;
out = &m_pModel->mCurrentMaterial->textureNormal;
clampIndex = ObjFile::Material::TextureNormalType;
} else if (!ASSIMP_strincmp(pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()))) {
// Reflection texture(s)
@@ -378,23 +410,23 @@ void ObjFileMtlImporter::getTexture() {
return;
} else if (!ASSIMP_strincmp(pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()))) {
// Specularity scaling (glossiness)
out = &m_pModel->m_pCurrentMaterial->textureSpecularity;
out = &m_pModel->mCurrentMaterial->textureSpecularity;
clampIndex = ObjFile::Material::TextureSpecularityType;
} else if ( !ASSIMP_strincmp( pPtr, RoughnessTexture.c_str(), static_cast<unsigned int>(RoughnessTexture.size()))) {
// PBR Roughness texture
out = & m_pModel->m_pCurrentMaterial->textureRoughness;
out = & m_pModel->mCurrentMaterial->textureRoughness;
clampIndex = ObjFile::Material::TextureRoughnessType;
} else if ( !ASSIMP_strincmp( pPtr, MetallicTexture.c_str(), static_cast<unsigned int>(MetallicTexture.size()))) {
// PBR Metallic texture
out = & m_pModel->m_pCurrentMaterial->textureMetallic;
out = & m_pModel->mCurrentMaterial->textureMetallic;
clampIndex = ObjFile::Material::TextureMetallicType;
} else if (!ASSIMP_strincmp( pPtr, SheenTexture.c_str(), static_cast<unsigned int>(SheenTexture.size()))) {
// PBR Sheen (reflectance) texture
out = & m_pModel->m_pCurrentMaterial->textureSheen;
out = & m_pModel->mCurrentMaterial->textureSheen;
clampIndex = ObjFile::Material::TextureSheenType;
} else if (!ASSIMP_strincmp( pPtr, RMATexture.c_str(), static_cast<unsigned int>(RMATexture.size()))) {
// PBR Rough/Metal/AO texture
out = & m_pModel->m_pCurrentMaterial->textureRMA;
out = & m_pModel->mCurrentMaterial->textureRMA;
clampIndex = ObjFile::Material::TextureRMAType;
} else {
ASSIMP_LOG_ERROR("OBJ/MTL: Encountered unknown texture type");
@@ -403,7 +435,7 @@ void ObjFileMtlImporter::getTexture() {
bool clamp = false;
getTextureOption(clamp, clampIndex, out);
m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp;
m_pModel->mCurrentMaterial->clamp[clampIndex] = clamp;
std::string texture;
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, texture);
@@ -451,31 +483,31 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value));
if (!ASSIMP_strincmp(value, "cube_top", 8)) {
clampIndex = ObjFile::Material::TextureReflectionCubeTopType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
out = &m_pModel->mCurrentMaterial->textureReflection[0];
} else if (!ASSIMP_strincmp(value, "cube_bottom", 11)) {
clampIndex = ObjFile::Material::TextureReflectionCubeBottomType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[1];
out = &m_pModel->mCurrentMaterial->textureReflection[1];
} else if (!ASSIMP_strincmp(value, "cube_front", 10)) {
clampIndex = ObjFile::Material::TextureReflectionCubeFrontType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[2];
out = &m_pModel->mCurrentMaterial->textureReflection[2];
} else if (!ASSIMP_strincmp(value, "cube_back", 9)) {
clampIndex = ObjFile::Material::TextureReflectionCubeBackType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[3];
out = &m_pModel->mCurrentMaterial->textureReflection[3];
} else if (!ASSIMP_strincmp(value, "cube_left", 9)) {
clampIndex = ObjFile::Material::TextureReflectionCubeLeftType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[4];
out = &m_pModel->mCurrentMaterial->textureReflection[4];
} else if (!ASSIMP_strincmp(value, "cube_right", 10)) {
clampIndex = ObjFile::Material::TextureReflectionCubeRightType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[5];
out = &m_pModel->mCurrentMaterial->textureReflection[5];
} else if (!ASSIMP_strincmp(value, "sphere", 6)) {
clampIndex = ObjFile::Material::TextureReflectionSphereType;
out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
out = &m_pModel->mCurrentMaterial->textureReflection[0];
}
skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, BumpOption.c_str(), static_cast<unsigned int>(BumpOption.size()))) {
DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
getFloat(it, m_DataItEnd, m_pModel->m_pCurrentMaterial->bump_multiplier);
getFloat(it, m_DataItEnd, m_pModel->mCurrentMaterial->bump_multiplier);
skipToken = 2;
} else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), static_cast<unsigned int>(BlendUOption.size())) || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), static_cast<unsigned int>(BlendVOption.size())) || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), static_cast<unsigned int>(BoostOption.size())) || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), static_cast<unsigned int>(ResolutionOption.size())) || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), static_cast<unsigned int>(ChannelOption.size()))) {
skipToken = 2;
+3
View File
@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/defs.h>
#include <string>
#include <vector>
#include "Common/Maybe.h"
struct aiColor3D;
struct aiString;
@@ -81,10 +82,12 @@ private:
void load();
/// Get color data.
void getColorRGBA(aiColor3D *pColor);
void getColorRGBA(Maybe<aiColor3D> &value);
/// Get illumination model from loaded data
void getIlluminationModel(int &illum_model);
/// Gets a float value from data.
void getFloatValue(ai_real &value);
void getFloatValue(Maybe<ai_real> &value);
/// Creates a new material from loaded data.
void createMaterial();
/// Get texture name from loaded data.
+76 -74
View File
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2022, assimp team
All rights reserved.
@@ -52,10 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <memory>
#include <utility>
#include <string_view>
namespace Assimp {
constexpr char ObjFileParser::DEFAULT_MATERIAL[];
constexpr const char ObjFileParser::DEFAULT_MATERIAL[];
ObjFileParser::ObjFileParser() :
m_DataIt(),
@@ -84,13 +85,13 @@ ObjFileParser::ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::stri
// Create the model instance to store all the data
m_pModel.reset(new ObjFile::Model());
m_pModel->m_ModelName = modelName;
m_pModel->mModelName = modelName;
// create default material and store it
m_pModel->m_pDefaultMaterial = new ObjFile::Material;
m_pModel->m_pDefaultMaterial->MaterialName.Set(DEFAULT_MATERIAL);
m_pModel->m_MaterialLib.push_back(DEFAULT_MATERIAL);
m_pModel->m_MaterialMap[DEFAULT_MATERIAL] = m_pModel->m_pDefaultMaterial;
m_pModel->mDefaultMaterial = new ObjFile::Material;
m_pModel->mDefaultMaterial->MaterialName.Set(DEFAULT_MATERIAL);
m_pModel->mMaterialLib.push_back(DEFAULT_MATERIAL);
m_pModel->mMaterialMap[DEFAULT_MATERIAL] = m_pModel->mDefaultMaterial;
// Start parsing the file
parseFile(streamBuffer);
@@ -153,23 +154,23 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
size_t numComponents = getNumComponentsInDataDefinition();
if (numComponents == 3) {
// read in vertex definition
getVector3(m_pModel->m_Vertices);
getVector3(m_pModel->mVertices);
} else if (numComponents == 4) {
// read in vertex definition (homogeneous coords)
getHomogeneousVector3(m_pModel->m_Vertices);
getHomogeneousVector3(m_pModel->mVertices);
} else if (numComponents == 6) {
// read vertex and vertex-color
getTwoVectors3(m_pModel->m_Vertices, m_pModel->m_VertexColors);
getTwoVectors3(m_pModel->mVertices, m_pModel->mVertexColors);
}
} else if (*m_DataIt == 't') {
// read in texture coordinate ( 2D or 3D )
++m_DataIt;
size_t dim = getTexCoordVector(m_pModel->m_TextureCoord);
m_pModel->m_TextureCoordDim = std::max(m_pModel->m_TextureCoordDim, (unsigned int)dim);
size_t dim = getTexCoordVector(m_pModel->mTextureCoord);
m_pModel->mTextureCoordDim = std::max(m_pModel->mTextureCoordDim, (unsigned int)dim);
} else if (*m_DataIt == 'n') {
// Read in normal vector definition
++m_DataIt;
getVector3(m_pModel->m_Normals);
getVector3(m_pModel->mNormals);
}
} break;
@@ -424,7 +425,7 @@ void ObjFileParser::getVector2(std::vector<aiVector2D> &point2d_array) {
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
}
static const std::string DefaultObjName = "defaultobject";
static constexpr char DefaultObjName[] = "defaultobject";
void ObjFileParser::getFace(aiPrimitiveType type) {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
@@ -435,12 +436,12 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
ObjFile::Face *face = new ObjFile::Face(type);
bool hasNormal = false;
const int vSize = static_cast<unsigned int>(m_pModel->m_Vertices.size());
const int vtSize = static_cast<unsigned int>(m_pModel->m_TextureCoord.size());
const int vnSize = static_cast<unsigned int>(m_pModel->m_Normals.size());
const int vSize = static_cast<unsigned int>(m_pModel->mVertices.size());
const int vtSize = static_cast<unsigned int>(m_pModel->mTextureCoord.size());
const int vnSize = static_cast<unsigned int>(m_pModel->mNormals.size());
const bool vt = (!m_pModel->m_TextureCoord.empty());
const bool vn = (!m_pModel->m_Normals.empty());
const bool vt = (!m_pModel->mTextureCoord.empty());
const bool vn = (!m_pModel->mNormals.empty());
int iPos = 0;
while (m_DataIt != m_DataItEnd) {
int iStep = 1;
@@ -458,8 +459,9 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
iPos = 0;
} else {
//OBJ USES 1 Base ARRAYS!!!!
const int iVal(::atoi(&(*m_DataIt)));
const char *token = &(*m_DataIt);
const int iVal = ::atoi(token);
// increment iStep position based off of the sign and # of digits
int tmp = iVal;
if (iVal < 0) {
@@ -499,7 +501,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
} else {
//On error, std::atoi will return 0 which is not a valid value
delete face;
throw DeadlyImportError("OBJ: Invalid face indice");
throw DeadlyImportError("OBJ: Invalid face index.");
}
}
m_DataIt += iStep;
@@ -514,28 +516,28 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
}
// Set active material, if one set
if (nullptr != m_pModel->m_pCurrentMaterial) {
face->m_pMaterial = m_pModel->m_pCurrentMaterial;
if (nullptr != m_pModel->mCurrentMaterial) {
face->m_pMaterial = m_pModel->mCurrentMaterial;
} else {
face->m_pMaterial = m_pModel->m_pDefaultMaterial;
face->m_pMaterial = m_pModel->mDefaultMaterial;
}
// Create a default object, if nothing is there
if (nullptr == m_pModel->m_pCurrent) {
if (nullptr == m_pModel->mCurrentObject) {
createObject(DefaultObjName);
}
// Assign face to mesh
if (nullptr == m_pModel->m_pCurrentMesh) {
if (nullptr == m_pModel->mCurrentMesh) {
createMesh(DefaultObjName);
}
// Store the face
m_pModel->m_pCurrentMesh->m_Faces.push_back(face);
m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_vertices.size();
m_pModel->m_pCurrentMesh->m_uiUVCoordinates[0] += (unsigned int)face->m_texturCoords.size();
if (!m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal) {
m_pModel->m_pCurrentMesh->m_hasNormals = true;
m_pModel->mCurrentMesh->m_Faces.emplace_back(face);
m_pModel->mCurrentMesh->m_uiNumIndices += static_cast<unsigned int>(face->m_vertices.size());
m_pModel->mCurrentMesh->m_uiUVCoordinates[0] += static_cast<unsigned int>(face->m_texturCoords.size());
if (!m_pModel->mCurrentMesh->m_hasNormals && hasNormal) {
m_pModel->mCurrentMesh->m_hasNormals = true;
}
// Skip the rest of the line
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
@@ -564,33 +566,33 @@ void ObjFileParser::getMaterialDesc() {
// If the current mesh has the same material, we simply ignore that 'usemtl' command
// There is no need to create another object or even mesh here
if (m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString(strName)) {
if (m_pModel->mCurrentMaterial && m_pModel->mCurrentMaterial->MaterialName == aiString(strName)) {
skip = true;
}
if (!skip) {
// Search for material
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->m_MaterialMap.find(strName);
if (it == m_pModel->m_MaterialMap.end()) {
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->mMaterialMap.find(strName);
if (it == m_pModel->mMaterialMap.end()) {
// Not found, so we don't know anything about the material except for its name.
// This may be the case if the material library is missing. We don't want to lose all
// materials if that happens, so create a new named material instead of discarding it
// completely.
ASSIMP_LOG_ERROR("OBJ: failed to locate material ", strName, ", creating new material");
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set(strName);
m_pModel->m_MaterialLib.push_back(strName);
m_pModel->m_MaterialMap[strName] = m_pModel->m_pCurrentMaterial;
m_pModel->mCurrentMaterial = new ObjFile::Material();
m_pModel->mCurrentMaterial->MaterialName.Set(strName);
m_pModel->mMaterialLib.push_back(strName);
m_pModel->mMaterialMap[strName] = m_pModel->mCurrentMaterial;
} else {
// Found, using detected material
m_pModel->m_pCurrentMaterial = (*it).second;
m_pModel->mCurrentMaterial = (*it).second;
}
if (needsNewMesh(strName)) {
createMesh(strName);
}
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
m_pModel->mCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
}
// Skip rest of line
@@ -677,17 +679,17 @@ void ObjFileParser::getNewMaterial() {
while (m_DataIt != m_DataItEnd && IsSpaceOrNewLine(*m_DataIt)) {
++m_DataIt;
}
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->m_MaterialMap.find(strMat);
if (it == m_pModel->m_MaterialMap.end()) {
std::map<std::string, ObjFile::Material *>::iterator it = m_pModel->mMaterialMap.find(strMat);
if (it == m_pModel->mMaterialMap.end()) {
// Show a warning, if material was not found
ASSIMP_LOG_WARN("OBJ: Unsupported material requested: ", strMat);
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
m_pModel->mCurrentMaterial = m_pModel->mDefaultMaterial;
} else {
// Set new material
if (needsNewMesh(strMat)) {
createMesh(strMat);
}
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strMat);
m_pModel->mCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strMat);
}
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
@@ -699,8 +701,8 @@ int ObjFileParser::getMaterialIndex(const std::string &strMaterialName) {
if (strMaterialName.empty()) {
return mat_index;
}
for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index) {
if (strMaterialName == m_pModel->m_MaterialLib[index]) {
for (size_t index = 0; index < m_pModel->mMaterialLib.size(); ++index) {
if (strMaterialName == m_pModel->mMaterialLib[index]) {
mat_index = (int)index;
break;
}
@@ -721,22 +723,22 @@ void ObjFileParser::getGroupName() {
}
// Change active group, if necessary
if (m_pModel->m_strActiveGroup != groupName) {
if (m_pModel->mActiveGroup != groupName) {
// Search for already existing entry
ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(groupName);
ObjFile::Model::ConstGroupMapIt it = m_pModel->mGroups.find(groupName);
// We are mapping groups into the object structure
createObject(groupName);
// New group name, creating a new entry
if (it == m_pModel->m_Groups.end()) {
if (it == m_pModel->mGroups.end()) {
std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
m_pModel->m_Groups[groupName] = pFaceIDArray;
m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
m_pModel->mGroups[groupName] = pFaceIDArray;
m_pModel->mGroupFaceIDs = (pFaceIDArray);
} else {
m_pModel->m_pGroupFaceIDs = (*it).second;
m_pModel->mGroupFaceIDs = (*it).second;
}
m_pModel->m_strActiveGroup = groupName;
m_pModel->mActiveGroup = groupName;
}
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
}
@@ -773,20 +775,20 @@ void ObjFileParser::getObjectName() {
std::string strObjectName(pStart, &(*m_DataIt));
if (!strObjectName.empty()) {
// Reset current object
m_pModel->m_pCurrent = nullptr;
m_pModel->mCurrentObject = nullptr;
// Search for actual object
for (std::vector<ObjFile::Object *>::const_iterator it = m_pModel->m_Objects.begin();
it != m_pModel->m_Objects.end();
for (std::vector<ObjFile::Object *>::const_iterator it = m_pModel->mObjects.begin();
it != m_pModel->mObjects.end();
++it) {
if ((*it)->m_strObjName == strObjectName) {
m_pModel->m_pCurrent = *it;
m_pModel->mCurrentObject = *it;
break;
}
}
// Allocate a new object, if current one was not found before
if (nullptr == m_pModel->m_pCurrent) {
if (nullptr == m_pModel->mCurrentObject) {
createObject(strObjectName);
}
}
@@ -797,16 +799,16 @@ void ObjFileParser::getObjectName() {
void ObjFileParser::createObject(const std::string &objName) {
ai_assert(nullptr != m_pModel);
m_pModel->m_pCurrent = new ObjFile::Object;
m_pModel->m_pCurrent->m_strObjName = objName;
m_pModel->m_Objects.push_back(m_pModel->m_pCurrent);
m_pModel->mCurrentObject = new ObjFile::Object;
m_pModel->mCurrentObject->m_strObjName = objName;
m_pModel->mObjects.push_back(m_pModel->mCurrentObject);
createMesh(objName);
if (m_pModel->m_pCurrentMaterial) {
m_pModel->m_pCurrentMesh->m_uiMaterialIndex =
getMaterialIndex(m_pModel->m_pCurrentMaterial->MaterialName.data);
m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
if (m_pModel->mCurrentMaterial) {
m_pModel->mCurrentMesh->m_uiMaterialIndex =
getMaterialIndex(m_pModel->mCurrentMaterial->MaterialName.data);
m_pModel->mCurrentMesh->m_pMaterial = m_pModel->mCurrentMaterial;
}
}
// -------------------------------------------------------------------
@@ -814,11 +816,11 @@ void ObjFileParser::createObject(const std::string &objName) {
void ObjFileParser::createMesh(const std::string &meshName) {
ai_assert(nullptr != m_pModel);
m_pModel->m_pCurrentMesh = new ObjFile::Mesh(meshName);
m_pModel->m_Meshes.push_back(m_pModel->m_pCurrentMesh);
unsigned int meshId = static_cast<unsigned int>(m_pModel->m_Meshes.size() - 1);
if (nullptr != m_pModel->m_pCurrent) {
m_pModel->m_pCurrent->m_Meshes.push_back(meshId);
m_pModel->mCurrentMesh = new ObjFile::Mesh(meshName);
m_pModel->mMeshes.push_back(m_pModel->mCurrentMesh);
unsigned int meshId = static_cast<unsigned int>(m_pModel->mMeshes.size() - 1);
if (nullptr != m_pModel->mCurrentObject) {
m_pModel->mCurrentObject->m_Meshes.push_back(meshId);
} else {
ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance.");
}
@@ -828,16 +830,16 @@ void ObjFileParser::createMesh(const std::string &meshName) {
// Returns true, if a new mesh must be created.
bool ObjFileParser::needsNewMesh(const std::string &materialName) {
// If no mesh data yet
if (m_pModel->m_pCurrentMesh == nullptr) {
if (m_pModel->mCurrentMesh == nullptr) {
return true;
}
bool newMat = false;
int matIdx = getMaterialIndex(materialName);
int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
int curMatIdx = m_pModel->mCurrentMesh->m_uiMaterialIndex;
if (curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx
// no need create a new mesh if no faces in current
// lets say 'usemtl' goes straight after 'g'
&& !m_pModel->m_pCurrentMesh->m_Faces.empty()) {
&& !m_pModel->mCurrentMesh->m_Faces.empty()) {
// New material -> only one material per mesh, so we need to create a new
// material
newMat = true;
+1 -4
View File
@@ -137,11 +137,8 @@ protected:
void reportErrorTokenInFace();
private:
// Copy and assignment constructor should be private
// because the class contains pointer to allocated memory
/// Default material name
static constexpr char DEFAULT_MATERIAL[] = AI_DEFAULT_MATERIAL_NAME;
static constexpr const char DEFAULT_MATERIAL[] = AI_DEFAULT_MATERIAL_NAME;
//! Iterator to current position in buffer
DataArrayIt m_DataIt;
//! Iterator to end position of buffer
+1 -1
View File
@@ -236,7 +236,7 @@ inline char_t CopyNextWord(char_t it, char_t end, char *pBuffer, size_t length)
template <class char_t>
inline char_t getFloat(char_t it, char_t end, ai_real &value) {
static const size_t BUFFERSIZE = 1024;
char buffer[BUFFERSIZE];
char buffer[BUFFERSIZE] = {};
it = CopyNextWord<char_t>(it, end, buffer, BUFFERSIZE);
value = (ai_real)fast_atof(buffer);
+21 -11
View File
@@ -248,6 +248,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
} else if (currentName == nnBoneAssignments) {
ReadBoneAssignments(currentNode, mesh->sharedVertexData);
} else if (currentName == nnSkeletonLink) {
mesh->skeletonRef = currentNode.attribute("name").as_string();
}
}
@@ -488,6 +489,15 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
Skeleton *skeleton = new Skeleton();
OgreXmlSerializer serializer(xmlParser.get());
XmlNode root = xmlParser->getRootNode();
if (std::string(root.name()) != nnSkeleton) {
printf("\nSkeleton is not a valid root: %s\n", root.name());
for (auto &a : root.children()) {
if (std::string(a.name()) == nnSkeleton) {
root = a;
break;
}
}
}
serializer.ReadSkeleton(root, skeleton);
mesh->skeleton = skeleton;
return true;
@@ -537,7 +547,7 @@ XmlParserPtr OgreXmlSerializer::OpenXmlParser(Assimp::IOSystem *pIOHandler, cons
}
void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
if (node.name() != nnSkeleton) {
if (std::string(node.name()) != nnSkeleton) {
throw DeadlyImportError("Root node is <" + std::string(node.name()) + "> expecting <skeleton>");
}
@@ -574,14 +584,14 @@ void OgreXmlSerializer::ReadAnimations(XmlNode &node, Skeleton *skeleton) {
anim->name = ReadAttribute<std::string>(currentNode, "name");
anim->length = ReadAttribute<float>(currentNode, "length");
for (XmlNode &currentChildNode : currentNode.children()) {
const std::string currentChildName = currentNode.name();
const std::string currentChildName = currentChildNode.name();
if (currentChildName == nnTracks) {
ReadAnimationTracks(currentChildNode, anim);
skeleton->animations.push_back(anim);
} else {
throw DeadlyImportError("No <tracks> found in <animation> ", anim->name);
}
}
skeleton->animations.push_back(anim);
}
}
}
@@ -594,14 +604,14 @@ void OgreXmlSerializer::ReadAnimationTracks(XmlNode &node, Animation *dest) {
track.type = VertexAnimationTrack::VAT_TRANSFORM;
track.boneName = ReadAttribute<std::string>(currentNode, "bone");
for (XmlNode &currentChildNode : currentNode.children()) {
const std::string currentChildName = currentNode.name();
const std::string currentChildName = currentChildNode.name();
if (currentChildName == nnKeyFrames) {
ReadAnimationKeyFrames(currentChildNode, dest, &track);
dest->tracks.push_back(track);
} else {
throw DeadlyImportError("No <keyframes> found in <track> ", dest->name);
}
}
dest->tracks.push_back(track);
}
}
}
@@ -614,15 +624,15 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, V
if (currentName == nnKeyFrame) {
keyframe.timePos = ReadAttribute<float>(currentNode, "time");
for (XmlNode &currentChildNode : currentNode.children()) {
const std::string currentChildName = currentNode.name();
const std::string currentChildName = currentChildNode.name();
if (currentChildName == nnTranslate) {
keyframe.position.x = ReadAttribute<float>(currentChildNode, anX);
keyframe.position.y = ReadAttribute<float>(currentChildNode, anY);
keyframe.position.z = ReadAttribute<float>(currentChildNode, anZ);
} else if (currentChildName == nnRotate) {
float angle = ReadAttribute<float>(currentChildNode, "angle");
for (XmlNode &currentChildChildNode : currentNode.children()) {
const std::string currentChildChildName = currentNode.name();
for (XmlNode &currentChildChildNode : currentChildNode.children()) {
const std::string currentChildChildName = currentChildChildNode.name();
if (currentChildChildName == nnAxis) {
aiVector3D axis;
axis.x = ReadAttribute<float>(currentChildChildNode, anX);
@@ -695,12 +705,12 @@ void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) {
bone->id = ReadAttribute<uint16_t>(currentNode, "id");
bone->name = ReadAttribute<std::string>(currentNode, "name");
for (XmlNode &currentChildNode : currentNode.children()) {
const std::string currentChildName = currentNode.name();
if (currentChildName == nnRotation) {
const std::string currentChildName = currentChildNode.name();
if (currentChildName == nnPosition) {
bone->position.x = ReadAttribute<float>(currentChildNode, anX);
bone->position.y = ReadAttribute<float>(currentChildNode, anY);
bone->position.z = ReadAttribute<float>(currentChildNode, anZ);
} else if (currentChildName == nnScale) {
} else if (currentChildName == nnRotation) {
float angle = ReadAttribute<float>(currentChildNode, "angle");
for (XmlNode currentChildChildNode : currentChildNode.children()) {
const std::string &currentChildChildName = currentChildChildNode.name();
+21 -29
View File
@@ -151,45 +151,46 @@ namespace Grammar {
}
static TokenType matchTokenType(const char *tokenType) {
if (MetricType == tokenType) {
const size_t len = std::strlen(tokenType);
if (0 == strncmp(MetricType, tokenType, len)) {
return MetricToken;
} else if (NameType == tokenType) {
} else if (0 == strncmp(NameType, tokenType, len)) {
return NameToken;
} else if (ObjectRefType == tokenType) {
} else if (0 == strncmp(ObjectRefType, tokenType, len)) {
return ObjectRefToken;
} else if (MaterialRefType == tokenType) {
} else if (0 == strncmp(MaterialRefType, tokenType, len)) {
return MaterialRefToken;
} else if (MetricKeyType == tokenType) {
} else if (0 == strncmp(MetricKeyType, tokenType, len)) {
return MetricKeyToken;
} else if (GeometryNodeType == tokenType) {
} else if (0 == strncmp(GeometryNodeType, tokenType, len)) {
return GeometryNodeToken;
} else if (CameraNodeType == tokenType) {
} else if (0 == strncmp(CameraNodeType, tokenType, len)) {
return CameraNodeToken;
} else if (LightNodeType == tokenType) {
} else if (0 == strncmp(LightNodeType, tokenType, len)) {
return LightNodeToken;
} else if (GeometryObjectType == tokenType) {
} else if (0 == strncmp(GeometryObjectType, tokenType, len)) {
return GeometryObjectToken;
} else if (CameraObjectType == tokenType) {
} else if (0 == strncmp(CameraObjectType, tokenType, len)) {
return CameraObjectToken;
} else if (LightObjectType == tokenType) {
} else if (0 == strncmp(LightObjectType, tokenType, len)) {
return LightObjectToken;
} else if (TransformType == tokenType) {
} else if (0 == strncmp(TransformType, tokenType, len)) {
return TransformToken;
} else if (MeshType == tokenType) {
} else if (0 == strncmp(MeshType, tokenType, len)) {
return MeshToken;
} else if (VertexArrayType == tokenType) {
} else if (0 == strncmp(VertexArrayType, tokenType, len)) {
return VertexArrayToken;
} else if (IndexArrayType == tokenType) {
} else if (0 == strncmp(IndexArrayType, tokenType, len)) {
return IndexArrayToken;
} else if (MaterialType == tokenType) {
} else if (0 == strncmp(MaterialType, tokenType, len)) {
return MaterialToken;
} else if (ColorType == tokenType) {
} else if (0 == strncmp(ColorType, tokenType, len)) {
return ColorToken;
} else if (ParamType == tokenType) {
} else if (0 == strncmp(ParamType, tokenType, len)) {
return ParamToken;
} else if (TextureType == tokenType) {
} else if (0 == strncmp(TextureType, tokenType, len)) {
return TextureToken;
} else if (AttenType == tokenType) {
} else if (0 == strncmp(AttenType, tokenType, len)) {
return AttenToken;
}
@@ -256,11 +257,6 @@ OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::stri
// empty
}
//------------------------------------------------------------------------------------------------
OpenGEXImporter::RefInfo::~RefInfo() {
// empty
}
//------------------------------------------------------------------------------------------------
OpenGEXImporter::OpenGEXImporter() :
m_root(nullptr),
@@ -285,10 +281,6 @@ OpenGEXImporter::OpenGEXImporter() :
// empty
}
//------------------------------------------------------------------------------------------------
OpenGEXImporter::~OpenGEXImporter() {
}
//------------------------------------------------------------------------------------------------
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
+3 -8
View File
@@ -79,12 +79,7 @@ struct MetricInfo {
float m_floatValue;
int m_intValue;
MetricInfo()
: m_stringValue( )
, m_floatValue( 0.0f )
, m_intValue( -1 ) {
// empty
}
MetricInfo(): m_stringValue( ), m_floatValue( 0.0f ), m_intValue( -1 ) {}
};
/** @brief This class is used to implement the OpenGEX importer
@@ -97,7 +92,7 @@ public:
OpenGEXImporter();
/// The class destructor.
~OpenGEXImporter() override;
~OpenGEXImporter() override = default;
/// BaseImporter override.
bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const override;
@@ -170,7 +165,7 @@ private:
std::vector<std::string> m_Names;
RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
~RefInfo();
~RefInfo() = default;
RefInfo( const RefInfo & ) = delete;
RefInfo &operator = ( const RefInfo & ) = delete;
+12 -2
View File
@@ -129,10 +129,20 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
unsigned int numTextures = (unsigned int)stream.GetI4();
std::vector<Material> materials;
materials.reserve(numMats);
try {
materials.reserve(numMats);
} catch(const std::bad_alloc&) {
ASSIMP_LOG_ERROR("Invalid alloc for materials.");
throw DeadlyImportError("Invalid Quick3D-file, material allocation failed.");
}
std::vector<Mesh> meshes;
meshes.reserve(numMeshes);
try {
meshes.reserve(numMeshes);
} catch(const std::bad_alloc&) {
ASSIMP_LOG_ERROR("Invalid alloc for meshes.");
throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed.");
}
// Allocate the scene root node
pScene->mRootNode = new aiNode();
+19 -19
View File
@@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
// 1) 80 byte header
// 2) 4 byte face count
// 3) 50 bytes per face
static bool IsBinarySTL(const char *buffer, unsigned int fileSize) {
static bool IsBinarySTL(const char *buffer, size_t fileSize) {
if (fileSize < 84) {
return false;
}
@@ -92,7 +92,7 @@ static const char UnicodeBoundary = 127;
// An ascii STL buffer will begin with "solid NAME", where NAME is optional.
// Note: The "solid NAME" check is necessary, but not sufficient, to determine
// if the buffer is ASCII; a binary header could also begin with "solid NAME".
static bool IsAsciiSTL(const char *buffer, unsigned int fileSize) {
static bool IsAsciiSTL(const char *buffer, size_t fileSize) {
if (IsBinarySTL(buffer, fileSize))
return false;
@@ -172,7 +172,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
throw DeadlyImportError("Failed to open STL file ", pFile, ".");
}
mFileSize = (unsigned int)file->FileSize();
mFileSize = file->FileSize();
// allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero)
@@ -233,7 +233,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
// try to guess how many vertices we could have
// assume we'll need 160 bytes for each face
size_t sizeEstimate = std::max(1u, mFileSize / 160u) * 3;
size_t sizeEstimate = std::max(1ull, mFileSize / 160ull) * 3ull;
positionBuffer.reserve(sizeEstimate);
normalBuffer.reserve(sizeEstimate);
@@ -284,8 +284,6 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
ASSIMP_LOG_WARN("STL: A new facet begins but the old is not yet complete");
}
faceVertexCounter = 0;
normalBuffer.push_back(aiVector3D());
aiVector3D *vn = &normalBuffer.back();
sz += 6;
SkipSpaces(&sz);
@@ -295,15 +293,17 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
if (sz[6] == '\0') {
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
}
aiVector3D vn;
sz += 7;
SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.x);
SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->y);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.y);
SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->z);
normalBuffer.push_back(*vn);
normalBuffer.push_back(*vn);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.z);
normalBuffer.emplace_back(vn);
normalBuffer.emplace_back(vn);
normalBuffer.emplace_back(vn);
}
} else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000
if (faceVertexCounter >= 3) {
@@ -315,7 +315,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
}
sz += 7;
SkipSpaces(&sz);
positionBuffer.push_back(aiVector3D());
positionBuffer.emplace_back();
aiVector3D *vn = &positionBuffer.back();
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x);
SkipSpaces(&sz);
@@ -439,7 +439,7 @@ bool STLImporter::LoadBinaryFile() {
pMesh->mNumFaces = *((uint32_t *)sz);
sz += 4;
if (mFileSize < 84 + pMesh->mNumFaces * 50) {
if (mFileSize < 84ull + pMesh->mNumFaces * 50ull) {
throw DeadlyImportError("STL: file is too small to hold all facets");
}
@@ -517,13 +517,13 @@ bool STLImporter::LoadBinaryFile() {
const ai_real invVal((ai_real)1.0 / (ai_real)31.0);
if (bIsMaterialise) // this is reversed
{
clr->r = (color & 0x31u) * invVal;
clr->g = ((color & (0x31u << 5)) >> 5u) * invVal;
clr->b = ((color & (0x31u << 10)) >> 10u) * invVal;
clr->r = (color & 0x1fu) * invVal;
clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal;
clr->b = ((color & (0x1fu << 10)) >> 10u) * invVal;
} else {
clr->b = (color & 0x31u) * invVal;
clr->g = ((color & (0x31u << 5)) >> 5u) * invVal;
clr->r = ((color & (0x31u << 10)) >> 10u) * invVal;
clr->b = (color & 0x1fu) * invVal;
clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal;
clr->r = ((color & (0x1fu << 10)) >> 10u) * invVal;
}
// assign the color to all vertices of the face
*(clr + 1) = *clr;
+1 -1
View File
@@ -109,7 +109,7 @@ protected:
const char* mBuffer;
/** Size of the file, in bytes */
unsigned int mFileSize;
size_t mFileSize;
/** Output scene */
aiScene* mScene;
+46 -94
View File
@@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2022, assimp team
All rights reserved.
@@ -59,7 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma warning(disable : 4127 4456 4245 4512 )
#endif // _MSC_VER
//
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
#else
@@ -99,13 +97,9 @@ namespace EXPRESS {
class DataType;
class UNSET; /*: public DataType */
class ISDERIVED; /*: public DataType */
// class REAL; /*: public DataType */
class ENUM; /*: public DataType */
// class STRING; /*: public DataType */
// class INTEGER; /*: public DataType */
class ENTITY; /*: public DataType */
class LIST; /*: public DataType */
// class SELECT; /*: public DataType */
// a conversion schema is not exactly an EXPRESS schema, rather it
// is a list of pointers to conversion functions to build up the
@@ -127,7 +121,8 @@ namespace STEP {
// -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code. It is typically
* coupled with a line number. */
* coupled with a line number.
*/
// -------------------------------------------------------------------------------
struct SyntaxError : DeadlyImportError {
enum : uint64_t {
@@ -139,8 +134,9 @@ struct SyntaxError : DeadlyImportError {
// -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code when a type
* error (i.e. an entity expects a string but receives a bool) occurs.
* It is typically coupled with both an entity id and a line number.*/
* error (i.e. an entity expects a string but receives a bool) occurs.
* It is typically coupled with both an entity id and a line number.
*/
// -------------------------------------------------------------------------------
struct TypeError : DeadlyImportError {
enum : uint64_t {
@@ -167,10 +163,8 @@ public:
typedef std::shared_ptr<const DataType> Out;
public:
virtual ~DataType() {
}
virtual ~DataType() = default;
public:
template <typename T>
const T &To() const {
return dynamic_cast<const T &>(*this);
@@ -206,16 +200,14 @@ public:
public:
/** parse a variable from a string and set 'inout' to the character
* behind the last consumed character. An optional schema enables,
* if specified, automatic conversion of custom data types.
*
* @throw SyntaxError
*/
* behind the last consumed character. An optional schema enables,
* if specified, automatic conversion of custom data types.
*
* @throw SyntaxError
*/
static std::shared_ptr<const EXPRESS::DataType> Parse(const char *&inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema *schema = NULL);
public:
};
typedef DataType SELECT;
@@ -238,7 +230,8 @@ private:
};
// -------------------------------------------------------------------------------
/** Shared implementation for some of the primitive data type, i.e. int, float */
/** Shared implementation for some of the primitive data type, i.e. int, float
*/
// -------------------------------------------------------------------------------
template <typename T>
class PrimitiveDataType : public DataType {
@@ -247,7 +240,7 @@ public:
// expose this data type to the user.
typedef T Out;
PrimitiveDataType() {}
PrimitiveDataType() = default;
PrimitiveDataType(const T &val) :
val(val) {}
@@ -280,28 +273,18 @@ class ENUMERATION : public STRING {
public:
ENUMERATION(const std::string &val) :
STRING(val) {}
private:
};
typedef ENUMERATION BOOLEAN;
// -------------------------------------------------------------------------------
/** This is just a reference to an entity/object somewhere else */
/** This is just a reference to an entity/object somewhere else
*/
// -------------------------------------------------------------------------------
class ENTITY : public PrimitiveDataType<uint64_t> {
public:
ENTITY(uint64_t val) :
PrimitiveDataType<uint64_t>(val) {
ai_assert(val != 0);
}
ENTITY() :
PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED) {
// empty
}
private:
ENTITY(uint64_t val) : PrimitiveDataType<uint64_t>(val) {}
ENTITY() : PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED) {}
};
// -------------------------------------------------------------------------------
@@ -319,7 +302,8 @@ public:
}
public:
/** @see DaraType::Parse */
/** @see DaraType::Parse
*/
static std::shared_ptr<const EXPRESS::LIST> Parse(const char *&inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema *schema = NULL);
@@ -331,29 +315,20 @@ private:
class BINARY : public PrimitiveDataType<uint32_t> {
public:
BINARY(uint32_t val) :
PrimitiveDataType<uint32_t>(val) {
// empty
}
BINARY() :
PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {
// empty
}
BINARY(uint32_t val) : PrimitiveDataType<uint32_t>(val) {}
BINARY() : PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {}
};
// -------------------------------------------------------------------------------
/* Not exactly a full EXPRESS schema but rather a list of conversion functions
* to extract valid C++ objects out of a STEP file. Those conversion functions
* may, however, perform further schema validations. */
* to extract valid C++ objects out of a STEP file. Those conversion functions
* may, however, perform further schema validations.
*/
// -------------------------------------------------------------------------------
class ConversionSchema {
public:
struct SchemaEntry {
SchemaEntry(const char *name, ConvertObjectProc func) :
mName(name), mFunc(func) {
// empty
}
SchemaEntry(const char *name, ConvertObjectProc func) : mName(name), mFunc(func) {}
const char *mName;
ConvertObjectProc mFunc;
@@ -366,8 +341,7 @@ public:
*this = schemas;
}
ConversionSchema() {
}
ConversionSchema() = default;
ConvertObjectProc GetConverterProc(const std::string &name) const {
ConverterMap::const_iterator it = converters.find(name);
@@ -399,8 +373,9 @@ private:
// ------------------------------------------------------------------------------
/** Bundle all the relevant info from a STEP header, parts of which may later
* be plainly dumped to the logfile, whereas others may help the caller pick an
* appropriate loading strategy.*/
* be plainly dumped to the logfile, whereas others may help the caller pick an
* appropriate loading strategy.
*/
// ------------------------------------------------------------------------------
struct HeaderInfo {
std::string timestamp;
@@ -409,18 +384,14 @@ struct HeaderInfo {
};
// ------------------------------------------------------------------------------
/** Base class for all concrete object instances */
/** Base class for all concrete object instances
*/
// ------------------------------------------------------------------------------
class Object {
public:
Object(const char *classname = "unknown") :
id(0), classname(classname) {
// empty
}
Object(const char *classname = "unknown") : id(0), classname(classname) {}
virtual ~Object() {
// empty
}
virtual ~Object() = default;
// utilities to simplify casting to concrete types
template <typename T>
@@ -469,26 +440,15 @@ size_t GenericFill(const STEP::DB &db, const EXPRESS::LIST &params, T *in);
// ------------------------------------------------------------------------------
template <typename TDerived, size_t arg_count>
struct ObjectHelper : virtual Object {
ObjectHelper() :
aux_is_derived(0) {
// empty
}
ObjectHelper() : aux_is_derived(0) {}
static Object *Construct(const STEP::DB &db, const EXPRESS::LIST &params) {
// make sure we don't leak if Fill() throws an exception
std::unique_ptr<TDerived> impl(new TDerived());
// GenericFill<T> is undefined so we need to have a specialization
const size_t num_args = GenericFill<TDerived>(db, params, &*impl);
(void)num_args;
static_cast<void>(GenericFill<TDerived>(db, params, &*impl));
// the following check is commented because it will always trigger if
// parts of the entities are generated with dummy wrapper code.
// This is currently done to reduce the size of the loader
// code.
//if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") {
// DefaultLogger::get()->debug("STEP: not all parameters consumed");
//}
return impl.release();
}
@@ -502,15 +462,9 @@ struct ObjectHelper : virtual Object {
// ------------------------------------------------------------------------------
template <typename T>
struct Maybe {
Maybe() :
have() {
// empty
}
Maybe() : have() {}
explicit Maybe(const T &ptr) :
ptr(ptr), have(true) {
// empty
}
explicit Maybe(const T &ptr) : ptr(ptr), have(true) {}
void flag_invalid() {
have = false;
@@ -557,7 +511,8 @@ private:
// ------------------------------------------------------------------------------
/** A LazyObject is created when needed. Before this happens, we just keep
the text line that contains the object definition. */
* the text line that contains the object definition.
*/
// -------------------------------------------------------------------------------
class LazyObject {
friend class DB;
@@ -649,10 +604,7 @@ inline bool operator==(const std::pair<uint64_t, std::shared_ptr<LazyObject>> &l
template <typename T>
struct Lazy {
typedef Lazy Out;
Lazy(const LazyObject *obj = nullptr) :
obj(obj) {
// empty
}
Lazy(const LazyObject *obj = nullptr) : obj(obj) {}
operator const T *() const {
return obj->ToPtr<T>();
@@ -785,8 +737,9 @@ inline void GenericConvert(ListOf<T1, N1, N2> &a, const std::shared_ptr<const EX
// ------------------------------------------------------------------------------
/** Lightweight manager class that holds the map of all objects in a
* STEP file. DB's are exclusively maintained by the functions in
* STEPFileReader.h*/
* STEP file. DB's are exclusively maintained by the functions in
* STEPFileReader.h
*/
// -------------------------------------------------------------------------------
class DB {
friend DB *ReadFileHeader(std::shared_ptr<IOStream> stream);
@@ -873,7 +826,7 @@ public:
if (it != objects_bytype.end() && (*it).second.size()) {
return *(*it).second.begin();
}
return NULL;
return nullptr;
}
// same, but raise an exception if the object doesn't exist and return a reference
@@ -965,7 +918,6 @@ private:
#endif // _MSC_VER
} // namespace STEP
} // namespace Assimp
#endif // INCLUDED_AI_STEPFILE_H
+1 -1
View File
@@ -333,7 +333,7 @@ void X3DImporter::readHead(XmlNode &node) {
}
mScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metaArray.size()));
unsigned int i = 0;
for (auto currentMeta : metaArray) {
for (const auto& currentMeta : metaArray) {
mScene->mMetaData->Set(i, currentMeta.name, aiString(currentMeta.value));
++i;
}
+5 -5
View File
@@ -53,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
using namespace Assimp;
using namespace glTFCommon;
namespace glTF {
using namespace glTFCommon;
#if _MSC_VER
#pragma warning(push)
@@ -891,12 +891,12 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
auto get_buf_offset = [](Ref<Accessor> &pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; };
// Indices
ifs.SetCoordIndex((IndicesType *const)(decoded_data + get_buf_offset(primitives[0].indices)));
ifs.SetCoordIndex((IndicesType *)(decoded_data + get_buf_offset(primitives[0].indices)));
// Coordinates
ifs.SetCoord((o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0])));
ifs.SetCoord((o3dgc::Real *)(decoded_data + get_buf_offset(primitives[0].attributes.position[0])));
// Normals
if (size_normal) {
ifs.SetNormal((o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0])));
ifs.SetNormal((o3dgc::Real *)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0])));
}
for (size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) {
@@ -904,7 +904,7 @@ inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DG
case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
if (idx_texcoord < primitives[0].attributes.texcoord.size()) {
// See above about absent attributes.
ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx])));
ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real *)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx])));
idx_texcoord++;
}
+2
View File
@@ -374,6 +374,8 @@ struct CustomExtension {
mValues(other.mValues) {
// empty
}
CustomExtension& operator=(const CustomExtension&) = default;
};
//! Base class for all glTF top-level objects
+13 -1
View File
@@ -82,9 +82,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// clang-format on
using namespace Assimp;
using namespace glTFCommon;
namespace glTF2 {
using glTFCommon::FindStringInContext;
using glTFCommon::FindNumberInContext;
using glTFCommon::FindUIntInContext;
using glTFCommon::FindArrayInContext;
using glTFCommon::FindObjectInContext;
using glTFCommon::FindExtensionInContext;
using glTFCommon::MemberOrDefault;
using glTFCommon::ReadMember;
using glTFCommon::FindMember;
using glTFCommon::FindObject;
using glTFCommon::FindUInt;
using glTFCommon::FindArray;
using glTFCommon::FindArray;
namespace {
+2 -2
View File
@@ -683,7 +683,7 @@ bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &she
}
// Default Sheen color factor {0,0,0} disables Sheen, so do not export
if (sheen.sheenColorFactor == defaultSheenFactor) {
if (sheen.sheenColorFactor[0] == defaultSheenFactor[0] && sheen.sheenColorFactor[1] == defaultSheenFactor[1] && sheen.sheenColorFactor[2] == defaultSheenFactor[2]) {
return false;
}
@@ -908,7 +908,7 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
do {
startNodeRef = parentNodeRef;
parentNodeRef = startNodeRef->parent;
} while (!parentNodeRef->jointName.empty());
} while (parentNodeRef && !parentNodeRef->jointName.empty());
return parentNodeRef;
}
+23 -20
View File
@@ -284,7 +284,7 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE);
aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF);
//pbrSpecularGlossiness
// pbrSpecularGlossiness
if (mat.pbrSpecularGlossiness.isPresent) {
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
@@ -606,7 +606,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
}
}
if (needTangents) {
if (target.tangent[0]->count != aim->mNumVertices) {
if (!aiAnimMesh.HasNormals()) {
// prevent nullptr access to aiAnimMesh.mNormals below when no normals are available
ASSIMP_LOG_WARN("Bitangents of target ", i, " in mesh \"", mesh.name, "\" can't be computed, because mesh has no normals.");
} else if (target.tangent[0]->count != aim->mNumVertices) {
ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
} else {
Tangent *tangent = nullptr;
@@ -698,12 +701,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
// The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
// For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
// For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
}
@@ -776,12 +779,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
nFaces = count - 2;
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < nFaces; ++i) {
//The ordering is to ensure that the triangles are all drawn with the same orientation
// The ordering is to ensure that the triangles are all drawn with the same orientation
if ((i + 1) % 2 == 0) {
//For even n, vertices n + 1, n, and n + 2 define triangle n
// For even n, vertices n + 1, n, and n + 2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2);
} else {
//For odd n, vertices n, n+1, and n+2 define triangle n
// For odd n, vertices n, n+1, and n+2 define triangle n
SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2);
}
}
@@ -904,14 +907,14 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) {
ail->mAttenuationLinear = 0.0;
ail->mAttenuationQuadratic = 0.0;
} else {
//in PBR attenuation is calculated using inverse square law which can be expressed
//using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
//this is correct equation for the case when range (see
//https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual)
//is not present. When range is not present it is assumed that it is infinite and so numerator is 1.
//When range is present then numerator might be any value in range [0,1] and then assimps equation
//will not suffice. In this case range is added into metadata in ImportNode function
//and its up to implementation to read it when it wants to
// in PBR attenuation is calculated using inverse square law which can be expressed
// using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters
// this is correct equation for the case when range (see
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual)
// is not present. When range is not present it is assumed that it is infinite and so numerator is 1.
// When range is present then numerator might be any value in range [0,1] and then assimps equation
// will not suffice. In this case range is added into metadata in ImportNode function
// and its up to implementation to read it when it wants to
ail->mAttenuationConstant = 0.0;
ail->mAttenuationLinear = 0.0;
ail->mAttenuationQuadratic = 1.0;
@@ -1178,8 +1181,8 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
if (node.light) {
pScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
//range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
//it is added to meta data of parent node, because there is no other place to put it
// range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
// it is added to meta data of parent node, because there is no other place to put it
if (node.light->range.isPresent) {
if (!ainode->mMetaData) {
ainode->mMetaData = aiMetadata::Alloc(1);
@@ -1573,9 +1576,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
if (ext) {
if (strcmp(ext, "jpeg") == 0) {
ext = "jpg";
} else if (strcmp(ext, "ktx2") == 0) { //basisu: ktx remains
} else if (strcmp(ext, "ktx2") == 0) { // basisu: ktx remains
ext = "kx2";
} else if (strcmp(ext, "basis") == 0) { //basisu
} else if (strcmp(ext, "basis") == 0) { // basisu
ext = "bu";
}