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";
}
+30 -15
View File
@@ -150,7 +150,7 @@ SET( Core_SRCS
Common/Assimp.cpp
)
IF(MSVC)
IF(MSVC OR (MINGW AND BUILD_SHARED_LIBS))
list(APPEND Core_SRCS "res/assimp.rc")
ENDIF()
@@ -167,6 +167,7 @@ SET( Logging_SRCS
SOURCE_GROUP(Logging FILES ${Logging_SRCS})
SET( Common_SRCS
Common/StbCommon.h
Common/Compression.cpp
Common/Compression.h
Common/BaseImporter.cpp
@@ -182,6 +183,7 @@ SET( Common_SRCS
Common/DefaultIOSystem.cpp
Common/ZipArchiveIOSystem.cpp
Common/PolyTools.h
Common/Maybe.h
Common/Importer.cpp
Common/IFF.h
Common/SGSpatialSort.cpp
@@ -1053,7 +1055,9 @@ ENDIF()
# Check dependencies for glTF importer with Open3DGC-compression.
# RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
# has implementation for different platforms: WIN32, __MACH__ and other ("else" block).
FIND_PACKAGE(RT QUIET)
IF (NOT WIN32)
FIND_PACKAGE(RT QUIET)
ENDIF ()
IF (NOT ASSIMP_HUNTER_ENABLED AND (RT_FOUND OR WIN32))
SET( ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC 1 )
ADD_DEFINITIONS( -DASSIMP_IMPORTER_GLTF_USE_OPEN3DGC=1 )
@@ -1096,8 +1100,6 @@ if(MSVC10)
endif()
endif()
ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT )
IF( MSVC OR "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") # clang with MSVC ABI
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
@@ -1174,13 +1176,22 @@ ENDIF()
ADD_LIBRARY( assimp ${assimp_src} )
ADD_LIBRARY(assimp::assimp ALIAS assimp)
# Add or remove dllexport tags depending on the library type.
IF (BUILD_SHARED_LIBS)
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE ASSIMP_BUILD_DLL_EXPORT)
ELSE ()
TARGET_COMPILE_DEFINITIONS(assimp PRIVATE OPENDDL_STATIC_LIBARY)
ENDIF ()
TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp)
# enable warnings as errors ########################################
IF (MSVC)
TARGET_COMPILE_OPTIONS(assimp PRIVATE /WX)
ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Werror)
IF (ASSIMP_WARNINGS_AS_ERRORS)
MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
IF (MSVC)
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror)
ENDIF()
ENDIF()
# adds C_FLAGS required to compile zip.c on old GCC 4.x compiler
@@ -1263,6 +1274,16 @@ if( MSVC )
set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
endif()
if (MINGW)
set(LIBRARY_SUFFIX "-${ASSIMP_SOVERSION}" CACHE STRING "the suffix for the assimp MinGW shared library")
SET_TARGET_PROPERTIES( assimp PROPERTIES
ARCHIVE_OUTPUT_NAME assimp
)
if (NOT BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES ( assimp -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lwinpthread ) # winpthread is for libminizip.
endif ()
endif()
if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
target_compile_definitions(assimp PUBLIC WindowsStore)
TARGET_LINK_LIBRARIES(assimp advapi32)
@@ -1274,12 +1295,6 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
OUTPUT_NAME assimp${LIBRARY_SUFFIX}
)
if (WIN32 AND CMAKE_COMPILER_IS_GNUCXX AND BUILD_SHARED_LIBS)
set_target_properties(assimp PROPERTIES
SUFFIX "-${ASSIMP_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}"
)
endif()
if (APPLE)
if (ASSIMP_BUILD_FRAMEWORK)
SET_TARGET_PROPERTIES( assimp PROPERTIES
+6 -13
View File
@@ -5,8 +5,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,
@@ -1282,18 +1280,13 @@ ASSIMP_API void aiQuaternionInterpolate(
# define STBI_ONLY_PNG
#endif
// Ensure all symbols are linked correctly
#if ASSIMP_NEEDS_STB_IMAGE
# if _MSC_VER // "unreferenced function has been removed" (SSE2 detection routine in x64 builds)
# pragma warning(push)
# pragma warning(disable: 4505)
// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
# define STBI_ONLY_PNG
# ifdef ASSIMP_USE_STB_IMAGE_STATIC
# define STB_IMAGE_STATIC
# endif
# define STB_IMAGE_IMPLEMENTATION
# include "stb/stb_image.h"
# if _MSC_VER
# pragma warning(pop)
# endif
# include "Common/StbCommon.h"
#endif
+10 -3
View File
@@ -63,7 +63,7 @@ inline int select_fseek(FILE *file, int64_t offset, int origin) {
#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
template <>
inline size_t select_ftell<8>(FILE *file) {
return (size_t)::_ftelli64(file);
@@ -74,7 +74,7 @@ inline int select_fseek<8>(FILE *file, int64_t offset, int origin) {
return ::_fseeki64(file, offset, origin);
}
#endif // #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
#endif
} // namespace
@@ -149,13 +149,20 @@ size_t DefaultIOStream::FileSize() const {
//
// See here for details:
// https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
struct __stat64 fileStat;
//using fileno + fstat avoids having to handle the filename
int err = _fstat64(_fileno(mFile), &fileStat);
if (0 != err)
return 0;
mCachedSize = (size_t)(fileStat.st_size);
#elif defined _WIN32
struct _stat32 fileStat;
//using fileno + fstat avoids having to handle the filename
int err = _fstat32(_fileno(mFile), &fileStat);
if (0 != err)
return 0;
mCachedSize = (size_t)(fileStat.st_size);
#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
struct stat fileStat;
int err = stat(mFilename.c_str(), &fileStat);
+2 -2
View File
@@ -300,10 +300,10 @@ private:
const char separator = getOsSeparator();
for (it = in.begin(); it != in.end(); ++it) {
int remaining = std::distance(in.end(), it);
const size_t remaining = std::distance(in.end(), it);
// Exclude :// and \\, which remain untouched.
// https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
if (remaining >= 3 && !strncmp(&*it, "://", 3 )) {
if (remaining >= 3u && !strncmp(&*it, "://", 3 )) {
it += 3;
continue;
}
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include <assimp/ai_assert.h>
template <typename T>
struct Maybe {
private:
T _val;
bool _valid;
public:
Maybe() :
_valid(false) {}
explicit Maybe(const T &val) :
_val(val), _valid(true) {
}
operator bool() const {
return _valid;
}
const T &Get() const {
ai_assert(_valid);
return _val;
}
private:
Maybe &operator&() = delete;
};
+30 -27
View File
@@ -105,36 +105,39 @@ void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!mesh->mTextureCoords[i]) {
mesh->mNumUVComponents[i] = 0;
} else {
if (!mesh->mNumUVComponents[i]) {
mesh->mNumUVComponents[i] = 2;
continue;
}
if (!mesh->mNumUVComponents[i]) {
mesh->mNumUVComponents[i] = 2;
}
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
// Ensure unused components are zeroed. This will make 1D texture channels work
// as if they were 2D channels .. just in case an application doesn't handle
// this case
if (2 == mesh->mNumUVComponents[i]) {
size_t num = 0;
for (; p != end; ++p) {
p->z = 0.f;
num++;
}
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
// Ensure unused components are zeroed. This will make 1D texture channels work
// as if they were 2D channels .. just in case an application doesn't handle
// this case
if (2 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p) {
p->z = 0.f;
}
} else if (1 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p) {
p->z = p->y = 0.f;
}
} else if (3 == mesh->mNumUVComponents[i]) {
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
for (; p != end; ++p) {
if (p->z != 0) {
break;
}
}
if (p == end) {
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
mesh->mNumUVComponents[i] = 2;
} else if (1 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p) {
p->z = p->y = 0.f;
}
} else if (3 == mesh->mNumUVComponents[i]) {
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
for (; p != end; ++p) {
if (p->z != 0) {
break;
}
}
if (p == end) {
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
mesh->mNumUVComponents[i] = 2;
}
}
}
+8 -6
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,
@@ -97,13 +96,14 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation;
aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4);
ai_real distanceToChild = childpos.Length();
if (distanceToChild < 0.0001)
if (distanceToChild < ai_epsilon) {
continue;
}
aiVector3D up = aiVector3D(childpos).Normalize();
aiVector3D orth(1.0, 0.0, 0.0);
if (std::fabs(orth * up) > 0.99)
if (std::fabs(orth * up) > 0.99) {
orth.Set(0.0, 1.0, 0.0);
}
aiVector3D front = (up ^ orth).Normalize();
aiVector3D side = (front ^ up).Normalize();
@@ -183,8 +183,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
// add all the vertices to the bone's influences
bone->mNumWeights = numVertices;
bone->mWeights = new aiVertexWeight[numVertices];
for (unsigned int a = 0; a < numVertices; a++)
for (unsigned int a = 0; a < numVertices; ++a) {
bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0);
}
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
// them to the array, but I'm tired now and I'm annoyed.
@@ -194,8 +195,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
}
// and finally recurse into the children list
for (unsigned int a = 0; a < pNode->mNumChildren; a++)
for (unsigned int a = 0; a < pNode->mNumChildren; ++a) {
CreateGeometry(pNode->mChildren[a]);
}
}
// ------------------------------------------------------------------------------------------------
+58
View File
@@ -0,0 +1,58 @@
/*
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,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#pragma once
#if _MSC_VER // "unreferenced function has been removed" (SSE2 detection routine in x64 builds)
#pragma warning(push)
#pragma warning(disable : 4505)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include "stb/stb_image.h"
#if _MSC_VER
#pragma warning(pop)
#else
#pragma GCC diagnostic pop
#endif
+5 -1
View File
@@ -135,6 +135,9 @@ ASSIMP_API aiScene::aiScene() :
mNumCameras(0),
mCameras(nullptr),
mMetaData(nullptr),
mName(),
mNumSkeletons(0),
mSkeletons(nullptr),
mPrivate(new Assimp::ScenePrivateData()) {
// empty
}
@@ -180,7 +183,8 @@ ASSIMP_API aiScene::~aiScene() {
delete[] mCameras;
aiMetadata::Dealloc(mMetaData);
mMetaData = nullptr;
delete[] mSkeletons;
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
}
+2
View File
@@ -196,7 +196,9 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
zlib_filefunc_def mapping;
mapping.zopen_file = (open_file_func)open;
#ifdef _UNZ_H
mapping.zopendisk_file = (opendisk_file_func)opendisk;
#endif
mapping.zread_file = (read_file_func)read;
mapping.zwrite_file = (write_file_func)write;
mapping.ztell_file = (tell_file_func)tell;
+1 -1
View File
@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h>
// -------------------------------------------------------------------------------
const char *TextureTypeToString(aiTextureType in) {
const char *aiTextureTypeToString(aiTextureType in) {
switch (in) {
case aiTextureType_NONE:
return "n/a";
+2 -2
View File
@@ -83,7 +83,7 @@ Other:
#include <sstream>
#include <string>
#include "stb/stb_image.h"
#include "Common/StbCommon.h"
using namespace Assimp;
@@ -590,7 +590,7 @@ void PbrtExporter::WriteMaterial(int m) {
for (int i = 1; i <= aiTextureType_UNKNOWN; i++) {
int count = material->GetTextureCount(aiTextureType(i));
if (count > 0)
mOutput << TextureTypeToString(aiTextureType(i)) << ": " << count << " ";
mOutput << aiTextureTypeToString(aiTextureType(i)) << ": " << count << " ";
}
mOutput << "\n";
@@ -415,7 +415,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
if (!DefaultLogger::isNullLogger())
{
ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
aiTextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
MappingTypeToString(mapping));
ASSIMP_LOG_INFO(buffer);
+1 -1
View File
@@ -128,7 +128,7 @@ bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path)
aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
pFile->Seek(0, aiOrigin_SET);
pFile->Read(reinterpret_cast<char*>(imageContent), imageSize, 1);
pFile->Read(reinterpret_cast<char*>(imageContent), static_cast<size_t>(imageSize), 1);
mIOHandler->Close(pFile);
// Enlarging the textures table
+75 -93
View File
@@ -5,8 +5,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,
@@ -45,41 +43,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* for all imported meshes
*/
#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
#include "JoinVerticesProcess.h"
#include "ProcessHelper.h"
#include <assimp/Vertex.h>
#include <assimp/TinyFormatter.h>
#include <stdio.h>
#include <unordered_set>
#include <unordered_map>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
JoinVerticesProcess::JoinVerticesProcess()
{
JoinVerticesProcess::JoinVerticesProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
JoinVerticesProcess::~JoinVerticesProcess()
{
JoinVerticesProcess::~JoinVerticesProcess() {
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
{
bool JoinVerticesProcess::IsActive( unsigned int pFlags) const {
return (pFlags & aiProcess_JoinIdenticalVertices) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void JoinVerticesProcess::Execute( aiScene* pScene)
{
void JoinVerticesProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("JoinVerticesProcess begin");
// get the total number of vertices BEFORE the step is executed
@@ -92,27 +87,29 @@ void JoinVerticesProcess::Execute( aiScene* pScene)
// execute the step
int iNumVertices = 0;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
}
pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
// if logging is active, print detailed statistics
if (!DefaultLogger::isNullLogger()) {
if (iNumOldVertices == iNumVertices) {
ASSIMP_LOG_DEBUG("JoinVerticesProcess finished ");
} else {
ASSIMP_LOG_INFO("JoinVerticesProcess finished | Verts in: ", iNumOldVertices,
" out: ", iNumVertices, " | ~",
((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f );
return;
}
// Show statistics
ASSIMP_LOG_INFO("JoinVerticesProcess finished | Verts in: ", iNumOldVertices,
" out: ", iNumVertices, " | ~",
((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f );
}
pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
}
namespace {
bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex)
{
bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) {
// A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f;
@@ -171,8 +168,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
// ----------------------------------------------------------------------------
// Position, if present (check made for aiAnimMesh)
if (pMesh->mVertices)
{
if (pMesh->mVertices) {
delete [] pMesh->mVertices;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@@ -181,8 +177,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
// Normals, if present
if (pMesh->mNormals)
{
if (pMesh->mNormals) {
delete [] pMesh->mNormals;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@@ -190,8 +185,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
}
// Tangents, if present
if (pMesh->mTangents)
{
if (pMesh->mTangents) {
delete [] pMesh->mTangents;
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@@ -199,8 +193,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
}
// Bitangents as well
if (pMesh->mBitangents)
{
if (pMesh->mBitangents) {
delete [] pMesh->mBitangents;
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@@ -208,8 +201,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
}
// Vertex colors
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
{
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) {
delete [] pMesh->mColors[a];
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
@@ -217,8 +209,7 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
}
// Texture coords
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
{
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) {
delete [] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
@@ -226,12 +217,40 @@ void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
{
// combine hashes
inline void hash_combine(std::size_t &) {
// empty
}
template <typename T, typename... Rest>
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
hash_combine(seed, rest...);
}
//template specialization for std::hash for Vertex
template<>
struct std::hash<Vertex> {
std::size_t operator()(Vertex const& v) const noexcept {
size_t seed = 0;
hash_combine(seed, v.position.x ,v.position.y,v.position.z);
return seed;
}
};
//template specialization for std::equal_to for Vertex
template<>
struct std::equal_to<Vertex> {
bool operator()(const Vertex &lhs, const Vertex &rhs) const {
return areVerticesEqual(lhs, rhs, false);
}
};
// now start the JoinVerticesProcess
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
static_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 8, "AI_MAX_NUMBER_OF_COLOR_SETS == 8");
static_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8, "AI_MAX_NUMBER_OF_TEXTURECOORDS == 8");
@@ -245,8 +264,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// multiple meshes)
std::unordered_set<unsigned int> usedVertexIndices;
usedVertexIndices.reserve(pMesh->mNumVertices);
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
aiFace& face = pMesh->mFaces[a];
for( unsigned int b = 0; b < face.mNumIndices; b++) {
usedVertexIndices.insert(face.mIndices[b]);
@@ -292,7 +310,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// Run an optimized code path if we don't have multiple UVs or vertex colors.
// This should yield false in more than 99% of all imports ...
const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
// We'll never have more vertices afterwards.
@@ -303,72 +320,38 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
}
}
// a map that maps a vertix to its new index
std::unordered_map<Vertex,int> vertex2Index;
// we can not end up with more vertices than we started with
vertex2Index.reserve(pMesh->mNumVertices);
// Now check each vertex if it brings something new to the table
int newIndex = 0;
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
// if the vertex is unused Do nothing
if (usedVertexIndices.find(a) == usedVertexIndices.end()) {
continue;
}
// collect the vertex data
Vertex v(pMesh,a);
// collect all vertices that are close enough to the given position
vertexFinder->FindIdenticalPositions( v.position, verticesFound);
unsigned int matchIndex = 0xffffffff;
// check all unique vertices close to the position if this vertex is already present among them
for( unsigned int b = 0; b < verticesFound.size(); b++) {
const unsigned int vidx = verticesFound[b];
const unsigned int uidx = replaceIndex[ vidx];
if( uidx & 0x80000000)
continue;
const Vertex& uv = uniqueVertices[ uidx];
if (!areVerticesEqual(v, uv, complex)) {
continue;
}
if (hasAnimMeshes) {
// If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology)
// NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces)
bool breaksAnimMesh = false;
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx];
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) {
breaksAnimMesh = true;
break;
}
}
if (breaksAnimMesh) {
continue;
}
}
// we're still here -> this vertex perfectly matches our given vertex
matchIndex = uidx;
break;
}
// found a replacement vertex among the uniques?
if( matchIndex != 0xffffffff)
{
// store where to found the matching unique vertex
replaceIndex[a] = matchIndex | 0x80000000;
}
else
{
// no unique vertex matches it up to now -> so add it
replaceIndex[a] = (unsigned int)uniqueVertices.size();
uniqueVertices.push_back( v);
// is the vertex already in the map?
auto it = vertex2Index.find(v);
// if the vertex is not in the map then it is a new vertex add it.
if (it == vertex2Index.end()) {
// this is a new vertex give it a new index
vertex2Index[v] = newIndex;
//keep track of its index and increment 1
replaceIndex[a] = newIndex++;
// add the vertex to the unique vertices
uniqueVertices.push_back(v);
if (hasAnimMeshes) {
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex);
uniqueAnimatedVertices[animMeshIndex].push_back(v);
}
}
} else{
// if the vertex is already there just find the replace index that is appropriate to it
replaceIndex[a] = it->second;
}
}
@@ -394,8 +377,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
}
// adjust the indices in all faces
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
aiFace& face = pMesh->mFaces[a];
for( unsigned int b = 0; b < face.mNumIndices; b++) {
face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000;
@@ -521,7 +521,7 @@ void ValidateDSProcess::Validate(const aiAnimation *pAnimation) {
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial *pMaterial,
aiTextureType type) {
const char *szType = TextureTypeToString(type);
const char *szType = aiTextureTypeToString(type);
// ****************************************************************************
// Search all keys of the material ...
+16 -55
View File
@@ -1,80 +1,41 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#include "revision.h"
#ifdef __GNUC__
#include "winresrc.h"
#else
#include "winres.h"
#endif
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Deutsch (Deutschland) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_FILEVERSION
FILEFLAGSMASK 0x17L
FILEFLAGSMASK VS_FF_DEBUG
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
FILEFLAGS VS_FF_DEBUG
#endif
FILEOS 0x4L
FILETYPE 0x7L
FILESUBTYPE 0x0L
FILEOS VOS_NT
FILETYPE VFT_DLL
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040704b0"
BLOCK "000004B0"
BEGIN
VALUE "Comments", "Licensed under a 3-clause BSD license"
VALUE "CompanyName", "assimp team"
VALUE "CompanyName", "ASSIMP Team"
VALUE "FileDescription", "Open Asset Import Library"
VALUE "FileVersion", VER_FILEVERSION
VALUE "InternalName", "assimp "
VALUE "LegalCopyright", "Copyright (C) 2006-2020"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "assimp"
VALUE "LegalCopyright", VER_COPYRIGHT_STR
VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR
VALUE "ProductName", "Open Asset Import Library"
VALUE "ProductVersion", VER_FILEVERSION_STR
,0
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x407, 1200
VALUE "Translation", 0x0, 65001
END
END
#endif // Deutsch (Deutschland) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
-14
View File
@@ -1,14 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by assimp.rc
// Next standard values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif