closes https://github.com/assimp/assimp/issues/1044: set default value in case of light intensity envelopes-

pull/3495/head
Kim Kulling 2020-11-11 19:38:42 +01:00
parent de610b8ce9
commit 456b54988a
14 changed files with 2039 additions and 2374 deletions

View File

@ -123,20 +123,20 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader // Setup configuration properties for the loader
void FBXImporter::SetupProperties(const Importer *pImp) { void FBXImporter::SetupProperties(const Importer *pImp) {
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true); mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); mSettings.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); mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -181,10 +181,10 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
Parser parser(tokens, is_binary); Parser parser(tokens, is_binary);
// take the raw parse-tree and convert it to a FBX DOM // 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 // convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones); ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
// size relative to cm // size relative to cm
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor(); float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();

View File

@ -70,27 +70,16 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> { class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
public: public:
FBXImporter(); FBXImporter();
virtual ~FBXImporter(); ~FBXImporter() override;
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
// --------------------
bool CanRead(const std::string &pFile,
IOSystem *pIOHandler,
bool checkSig) const;
protected: protected:
// --------------------
const aiImporterDesc *GetInfo() const; const aiImporterDesc *GetInfo() const;
// --------------------
void SetupProperties(const Importer *pImp); void SetupProperties(const Importer *pImp);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
// --------------------
void InternReadFile(const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler);
private: private:
FBX::ImportSettings settings; FBX::ImportSettings mSettings;
}; // !class FBXImporter }; // !class FBXImporter
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -48,12 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <functional> #include <functional>
#include "FBXMeshGeometry.h"
#include "FBXDocument.h" #include "FBXDocument.h"
#include "FBXImporter.h"
#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXImportSettings.h"
#include "FBXImporter.h"
#include "FBXMeshGeometry.h"
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
@ -61,10 +60,8 @@ namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) Geometry::Geometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Object(id, element, name) Object(id, element, name), skin() {
, skin()
{
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer"); const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
for (const Connection *con : conns) { for (const Connection *con : conns) {
const Skin *const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element); const Skin *const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
@ -79,8 +76,7 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Geometry::~Geometry() Geometry::~Geometry() {
{
// empty // empty
} }
@ -95,9 +91,8 @@ const Skin* Geometry::DeformerSkin() const {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) MeshGeometry::MeshGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Geometry(id, element,name, doc) Geometry(id, element, name, doc) {
{
const Scope *sc = element.Compound(); const Scope *sc = element.Compound();
if (!sc) { if (!sc) {
DOMError("failed to read Geometry object (class: Mesh), no data scope found"); DOMError("failed to read Geometry object (class: Mesh), no data scope found");
@ -183,8 +178,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
if (doc.Settings().readAllLayers || index == 0) { if (doc.Settings().readAllLayers || index == 0) {
const Scope &layer = GetRequiredScope(*(*it).second); const Scope &layer = GetRequiredScope(*(*it).second);
ReadLayer(layer); ReadLayer(layer);
} } else {
else {
FBXImporter::LogWarn("ignoring additional geometry layers"); FBXImporter::LogWarn("ignoring additional geometry layers");
} }
} }
@ -269,15 +263,13 @@ unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
const std::vector<unsigned int>::iterator it = std::upper_bound( const std::vector<unsigned int>::iterator it = std::upper_bound(
m_facesVertexStartIndices.begin(), m_facesVertexStartIndices.begin(),
m_facesVertexStartIndices.end(), m_facesVertexStartIndices.end(),
in_index in_index);
);
return static_cast<unsigned int>(std::distance(m_facesVertexStartIndices.begin(), it - 1)); return static_cast<unsigned int>(std::distance(m_facesVertexStartIndices.begin(), it - 1));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadLayer(const Scope& layer) void MeshGeometry::ReadLayer(const Scope &layer) {
{
const ElementCollection &LayerElement = layer.GetCollection("LayerElement"); const ElementCollection &LayerElement = layer.GetCollection("LayerElement");
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) { for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
const Scope &elayer = GetRequiredScope(*(*eit).second); const Scope &elayer = GetRequiredScope(*(*eit).second);
@ -286,10 +278,8 @@ void MeshGeometry::ReadLayer(const Scope& layer)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadLayerElement(const Scope& layerElement) void MeshGeometry::ReadLayerElement(const Scope &layerElement) {
{
const Element &Type = GetRequiredElement(layerElement, "Type"); const Element &Type = GetRequiredElement(layerElement, "Type");
const Element &TypedIndex = GetRequiredElement(layerElement, "TypedIndex"); const Element &TypedIndex = GetRequiredElement(layerElement, "TypedIndex");
@ -312,15 +302,12 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source) void MeshGeometry::ReadVertexData(const std::string &type, int index, const Scope &source) {
{
const std::string &MappingInformationType = ParseTokenAsString(GetRequiredToken( const std::string &MappingInformationType = ParseTokenAsString(GetRequiredToken(
GetRequiredElement(source,"MappingInformationType"),0) GetRequiredElement(source, "MappingInformationType"), 0));
);
const std::string &ReferenceInformationType = ParseTokenAsString(GetRequiredToken( const std::string &ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
GetRequiredElement(source,"ReferenceInformationType"),0) GetRequiredElement(source, "ReferenceInformationType"), 0));
);
if (type == "LayerElementUV") { if (type == "LayerElementUV") {
if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
@ -337,10 +324,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataUV(m_uvs[index], source, ReadVertexDataUV(m_uvs[index], source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
); } else if (type == "LayerElementMaterial") {
}
else if (type == "LayerElementMaterial") {
if (m_materials.size() > 0) { if (m_materials.size() > 0) {
FBXImporter::LogError("ignoring additional material layer"); FBXImporter::LogError("ignoring additional material layer");
return; return;
@ -350,8 +335,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataMaterials(temp_materials, source, ReadVertexDataMaterials(temp_materials, source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
);
// sometimes, there will be only negative entries. Drop the material // sometimes, there will be only negative entries. Drop the material
// layer in such a case (I guess it means a default material should // layer in such a case (I guess it means a default material should
@ -366,8 +350,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
} }
std::swap(temp_materials, m_materials); std::swap(temp_materials, m_materials);
} } else if (type == "LayerElementNormal") {
else if (type == "LayerElementNormal") {
if (m_normals.size() > 0) { if (m_normals.size() > 0) {
FBXImporter::LogError("ignoring additional normal layer"); FBXImporter::LogError("ignoring additional normal layer");
return; return;
@ -375,10 +358,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataNormals(m_normals, source, ReadVertexDataNormals(m_normals, source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
); } else if (type == "LayerElementTangent") {
}
else if (type == "LayerElementTangent") {
if (m_tangents.size() > 0) { if (m_tangents.size() > 0) {
FBXImporter::LogError("ignoring additional tangent layer"); FBXImporter::LogError("ignoring additional tangent layer");
return; return;
@ -386,10 +367,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataTangents(m_tangents, source, ReadVertexDataTangents(m_tangents, source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
); } else if (type == "LayerElementBinormal") {
}
else if (type == "LayerElementBinormal") {
if (m_binormals.size() > 0) { if (m_binormals.size() > 0) {
FBXImporter::LogError("ignoring additional binormal layer"); FBXImporter::LogError("ignoring additional binormal layer");
return; return;
@ -397,10 +376,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataBinormals(m_binormals, source, ReadVertexDataBinormals(m_binormals, source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
); } else if (type == "LayerElementColor") {
}
else if (type == "LayerElementColor") {
if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) { if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ") FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
<< index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")"); << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")");
@ -409,8 +386,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
ReadVertexDataColors(m_colors[index], source, ReadVertexDataColors(m_colors[index], source,
MappingInformationType, MappingInformationType,
ReferenceInformationType ReferenceInformationType);
);
} }
} }
@ -427,8 +403,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
size_t vertex_count, size_t vertex_count,
const std::vector<unsigned int> &mapping_counts, const std::vector<unsigned int> &mapping_counts,
const std::vector<unsigned int> &mapping_offsets, const std::vector<unsigned int> &mapping_offsets,
const std::vector<unsigned int>& mappings) const std::vector<unsigned int> &mappings) {
{
bool isDirect = ReferenceInformationType == "Direct"; bool isDirect = ReferenceInformationType == "Direct";
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect"; bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
@ -461,8 +436,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out[mappings[j]] = tempData[i]; data_out[mappings[j]] = tempData[i];
} }
} }
} } else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
std::vector<T> tempData; std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
@ -487,21 +461,18 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out[mappings[j]] = tempData[uvIndices[i]]; data_out[mappings[j]] = tempData[uvIndices[i]];
} }
} }
} } else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
std::vector<T> tempData; std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
if (tempData.size() != vertex_count) { if (tempData.size() != vertex_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
<< tempData.size() << ", expected " << vertex_count << tempData.size() << ", expected " << vertex_count);
);
return; return;
} }
data_out.swap(tempData); data_out.swap(tempData);
} } else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
std::vector<T> tempData; std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
@ -529,8 +500,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out[next++] = tempData[i]; data_out[next++] = tempData[i];
} }
} } else {
else {
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ") FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
<< MappingInformationType << "," << ReferenceInformationType); << MappingInformationType << "," << ReferenceInformationType);
} }
@ -539,8 +509,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D> &normals_out, const Scope &source, void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D> &normals_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
ResolveVertexDataArray(normals_out, source, MappingInformationType, ReferenceInformationType, ResolveVertexDataArray(normals_out, source, MappingInformationType, ReferenceInformationType,
"Normals", "Normals",
"NormalsIndex", "NormalsIndex",
@ -553,8 +522,7 @@ void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, c
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D> &uv_out, const Scope &source, void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D> &uv_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
ResolveVertexDataArray(uv_out, source, MappingInformationType, ReferenceInformationType, ResolveVertexDataArray(uv_out, source, MappingInformationType, ReferenceInformationType,
"UV", "UV",
"UVIndex", "UVIndex",
@ -567,8 +535,7 @@ void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D> &colors_out, const Scope &source, void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D> &colors_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
ResolveVertexDataArray(colors_out, source, MappingInformationType, ReferenceInformationType, ResolveVertexDataArray(colors_out, source, MappingInformationType, ReferenceInformationType,
"Colors", "Colors",
"ColorIndex", "ColorIndex",
@ -584,8 +551,7 @@ static const char *TangentsIndexToken = "TangentsIndex";
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D> &tangents_out, const Scope &source, void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D> &tangents_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
const char *str = source.Elements().count("Tangents") > 0 ? "Tangents" : "Tangent"; const char *str = source.Elements().count("Tangents") > 0 ? "Tangents" : "Tangent";
const char *strIdx = source.Elements().count("Tangents") > 0 ? TangentsIndexToken : TangentIndexToken; const char *strIdx = source.Elements().count("Tangents") > 0 ? TangentsIndexToken : TangentIndexToken;
ResolveVertexDataArray(tangents_out, source, MappingInformationType, ReferenceInformationType, ResolveVertexDataArray(tangents_out, source, MappingInformationType, ReferenceInformationType,
@ -603,8 +569,7 @@ static const std::string BinormalsIndexToken = "BinormalsIndex";
void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D> &binormals_out, const Scope &source, void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D> &binormals_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
const char *str = source.Elements().count("Binormals") > 0 ? "Binormals" : "Binormal"; const char *str = source.Elements().count("Binormals") > 0 ? "Binormals" : "Binormal";
const char *strIdx = source.Elements().count("Binormals") > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str(); const char *strIdx = source.Elements().count("Binormals") > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
ResolveVertexDataArray(binormals_out, source, MappingInformationType, ReferenceInformationType, ResolveVertexDataArray(binormals_out, source, MappingInformationType, ReferenceInformationType,
@ -616,15 +581,12 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
m_mappings); m_mappings);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexDataMaterials(std::vector<int> &materials_out, const Scope &source, void MeshGeometry::ReadVertexDataMaterials(std::vector<int> &materials_out, const Scope &source,
const std::string &MappingInformationType, const std::string &MappingInformationType,
const std::string& ReferenceInformationType) const std::string &ReferenceInformationType) {
{
const size_t face_count = m_faces.size(); const size_t face_count = m_faces.size();
if( 0 == face_count ) if (0 == face_count) {
{
return; return;
} }
@ -650,8 +612,7 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
if (materials_out.size() != face_count) { if (materials_out.size() != face_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
<< materials_out.size() << ", expected " << face_count << materials_out.size() << ", expected " << face_count);
);
return; return;
} }
} else { } else {
@ -660,8 +621,8 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) ShapeGeometry::ShapeGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Geometry(id, element, name, doc) { Geometry(id, element, name, doc) {
const Scope *sc = element.Compound(); const Scope *sc = element.Compound();
if (nullptr == sc) { if (nullptr == sc) {
DOMError("failed to read Geometry object (class: Shape), no data scope found"); DOMError("failed to read Geometry object (class: Shape), no data scope found");
@ -691,9 +652,8 @@ const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
return m_indices; return m_indices;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) LineGeometry::LineGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
: Geometry(id, element, name, doc) Geometry(id, element, name, doc) {
{
const Scope *sc = element.Compound(); const Scope *sc = element.Compound();
if (!sc) { if (!sc) {
DOMError("failed to read Geometry object (class: Line), no data scope found"); DOMError("failed to read Geometry object (class: Line), no data scope found");
@ -716,7 +676,6 @@ const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
const std::vector<int> &LineGeometry::GetIndices() const { const std::vector<int> &LineGeometry::GetIndices() const {
return m_indices; return m_indices;
} }
} // !FBX } // namespace FBX
} // !Assimp } // namespace Assimp
#endif #endif

View File

@ -52,13 +52,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../contrib/zlib/zlib.h" #include "../contrib/zlib/zlib.h"
#endif #endif
#include "FBXTokenizer.h"
#include "FBXParser.h" #include "FBXParser.h"
#include "FBXTokenizer.h"
#include "FBXUtil.h" #include "FBXUtil.h"
#include <assimp/ByteSwapper.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/ByteSwapper.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <iostream> #include <iostream>
@ -71,25 +71,21 @@ namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// signal parse error, this is always unrecoverable. Throws DeadlyImportError. // signal parse error, this is always unrecoverable. Throws DeadlyImportError.
AI_WONT_RETURN void ParseError(const std::string &message, const Token &token) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ParseError(const std::string &message, const Token &token) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN void ParseError(const std::string &message, const Token &token) {
{
throw DeadlyImportError("FBX-Parser", Util::GetTokenText(&token), message); throw DeadlyImportError("FBX-Parser", Util::GetTokenText(&token), message);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void ParseError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ParseError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void ParseError(const std::string& message, const Element* element) AI_WONT_RETURN void ParseError(const std::string &message, const Element *element) {
{
if (element) { if (element) {
ParseError(message, element->KeyToken()); ParseError(message, element->KeyToken());
} }
throw DeadlyImportError("FBX-Parser ", message); throw DeadlyImportError("FBX-Parser ", message);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ParseError(const std::string& message, TokenPtr token) void ParseError(const std::string &message, TokenPtr token) {
{
if (token) { if (token) {
ParseError(message, *token); ParseError(message, *token);
} }
@ -109,15 +105,14 @@ namespace {
::memcpy(&result, data, sizeof(T)); ::memcpy(&result, data, sizeof(T));
return result; return result;
} }
} } // namespace
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Element::Element(const Token& key_token, Parser& parser) Element::Element(const Token &key_token, Parser &parser) :
: key_token(key_token) key_token(key_token) {
{
TokenPtr n = nullptr; TokenPtr n = nullptr;
do { do {
n = parser.AdvanceToNextToken(); n = parser.AdvanceToNextToken();
@ -160,19 +155,16 @@ Element::Element(const Token& key_token, Parser& parser)
parser.AdvanceToNextToken(); parser.AdvanceToNextToken();
return; return;
} }
} } while (n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Element::~Element() Element::~Element() {
{
// no need to delete tokens, they are owned by the parser // no need to delete tokens, they are owned by the parser
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Scope::Scope(Parser& parser,bool topLevel) Scope::Scope(Parser &parser, bool topLevel) {
{
if (!topLevel) { if (!topLevel) {
TokenPtr t = parser.CurrentToken(); TokenPtr t = parser.CurrentToken();
if (t->Type() != TokenType_OPEN_BRACKET) { if (t->Type() != TokenType_OPEN_BRACKET) {
@ -206,34 +198,26 @@ Scope::Scope(Parser& parser,bool topLevel)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Scope::~Scope() Scope::~Scope() {
{
for (ElementMap::value_type &v : elements) { for (ElementMap::value_type &v : elements) {
delete v.second; delete v.second;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Parser::Parser (const TokenList& tokens, bool is_binary) Parser::Parser(const TokenList &tokens, bool is_binary) :
: tokens(tokens) tokens(tokens), last(), current(), cursor(tokens.begin()), is_binary(is_binary) {
, last()
, current()
, cursor(tokens.begin())
, is_binary(is_binary)
{
ASSIMP_LOG_DEBUG("Parsing FBX tokens"); ASSIMP_LOG_DEBUG("Parsing FBX tokens");
root.reset(new Scope(*this, true)); root.reset(new Scope(*this, true));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Parser::~Parser() Parser::~Parser() {
{
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken() TokenPtr Parser::AdvanceToNextToken() {
{
last = current; last = current;
if (cursor == tokens.end()) { if (cursor == tokens.end()) {
current = nullptr; current = nullptr;
@ -244,20 +228,17 @@ TokenPtr Parser::AdvanceToNextToken()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::CurrentToken() const TokenPtr Parser::CurrentToken() const {
{
return current; return current;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const TokenPtr Parser::LastToken() const {
{
return last; return last;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(const Token& t, const char*& err_out) uint64_t ParseTokenAsID(const Token &t, const char *&err_out) {
{
err_out = nullptr; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
@ -265,8 +246,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return 0L; return 0L;
} }
if(t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'L') { if (data[0] != 'L') {
err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)"; err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
@ -293,8 +273,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
size_t ParseTokenAsDim(const Token& t, const char*& err_out) size_t ParseTokenAsDim(const Token &t, const char *&err_out) {
{
// same as ID parsing, except there is a trailing asterisk // same as ID parsing, except there is a trailing asterisk
err_out = nullptr; err_out = nullptr;
@ -303,8 +282,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0; return 0;
} }
if(t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'L') { if (data[0] != 'L') {
err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)"; err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
@ -338,10 +316,8 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return id; return id;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
float ParseTokenAsFloat(const Token& t, const char*& err_out) float ParseTokenAsFloat(const Token &t, const char *&err_out) {
{
err_out = nullptr; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
@ -349,8 +325,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
return 0.0f; return 0.0f;
} }
if(t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'F' && data[0] != 'D') { if (data[0] != 'F' && data[0] != 'D') {
err_out = "failed to parse F(loat) or D(ouble), unexpected data type (binary)"; err_out = "failed to parse F(loat) or D(ouble), unexpected data type (binary)";
@ -359,8 +334,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
if (data[0] == 'F') { if (data[0] == 'F') {
return SafeParse<float>(data + 1, t.end()); return SafeParse<float>(data + 1, t.end());
} } else {
else {
return static_cast<float>(SafeParse<double>(data + 1, t.end())); return static_cast<float>(SafeParse<double>(data + 1, t.end()));
} }
} }
@ -381,10 +355,8 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
return fast_atof(temp); return fast_atof(temp);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int ParseTokenAsInt(const Token& t, const char*& err_out) int ParseTokenAsInt(const Token &t, const char *&err_out) {
{
err_out = nullptr; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
@ -392,8 +364,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
return 0; return 0;
} }
if(t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'I') { if (data[0] != 'I') {
err_out = "failed to parse I(nt), unexpected data type (binary)"; err_out = "failed to parse I(nt), unexpected data type (binary)";
@ -417,10 +388,8 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
return intval; return intval;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) int64_t ParseTokenAsInt64(const Token &t, const char *&err_out) {
{
err_out = nullptr; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
@ -428,8 +397,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
return 0L; return 0L;
} }
if (t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'L') { if (data[0] != 'L') {
err_out = "failed to parse Int64, unexpected data type"; err_out = "failed to parse Int64, unexpected data type";
@ -456,8 +424,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ParseTokenAsString(const Token& t, const char*& err_out) std::string ParseTokenAsString(const Token &t, const char *&err_out) {
{
err_out = nullptr; err_out = nullptr;
if (t.Type() != TokenType_DATA) { if (t.Type() != TokenType_DATA) {
@ -465,8 +432,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
return ""; return "";
} }
if(t.IsBinary()) if (t.IsBinary()) {
{
const char *data = t.begin(); const char *data = t.begin();
if (data[0] != 'S') { if (data[0] != 'S') {
err_out = "failed to parse S(tring), unexpected data type (binary)"; err_out = "failed to parse S(tring), unexpected data type (binary)";
@ -496,14 +462,12 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
return std::string(s + 1, length - 2); return std::string(s + 1, length - 2);
} }
namespace { namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read the type code and element count of a binary data array and stop there // read the type code and element count of a binary data array and stop there
void ReadBinaryDataArrayHead(const char *&data, const char *end, char &type, uint32_t &count, void ReadBinaryDataArrayHead(const char *&data, const char *end, char &type, uint32_t &count,
const Element& el) const Element &el) {
{
if (static_cast<size_t>(end - data) < 5) { if (static_cast<size_t>(end - data) < 5) {
ParseError("binary data array is too short, need five (5) bytes for type signature and element count", &el); ParseError("binary data array is too short, need five (5) bytes for type signature and element count", &el);
} }
@ -519,13 +483,11 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
data += 5; data += 5;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header) // read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
void ReadBinaryDataArray(char type, uint32_t count, const char *&data, const char *end, void ReadBinaryDataArray(char type, uint32_t count, const char *&data, const char *end,
std::vector<char> &buff, std::vector<char> &buff,
const Element& /*el*/) const Element & /*el*/) {
{
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end); BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
AI_SWAP4(encmode); AI_SWAP4(encmode);
data += 4; data += 4;
@ -539,8 +501,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
// determine the length of the uncompressed data by looking at the type signature // determine the length of the uncompressed data by looking at the type signature
uint32_t stride = 0; uint32_t stride = 0;
switch(type) switch (type) {
{
case 'f': case 'f':
case 'i': case 'i':
stride = 4; stride = 4;
@ -563,8 +524,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
// plain data, no compression // plain data, no compression
std::copy(data, end, buff.begin()); std::copy(data, end, buff.begin());
} } else if (encmode == 1) {
else if(encmode == 1) {
// zlib/deflate, next comes ZIP head (0x78 0x01) // zlib/deflate, next comes ZIP head (0x78 0x01)
// see http://www.ietf.org/rfc/rfc1950.txt // see http://www.ietf.org/rfc/rfc1950.txt
@ -604,13 +564,11 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
ai_assert(data == end); ai_assert(data == end);
} }
} // !anon } // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of float3 tuples // read an array of float3 tuples
void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el) void ParseVectorDataArray(std::vector<aiVector3D> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
@ -660,8 +618,7 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl; stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl;
DefaultLogger::get()->info( stream.str() ); DefaultLogger::get()->info( stream.str() );
}*/ }*/
} } else if (type == 'f') {
else if (type == 'f') {
const float *f = reinterpret_cast<const float *>(&buff[0]); const float *f = reinterpret_cast<const float *>(&buff[0]);
for (unsigned int i = 0; i < count3; ++i, f += 3) { for (unsigned int i = 0; i < count3; ++i, f += 3) {
out.push_back(aiVector3D(f[0], f[1], f[2])); out.push_back(aiVector3D(f[0], f[1], f[2]));
@ -694,11 +651,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of color4 tuples // read an array of color4 tuples
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el) void ParseVectorDataArray(std::vector<aiColor4D> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -741,8 +696,7 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
static_cast<float>(d[2]), static_cast<float>(d[2]),
static_cast<float>(d[3]))); static_cast<float>(d[3])));
} }
} } else if (type == 'f') {
else if (type == 'f') {
const float *f = reinterpret_cast<const float *>(&buff[0]); const float *f = reinterpret_cast<const float *>(&buff[0]);
for (unsigned int i = 0; i < count4; ++i, f += 4) { for (unsigned int i = 0; i < count4; ++i, f += 4) {
out.push_back(aiColor4D(f[0], f[1], f[2], f[3])); out.push_back(aiColor4D(f[0], f[1], f[2], f[3]));
@ -773,11 +727,9 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of float2 tuples // read an array of float2 tuples
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) void ParseVectorDataArray(std::vector<aiVector2D> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -818,8 +770,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
out.push_back(aiVector2D(static_cast<float>(d[0]), out.push_back(aiVector2D(static_cast<float>(d[0]),
static_cast<float>(d[1]))); static_cast<float>(d[1])));
} }
} } else if (type == 'f') {
else if (type == 'f') {
const float *f = reinterpret_cast<const float *>(&buff[0]); const float *f = reinterpret_cast<const float *>(&buff[0]);
for (unsigned int i = 0; i < count2; ++i, f += 2) { for (unsigned int i = 0; i < count2; ++i, f += 2) {
out.push_back(aiVector2D(f[0], f[1])); out.push_back(aiVector2D(f[0], f[1]));
@ -849,11 +800,9 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of ints // read an array of ints
void ParseVectorDataArray(std::vector<int>& out, const Element& el) void ParseVectorDataArray(std::vector<int> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -907,11 +856,9 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of floats // read an array of floats
void ParseVectorDataArray(std::vector<float>& out, const Element& el) void ParseVectorDataArray(std::vector<float> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -944,8 +891,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
for (unsigned int i = 0; i < count; ++i, ++d) { for (unsigned int i = 0; i < count; ++i, ++d) {
out.push_back(static_cast<float>(*d)); out.push_back(static_cast<float>(*d));
} }
} } else if (type == 'f') {
else if (type == 'f') {
const float *f = reinterpret_cast<const float *>(&buff[0]); const float *f = reinterpret_cast<const float *>(&buff[0]);
for (unsigned int i = 0; i < count; ++i, ++f) { for (unsigned int i = 0; i < count; ++i, ++f) {
out.push_back(*f); out.push_back(*f);
@ -971,8 +917,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of uints // 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); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -1033,11 +978,9 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of uint64_ts // read an array of uint64_ts
void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el) void ParseVectorDataArray(std::vector<uint64_t> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -1094,8 +1037,7 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of int64_ts // read an array of int64_ts
void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el) void ParseVectorDataArray(std::vector<int64_t> &out, const Element &el) {
{
out.resize(0); out.resize(0);
const TokenList &tok = el.Tokens(); const TokenList &tok = el.Tokens();
if (tok.empty()) { if (tok.empty()) {
@ -1151,8 +1093,7 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMatrix4x4 ReadMatrix(const Element& element) aiMatrix4x4 ReadMatrix(const Element &element) {
{
std::vector<float> values; std::vector<float> values;
ParseVectorDataArray(values, element); ParseVectorDataArray(values, element);
@ -1162,7 +1103,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
aiMatrix4x4 result; aiMatrix4x4 result;
result.a1 = values[0]; result.a1 = values[0];
result.a2 = values[1]; result.a2 = values[1];
result.a3 = values[2]; result.a3 = values[2];
@ -1187,11 +1127,9 @@ aiMatrix4x4 ReadMatrix(const Element& element)
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsString() with ParseError handling // wrapper around ParseTokenAsString() with ParseError handling
std::string ParseTokenAsString(const Token& t) std::string ParseTokenAsString(const Token &t) {
{
const char *err; const char *err;
const std::string &i = ParseTokenAsString(t, err); const std::string &i = ParseTokenAsString(t, err);
if (err) { if (err) {
@ -1211,8 +1149,7 @@ bool HasElement( const Scope& sc, const std::string& index ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// extract a required element from a scope, abort if the element cannot be found // extract a required element from a scope, abort if the element cannot be found
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= nullptr*/) const Element &GetRequiredElement(const Scope &sc, const std::string &index, const Element *element /*= nullptr*/) {
{
const Element *el = sc[index]; const Element *el = sc[index];
if (!el) { if (!el) {
ParseError("did not find required element \"" + index + "\"", element); ParseError("did not find required element \"" + index + "\"", element);
@ -1220,11 +1157,9 @@ const Element& GetRequiredElement(const Scope& sc, const std::string& index, con
return *el; return *el;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// extract required compound scope // extract required compound scope
const Scope& GetRequiredScope(const Element& el) const Scope &GetRequiredScope(const Element &el) {
{
const Scope *const s = el.Compound(); const Scope *const s = el.Compound();
if (!s) { if (!s) {
ParseError("expected compound scope", &el); ParseError("expected compound scope", &el);
@ -1233,11 +1168,9 @@ const Scope& GetRequiredScope(const Element& el)
return *s; return *s;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// get token at a particular index // get token at a particular index
const Token& GetRequiredToken(const Element& el, unsigned int index) const Token &GetRequiredToken(const Element &el, unsigned int index) {
{
const TokenList &t = el.Tokens(); const TokenList &t = el.Tokens();
if (index >= t.size()) { if (index >= t.size()) {
ParseError(Formatter::format("missing token at index ") << index, &el); ParseError(Formatter::format("missing token at index ") << index, &el);
@ -1246,11 +1179,9 @@ const Token& GetRequiredToken(const Element& el, unsigned int index)
return *t[index]; return *t[index];
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsID() with ParseError handling // wrapper around ParseTokenAsID() with ParseError handling
uint64_t ParseTokenAsID(const Token& t) uint64_t ParseTokenAsID(const Token &t) {
{
const char *err; const char *err;
const uint64_t i = ParseTokenAsID(t, err); const uint64_t i = ParseTokenAsID(t, err);
if (err) { if (err) {
@ -1259,11 +1190,9 @@ uint64_t ParseTokenAsID(const Token& t)
return i; return i;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsDim() with ParseError handling // wrapper around ParseTokenAsDim() with ParseError handling
size_t ParseTokenAsDim(const Token& t) size_t ParseTokenAsDim(const Token &t) {
{
const char *err; const char *err;
const size_t i = ParseTokenAsDim(t, err); const size_t i = ParseTokenAsDim(t, err);
if (err) { if (err) {
@ -1272,11 +1201,9 @@ size_t ParseTokenAsDim(const Token& t)
return i; return i;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsFloat() with ParseError handling // wrapper around ParseTokenAsFloat() with ParseError handling
float ParseTokenAsFloat(const Token& t) float ParseTokenAsFloat(const Token &t) {
{
const char *err; const char *err;
const float i = ParseTokenAsFloat(t, err); const float i = ParseTokenAsFloat(t, err);
if (err) { if (err) {
@ -1287,8 +1214,7 @@ float ParseTokenAsFloat(const Token& t)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt() with ParseError handling // wrapper around ParseTokenAsInt() with ParseError handling
int ParseTokenAsInt(const Token& t) int ParseTokenAsInt(const Token &t) {
{
const char *err; const char *err;
const int i = ParseTokenAsInt(t, err); const int i = ParseTokenAsInt(t, err);
if (err) { if (err) {
@ -1299,8 +1225,7 @@ int ParseTokenAsInt(const Token& t)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsInt64() with ParseError handling // wrapper around ParseTokenAsInt64() with ParseError handling
int64_t ParseTokenAsInt64(const Token& t) int64_t ParseTokenAsInt64(const Token &t) {
{
const char *err; const char *err;
const int64_t i = ParseTokenAsInt64(t, err); const int64_t i = ParseTokenAsInt64(t, err);
if (err) { if (err) {
@ -1309,7 +1234,7 @@ int64_t ParseTokenAsInt64(const Token& t)
return i; return i;
} }
} // !FBX } // namespace FBX
} // !Assimp } // namespace Assimp
#endif #endif

View File

@ -66,8 +66,7 @@ void TempOpening::Transform(const IfcMatrix4& mat) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMesh* TempMesh::ToMesh() aiMesh *TempMesh::ToMesh() {
{
ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(), mVertcnt.end(), size_t(0))); ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(), mVertcnt.end(), size_t(0)));
if (mVerts.empty()) { if (mVerts.empty()) {
@ -105,36 +104,31 @@ aiMesh* TempMesh::ToMesh()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Clear() void TempMesh::Clear() {
{
mVerts.clear(); mVerts.clear();
mVertcnt.clear(); mVertcnt.clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Transform(const IfcMatrix4& mat) void TempMesh::Transform(const IfcMatrix4 &mat) {
{
for (IfcVector3 &v : mVerts) { for (IfcVector3 &v : mVerts) {
v *= mat; v *= mat;
} }
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
IfcVector3 TempMesh::Center() const IfcVector3 TempMesh::Center() const {
{
return (mVerts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(), mVerts.end(), IfcVector3()) / static_cast<IfcFloat>(mVerts.size())); return (mVerts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(), mVerts.end(), IfcVector3()) / static_cast<IfcFloat>(mVerts.size()));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Append(const TempMesh& other) void TempMesh::Append(const TempMesh &other) {
{
mVerts.insert(mVerts.end(), other.mVerts.begin(), other.mVerts.end()); mVerts.insert(mVerts.end(), other.mVerts.begin(), other.mVerts.end());
mVertcnt.insert(mVertcnt.end(), other.mVertcnt.begin(), other.mVertcnt.end()); mVertcnt.insert(mVertcnt.end(), other.mVertcnt.begin(), other.mVertcnt.end());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::RemoveDegenerates() void TempMesh::RemoveDegenerates() {
{
// The strategy is simple: walk the mesh and compute normals using // The strategy is simple: walk the mesh and compute normals using
// Newell's algorithm. The length of the normals gives the area // Newell's algorithm. The length of the normals gives the area
// of the polygons, which is close to zero for lines. // of the polygons, which is close to zero for lines.
@ -167,11 +161,10 @@ void TempMesh::RemoveDegenerates()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize) IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3 *vtcs, size_t cnt, bool normalize) {
{ const size_t Capa = cnt + 2;
std::vector<IfcFloat> temp((cnt+2)*3); std::vector<IfcFloat> temp((Capa)*3);
for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs ) for (size_t vofs = 0, i = 0; vofs < cnt; ++vofs) {
{
const IfcVector3 &v = vtcs[vofs]; const IfcVector3 &v = vtcs[vofs];
temp[i++] = v.x; temp[i++] = v.x;
temp[i++] = v.y; temp[i++] = v.y;
@ -179,22 +172,19 @@ IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bo
} }
IfcVector3 nor; IfcVector3 nor;
NewellNormal<3, 3, 3>(nor, static_cast<int>(cnt), &temp[0], &temp[1], &temp[2]); NewellNormal<3, 3, 3>(nor, static_cast<int>(cnt), &temp[0], &temp[1], &temp[2], Capa);
return normalize ? nor.Normalize() : nor; return normalize ? nor.Normalize() : nor;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals, void TempMesh::ComputePolygonNormals(std::vector<IfcVector3> &normals, bool normalize, size_t ofs) const {
bool normalize,
size_t ofs) const
{
size_t max_vcount = 0; size_t max_vcount = 0;
std::vector<unsigned int>::const_iterator begin = mVertcnt.begin() + ofs, end = mVertcnt.end(), iit; std::vector<unsigned int>::const_iterator begin = mVertcnt.begin() + ofs, end = mVertcnt.end(), iit;
for (iit = begin; iit != end; ++iit) { for (iit = begin; iit != end; ++iit) {
max_vcount = std::max(max_vcount, static_cast<size_t>(*iit)); max_vcount = std::max(max_vcount, static_cast<size_t>(*iit));
} }
const size_t Capa = max_vcount + 2;
std::vector<IfcFloat> temp((max_vcount+2)*4); std::vector<IfcFloat> temp(Capa * 4);
normals.reserve(normals.size() + mVertcnt.size() - ofs); normals.reserve(normals.size() + mVertcnt.size() - ofs);
// `NewellNormal()` currently has a relatively strange interface and need to // `NewellNormal()` currently has a relatively strange interface and need to
@ -217,7 +207,7 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
} }
normals.push_back(IfcVector3()); normals.push_back(IfcVector3());
NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]); NewellNormal<4, 4, 4>(normals.back(), *iit, &temp[0], &temp[1], &temp[2], Capa);
} }
if (normalize) { if (normalize) {
@ -229,30 +219,26 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Compute the normal of the last polygon in the given mesh // Compute the normal of the last polygon in the given mesh
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
{
return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize); return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize);
} }
struct CompareVector struct CompareVector {
{ bool operator()(const IfcVector3 &a, const IfcVector3 &b) const {
bool operator () (const IfcVector3& a, const IfcVector3& b) const
{
IfcVector3 d = a - b; IfcVector3 d = a - b;
IfcFloat eps = 1e-6; IfcFloat eps = 1e-6;
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps); return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
} }
}; };
struct FindVector struct FindVector {
{
IfcVector3 v; IfcVector3 v;
FindVector(const IfcVector3& p) : v(p) { } FindVector(const IfcVector3 &p) :
v(p) {}
bool operator()(const IfcVector3 &p) { return FuzzyVectorCompare(1e-6)(p, v); } bool operator()(const IfcVector3 &p) { return FuzzyVectorCompare(1e-6)(p, v); }
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::FixupFaceOrientation() void TempMesh::FixupFaceOrientation() {
{
const IfcVector3 vavg = Center(); const IfcVector3 vavg = Center();
// create a list of start indices for all faces to allow random access to faces // create a list of start indices for all faces to allow random access to faces
@ -262,18 +248,15 @@ void TempMesh::FixupFaceOrientation()
// list all faces on a vertex // list all faces on a vertex
std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex; std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
for( size_t a = 0; a < mVertcnt.size(); ++a ) for (size_t a = 0; a < mVertcnt.size(); ++a) {
{
for (size_t b = 0; b < mVertcnt[a]; ++b) for (size_t b = 0; b < mVertcnt[a]; ++b)
facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a); facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a);
} }
// determine neighbourhood for all polys // determine neighbourhood for all polys
std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX); std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX);
std::vector<size_t> tempIntersect(10); std::vector<size_t> tempIntersect(10);
for( size_t a = 0; a < mVertcnt.size(); ++a ) for (size_t a = 0; a < mVertcnt.size(); ++a) {
{ for (size_t b = 0; b < mVertcnt[a]; ++b) {
for( size_t b = 0; b < mVertcnt[a]; ++b )
{
size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a]; size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a];
const std::vector<size_t> &facesOnB = facesByVertex[mVerts[ib]]; const std::vector<size_t> &facesOnB = facesByVertex[mVerts[ib]];
const std::vector<size_t> &facesOnNB = facesByVertex[mVerts[nib]]; const std::vector<size_t> &facesOnNB = facesByVertex[mVerts[nib]];
@ -294,30 +277,31 @@ void TempMesh::FixupFaceOrientation()
// facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring // facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
// faces to have the same winding until all faces have been tested. // faces to have the same winding until all faces have been tested.
std::vector<bool> faceDone(mVertcnt.size(), false); std::vector<bool> faceDone(mVertcnt.size(), false);
while( std::count(faceDone.begin(), faceDone.end(), false) != 0 ) while (std::count(faceDone.begin(), faceDone.end(), false) != 0) {
{
// find the farthest of the remaining faces // find the farthest of the remaining faces
size_t farthestIndex = SIZE_MAX; size_t farthestIndex = SIZE_MAX;
IfcFloat farthestDistance = -1.0; IfcFloat farthestDistance = -1.0;
for( size_t a = 0; a < mVertcnt.size(); ++a ) for (size_t a = 0; a < mVertcnt.size(); ++a) {
{
if (faceDone[a]) if (faceDone[a])
continue; continue;
IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a], IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a],
mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) / IfcFloat(mVertcnt[a]); mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) /
IfcFloat(mVertcnt[a]);
IfcFloat dst = (faceCenter - vavg).SquareLength(); IfcFloat dst = (faceCenter - vavg).SquareLength();
if( dst > farthestDistance ) { farthestDistance = dst; farthestIndex = a; } if (dst > farthestDistance) {
farthestDistance = dst;
farthestIndex = a;
}
} }
// calculate its normal and reverse the poly if its facing towards the mesh center // calculate its normal and reverse the poly if its facing towards the mesh center
IfcVector3 farthestNormal = ComputePolygonNormal(mVerts.data() + faceStartIndices[farthestIndex], mVertcnt[farthestIndex]); IfcVector3 farthestNormal = ComputePolygonNormal(mVerts.data() + faceStartIndices[farthestIndex], mVertcnt[farthestIndex]);
IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex], IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0)) mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0)) /
/ IfcFloat(mVertcnt[farthestIndex]); IfcFloat(mVertcnt[farthestIndex]);
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in // We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
// the file. // the file.
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 ) if ((farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4) {
{
size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex]; size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex];
std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc); std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc);
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc); std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
@ -334,15 +318,13 @@ void TempMesh::FixupFaceOrientation()
todo.push_back(farthestIndex); todo.push_back(farthestIndex);
// go over its neighbour faces recursively and adapt their winding order to match the farthest face // go over its neighbour faces recursively and adapt their winding order to match the farthest face
while( !todo.empty() ) while (!todo.empty()) {
{
size_t tdf = todo.back(); size_t tdf = todo.back();
size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf]; size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf];
todo.pop_back(); todo.pop_back();
// check its neighbours // check its neighbours
for( size_t a = 0; a < vc; ++a ) for (size_t a = 0; a < vc; ++a) {
{
// ignore neighbours if we already checked them // ignore neighbours if we already checked them
size_t nbi = neighbour[vsi + a]; size_t nbi = neighbour[vsi + a];
if (nbi == SIZE_MAX || faceDone[nbi]) if (nbi == SIZE_MAX || faceDone[nbi])
@ -358,8 +340,7 @@ void TempMesh::FixupFaceOrientation()
// to reverse the neighbour // to reverse the neighbour
nb_vidx = (nb_vidx + 1) % nbvc; nb_vidx = (nb_vidx + 1) % nbvc;
size_t oursideidx = (a + 1) % vc; size_t oursideidx = (a + 1) % vc;
if( FuzzyVectorCompare(1e-6)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx]) ) if (FuzzyVectorCompare(1e-6)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx])) {
{
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc); std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc); std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
for (size_t aa = 0; aa < nbvc - 1; ++aa) { for (size_t aa = 0; aa < nbvc - 1; ++aa) {
@ -390,7 +371,6 @@ void TempMesh::RemoveAdjacentDuplicates() {
IfcVector3 vmin, vmax; IfcVector3 vmin, vmax;
ArrayBounds(&*base, cnt, vmin, vmax); ArrayBounds(&*base, cnt, vmin, vmax);
const IfcFloat epsilon = (vmax - vmin).SquareLength() / static_cast<IfcFloat>(1e9); const IfcFloat epsilon = (vmax - vmin).SquareLength() / static_cast<IfcFloat>(1e9);
//const IfcFloat dotepsilon = 1e-9; //const IfcFloat dotepsilon = 1e-9;
@ -442,78 +422,58 @@ void TempMesh::RemoveAdjacentDuplicates() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TempMesh::Swap(TempMesh& other) void TempMesh::Swap(TempMesh &other) {
{
mVertcnt.swap(other.mVertcnt); mVertcnt.swap(other.mVertcnt);
mVerts.swap(other.mVerts); mVerts.swap(other.mVerts);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN& in) bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN &in) {
{
return (std::string)in == "TRUE" || (std::string)in == "T"; return (std::string)in == "TRUE" || (std::string)in == "T";
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IfcFloat ConvertSIPrefix(const std::string& prefix) IfcFloat ConvertSIPrefix(const std::string &prefix) {
{
if (prefix == "EXA") { if (prefix == "EXA") {
return 1e18f; return 1e18f;
} } else if (prefix == "PETA") {
else if (prefix == "PETA") {
return 1e15f; return 1e15f;
} } else if (prefix == "TERA") {
else if (prefix == "TERA") {
return 1e12f; return 1e12f;
} } else if (prefix == "GIGA") {
else if (prefix == "GIGA") {
return 1e9f; return 1e9f;
} } else if (prefix == "MEGA") {
else if (prefix == "MEGA") {
return 1e6f; return 1e6f;
} } else if (prefix == "KILO") {
else if (prefix == "KILO") {
return 1e3f; return 1e3f;
} } else if (prefix == "HECTO") {
else if (prefix == "HECTO") {
return 1e2f; return 1e2f;
} } else if (prefix == "DECA") {
else if (prefix == "DECA") {
return 1e-0f; return 1e-0f;
} } else if (prefix == "DECI") {
else if (prefix == "DECI") {
return 1e-1f; return 1e-1f;
} } else if (prefix == "CENTI") {
else if (prefix == "CENTI") {
return 1e-2f; return 1e-2f;
} } else if (prefix == "MILLI") {
else if (prefix == "MILLI") {
return 1e-3f; return 1e-3f;
} } else if (prefix == "MICRO") {
else if (prefix == "MICRO") {
return 1e-6f; return 1e-6f;
} } else if (prefix == "NANO") {
else if (prefix == "NANO") {
return 1e-9f; return 1e-9f;
} } else if (prefix == "PICO") {
else if (prefix == "PICO") {
return 1e-12f; return 1e-12f;
} } else if (prefix == "FEMTO") {
else if (prefix == "FEMTO") {
return 1e-15f; return 1e-15f;
} } else if (prefix == "ATTO") {
else if (prefix == "ATTO") {
return 1e-18f; return 1e-18f;
} } else {
else {
IFCImporter::LogError("Unrecognized SI prefix: " + prefix); IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
return 1; return 1;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in) void ConvertColor(aiColor4D &out, const Schema_2x3::IfcColourRgb &in) {
{
out.r = static_cast<float>(in.Red); out.r = static_cast<float>(in.Red);
out.g = static_cast<float>(in.Green); out.g = static_cast<float>(in.Green);
out.b = static_cast<float>(in.Blue); out.b = static_cast<float>(in.Blue);
@ -521,8 +481,7 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base) void ConvertColor(aiColor4D &out, const Schema_2x3::IfcColourOrFactor &in, ConversionData &conv, const aiColor4D *base) {
{
if (const ::Assimp::STEP::EXPRESS::REAL *const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { if (const ::Assimp::STEP::EXPRESS::REAL *const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
out.r = out.g = out.b = static_cast<float>(*r); out.r = out.g = out.b = static_cast<float>(*r);
if (base) { if (base) {
@ -530,20 +489,17 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,Conver
out.g *= static_cast<float>(base->g); out.g *= static_cast<float>(base->g);
out.b *= static_cast<float>(base->b); out.b *= static_cast<float>(base->b);
out.a = static_cast<float>(base->a); out.a = static_cast<float>(base->a);
} } else
else out.a = 1.0; out.a = 1.0;
} } else if (const Schema_2x3::IfcColourRgb *const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
else if (const Schema_2x3::IfcColourRgb* const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
ConvertColor(out, *rgb); ConvertColor(out, *rgb);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity"); IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint& in) void ConvertCartesianPoint(IfcVector3 &out, const Schema_2x3::IfcCartesianPoint &in) {
{
out = IfcVector3(); out = IfcVector3();
for (size_t i = 0; i < in.Coordinates.size(); ++i) { for (size_t i = 0; i < in.Coordinates.size(); ++i) {
out[static_cast<unsigned int>(i)] = in.Coordinates[i]; out[static_cast<unsigned int>(i)] = in.Coordinates[i];
@ -551,15 +507,13 @@ void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint&
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertVector(IfcVector3& out, const Schema_2x3::IfcVector& in) void ConvertVector(IfcVector3 &out, const Schema_2x3::IfcVector &in) {
{
ConvertDirection(out, in.Orientation); ConvertDirection(out, in.Orientation);
out *= in.Magnitude; out *= in.Magnitude;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in) void ConvertDirection(IfcVector3 &out, const Schema_2x3::IfcDirection &in) {
{
out = IfcVector3(); out = IfcVector3();
for (size_t i = 0; i < in.DirectionRatios.size(); ++i) { for (size_t i = 0; i < in.DirectionRatios.size(); ++i) {
out[static_cast<unsigned int>(i)] = in.DirectionRatios[i]; out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
@ -573,8 +527,7 @@ void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z) void AssignMatrixAxes(IfcMatrix4 &out, const IfcVector3 &x, const IfcVector3 &y, const IfcVector3 &z) {
{
out.a1 = x.x; out.a1 = x.x;
out.b1 = x.y; out.b1 = x.y;
out.c1 = x.z; out.c1 = x.z;
@ -589,8 +542,7 @@ void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D& in) void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement3D &in) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc, in.Location); ConvertCartesianPoint(loc, in.Location);
@ -614,8 +566,7 @@ void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D& in) void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement2D &in) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc, in.Location); ConvertCartesianPoint(loc, in.Location);
@ -631,34 +582,28 @@ void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const Schema_2x3::IfcAxis1Placement& in) void ConvertAxisPlacement(IfcVector3 &axis, IfcVector3 &pos, const Schema_2x3::IfcAxis1Placement &in) {
{
ConvertCartesianPoint(pos, in.Location); ConvertCartesianPoint(pos, in.Location);
if (in.Axis) { if (in.Axis) {
ConvertDirection(axis, in.Axis.Get()); ConvertDirection(axis, in.Axis.Get());
} } else {
else {
axis = IfcVector3(0.f, 0.f, 1.f); axis = IfcVector3(0.f, 0.f, 1.f);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement& in, ConversionData& conv) void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement &in, ConversionData &conv) {
{
if (const Schema_2x3::IfcAxis2Placement3D *pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) { if (const Schema_2x3::IfcAxis2Placement3D *pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) {
ConvertAxisPlacement(out, *pl3); ConvertAxisPlacement(out, *pl3);
} } else if (const Schema_2x3::IfcAxis2Placement2D *pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
else if(const Schema_2x3::IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
ConvertAxisPlacement(out, *pl2); ConvertAxisPlacement(out, *pl2);
} } else {
else {
IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity"); IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTransformationOperator& op) void ConvertTransformOperator(IfcMatrix4 &out, const Schema_2x3::IfcCartesianTransformationOperator &op) {
{
IfcVector3 loc; IfcVector3 loc;
ConvertCartesianPoint(loc, op.LocalOrigin); ConvertCartesianPoint(loc, op.LocalOrigin);
@ -679,14 +624,12 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
IfcMatrix4::Translation(loc, locm); IfcMatrix4::Translation(loc, locm);
AssignMatrixAxes(out, x, y, z); AssignMatrixAxes(out, x, y, z);
IfcVector3 vscale; IfcVector3 vscale;
if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform *nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) { if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform *nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) {
vscale.x = nuni->Scale ? op.Scale.Get() : 1.f; vscale.x = nuni->Scale ? op.Scale.Get() : 1.f;
vscale.y = nuni->Scale2 ? nuni->Scale2.Get() : 1.f; vscale.y = nuni->Scale2 ? nuni->Scale2.Get() : 1.f;
vscale.z = nuni->Scale3 ? nuni->Scale3.Get() : 1.f; vscale.z = nuni->Scale3 ? nuni->Scale3.Get() : 1.f;
} } else {
else {
const IfcFloat sc = op.Scale ? op.Scale.Get() : 1.f; const IfcFloat sc = op.Scale ? op.Scale.Get() : 1.f;
vscale = IfcVector3(sc, sc, sc); vscale = IfcVector3(sc, sc, sc);
} }
@ -697,8 +640,7 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
out = locm * out * s; out = locm * out * s;
} }
} // namespace IFC
} // ! IFC } // namespace Assimp
} // ! Assimp
#endif #endif

View File

@ -43,9 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the CPP-API class #Importer * @brief Implementation of the CPP-API class #Importer
*/ */
#include <assimp/version.h>
#include <assimp/config.h> #include <assimp/config.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/version.h>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/* Uncomment this line to prevent Assimp from catching unknown exceptions. /* Uncomment this line to prevent Assimp from catching unknown exceptions.
@ -62,29 +62,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Internal headers // Internal headers
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include "Common/Importer.h"
#include "Common/BaseProcess.h" #include "Common/BaseProcess.h"
#include "Common/DefaultProgressHandler.h" #include "Common/DefaultProgressHandler.h"
#include "PostProcessing/ProcessHelper.h" #include "Common/Importer.h"
#include "Common/ScenePreprocessor.h" #include "Common/ScenePreprocessor.h"
#include "Common/ScenePrivate.h" #include "Common/ScenePrivate.h"
#include "PostProcessing/ProcessHelper.h"
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/Exceptional.h>
#include <assimp/GenericProperty.h> #include <assimp/GenericProperty.h>
#include <assimp/MemoryIOWrapper.h> #include <assimp/MemoryIOWrapper.h>
#include <assimp/Profiler.h> #include <assimp/Profiler.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <assimp/Exceptional.h>
#include <assimp/Profiler.h>
#include <assimp/commonMetaData.h> #include <assimp/commonMetaData.h>
#include <set>
#include <memory>
#include <cctype> #include <cctype>
#include <memory>
#include <set>
#include <assimp/DefaultIOStream.h> #include <assimp/DefaultIOStream.h>
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
// clang-format off
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
# include "PostProcessing/ValidateDataStructure.h" # include "PostProcessing/ValidateDataStructure.h"
#endif #endif
@ -99,8 +100,9 @@ namespace Assimp {
// PostStepRegistry.cpp // PostStepRegistry.cpp
void GetPostProcessingStepInstanceList(std::vector<BaseProcess *> &out); void GetPostProcessingStepInstanceList(std::vector<BaseProcess *> &out);
} } // namespace Assimp
// clang-format on
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Intern; using namespace Assimp::Intern;
@ -117,8 +119,7 @@ void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) {
void *AllocateFromAssimpHeap::operator new(size_t num_bytes, const std::nothrow_t &) throw() { void *AllocateFromAssimpHeap::operator new(size_t num_bytes, const std::nothrow_t &) throw() {
try { try {
return AllocateFromAssimpHeap::operator new(num_bytes); return AllocateFromAssimpHeap::operator new(num_bytes);
} } catch (...) {
catch( ... ) {
return nullptr; return nullptr;
} }
} }
@ -145,8 +146,8 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer constructor. // Importer constructor.
Importer::Importer() Importer::Importer() :
: pimpl( new ImporterPimpl ) { pimpl(new ImporterPimpl) {
pimpl->mScene = nullptr; pimpl->mScene = nullptr;
pimpl->mErrorString = ""; pimpl->mErrorString = "";
@ -652,8 +653,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
// Get file size for progress handler // Get file size for progress handler
IOStream *fileIO = pimpl->mIOHandler->Open(pFile); IOStream *fileIO = pimpl->mIOHandler->Open(pFile);
uint32_t fileSize = 0; uint32_t fileSize = 0;
if (fileIO) if (fileIO) {
{
fileSize = static_cast<uint32_t>(fileIO->FileSize()); fileSize = static_cast<uint32_t>(fileIO->FileSize());
pimpl->mIOHandler->Close(fileIO); pimpl->mIOHandler->Close(fileIO);
} }
@ -738,7 +738,8 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
#endif #endif
ASSIMP_LOG_ERROR(pimpl->mErrorString); ASSIMP_LOG_ERROR(pimpl->mErrorString);
delete pimpl->mScene; pimpl->mScene = nullptr; delete pimpl->mScene;
pimpl->mScene = nullptr;
} }
#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
@ -748,7 +749,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
return pimpl->mScene; return pimpl->mScene;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Apply post-processing to the currently bound scene // Apply post-processing to the currently bound scene
const aiScene *Importer::ApplyPostProcessing(unsigned int pFlags) { const aiScene *Importer::ApplyPostProcessing(unsigned int pFlags) {
@ -781,8 +781,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
} }
#endif // no validation #endif // no validation
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
if (pimpl->bExtraVerbose) if (pimpl->bExtraVerbose) {
{
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings"); ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
#endif // no validation #endif // no validation
@ -870,8 +869,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
// The ValidateDS process plays an exceptional role. It isn't contained in the global // The ValidateDS process plays an exceptional role. It isn't contained in the global
// list of post-processing steps, so we need to call it manually. // list of post-processing steps, so we need to call it manually.
if ( requestValidation ) if (requestValidation) {
{
ValidateDSProcess ds; ValidateDSProcess ds;
ds.ExecuteOnScene(this); ds.ExecuteOnScene(this);
if (!pimpl->mScene) { if (!pimpl->mScene) {
@ -880,8 +878,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
} }
#endif // no validation #endif // no validation
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
if ( pimpl->bExtraVerbose ) if (pimpl->bExtraVerbose) {
{
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings"); ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
#endif // no validation #endif // no validation
@ -947,7 +944,6 @@ const aiImporterDesc* Importer::GetImporterInfo(size_t index) const {
return pimpl->mImporter[index]->GetInfo(); return pimpl->mImporter[index]->GetInfo();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BaseImporter *Importer::GetImporter(size_t index) const { BaseImporter *Importer::GetImporter(size_t index) const {
ai_assert(nullptr != pimpl); ai_assert(nullptr != pimpl);
@ -975,7 +971,8 @@ size_t Importer::GetImporterIndex (const char* szExtension) const {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// skip over wildcard and dot characters at string head -- // skip over wildcard and dot characters at string head --
for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension ); for (; *szExtension == '*' || *szExtension == '.'; ++szExtension)
;
std::string ext(szExtension); std::string ext(szExtension);
if (ext.empty()) { if (ext.empty()) {
@ -1106,8 +1103,7 @@ aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& i
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get the memory requirements of a single node // Get the memory requirements of a single node
inline inline void AddNodeWeight(unsigned int &iScene, const aiNode *pcNode) {
void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) {
if (nullptr == pcNode) { if (nullptr == pcNode) {
return; return;
} }

View File

@ -44,10 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_IMPORTER_H #ifndef INCLUDED_AI_IMPORTER_H
#define INCLUDED_AI_IMPORTER_H #define INCLUDED_AI_IMPORTER_H
#include <map>
#include <vector>
#include <string>
#include <assimp/matrix4x4.h> #include <assimp/matrix4x4.h>
#include <map>
#include <string>
#include <vector>
struct aiScene; struct aiScene;
@ -58,7 +58,6 @@ namespace Assimp {
class BaseProcess; class BaseProcess;
class SharedPostProcessInfo; class SharedPostProcessInfo;
//! @cond never //! @cond never
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Internal PIMPL implementation for Assimp::Importer /** @brief Internal PIMPL implementation for Assimp::Importer
@ -70,7 +69,7 @@ namespace Assimp {
class ImporterPimpl { class ImporterPimpl {
public: public:
// Data type to store the key hash // Data type to store the key hash
typedef unsigned int KeyType; using KeyType = unsigned int;
// typedefs for our four configuration maps. // typedefs for our four configuration maps.
// We don't need more, so there is no need for a generic solution // We don't need more, so there is no need for a generic solution
@ -126,9 +125,7 @@ public:
ImporterPimpl() AI_NO_EXCEPT; ImporterPimpl() AI_NO_EXCEPT;
}; };
inline inline ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : mIOHandler(nullptr),
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
mIOHandler( nullptr ),
mIsDefaultHandler(false), mIsDefaultHandler(false),
mProgressHandler(nullptr), mProgressHandler(nullptr),
mIsDefaultProgressHandler(false), mIsDefaultProgressHandler(false),
@ -214,8 +211,7 @@ public:
unsigned int AddLoadRequest( unsigned int AddLoadRequest(
const std::string &file, const std::string &file,
unsigned int steps = 0, unsigned int steps = 0,
const PropertyMap *map = nullptr const PropertyMap *map = nullptr);
);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get an imported scene. /** Get an imported scene.
@ -227,8 +223,7 @@ public:
* @return nullptr if there is no scene with this file name * @return nullptr if there is no scene with this file name
* in the queue of the scene hasn't been loaded yet. */ * in the queue of the scene hasn't been loaded yet. */
aiScene *GetImport( aiScene *GetImport(
unsigned int which unsigned int which);
);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Waits until all scenes have been loaded. This returns /** Waits until all scenes have been loaded. This returns

View File

@ -45,8 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_POLYTOOLS_H_INCLUDED #ifndef AI_POLYTOOLS_H_INCLUDED
#define AI_POLYTOOLS_H_INCLUDED #define AI_POLYTOOLS_H_INCLUDED
#include <assimp/material.h>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/material.h>
#include <assimp/vector3.h>
namespace Assimp { namespace Assimp {
@ -55,8 +56,7 @@ namespace Assimp {
* The function accepts an unconstrained template parameter for use with * The function accepts an unconstrained template parameter for use with
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
template <typename T> template <typename T>
inline double GetArea2D(const T& v1, const T& v2, const T& v3) inline double GetArea2D(const T &v1, const T &v2, const T &v3) {
{
return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y)); return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
} }
@ -65,8 +65,7 @@ inline double GetArea2D(const T& v1, const T& v2, const T& v3)
* The function accepts an unconstrained template parameter for use with * The function accepts an unconstrained template parameter for use with
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
template <typename T> template <typename T>
inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2) inline bool OnLeftSideOfLine2D(const T &p0, const T &p1, const T &p2) {
{
return GetArea2D(p0, p2, p1) > 0; return GetArea2D(p0, p2, p1) > 0;
} }
@ -75,8 +74,7 @@ inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
* The function accepts an unconstrained template parameter for use with * The function accepts an unconstrained template parameter for use with
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/ * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
template <typename T> template <typename T>
inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp) inline bool PointInTriangle2D(const T &p0, const T &p1, const T &p2, const T &pp) {
{
// Point in triangle test using baryzentric coordinates // Point in triangle test using baryzentric coordinates
const aiVector2D v0 = p1 - p0; const aiVector2D v0 = p1 - p0;
const aiVector2D v1 = p2 - p0; const aiVector2D v1 = p2 - p0;
@ -95,7 +93,6 @@ inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1); return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1);
} }
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Check whether the winding order of a given polygon is counter-clockwise. /** Check whether the winding order of a given polygon is counter-clockwise.
* The function accepts an unconstrained template parameter, but is intended * The function accepts an unconstrained template parameter, but is intended
@ -133,8 +130,7 @@ inline bool IsCCW(T* in, size_t npoints) {
// in[i+2].x, in[i+2].y)) { // in[i+2].x, in[i+2].y)) {
convex_turn = AI_MATH_PI_F - theta; convex_turn = AI_MATH_PI_F - theta;
convex_sum += convex_turn; convex_sum += convex_turn;
} } else {
else {
convex_sum -= AI_MATH_PI_F - theta; convex_sum -= AI_MATH_PI_F - theta;
} }
} }
@ -161,15 +157,13 @@ inline bool IsCCW(T* in, size_t npoints) {
if (OnLeftSideOfLine2D(in[npoints - 2], in[1], in[0])) { if (OnLeftSideOfLine2D(in[npoints - 2], in[1], in[0])) {
convex_turn = AI_MATH_PI_F - theta; convex_turn = AI_MATH_PI_F - theta;
convex_sum += convex_turn; convex_sum += convex_turn;
} } else {
else {
convex_sum -= AI_MATH_PI_F - theta; convex_sum -= AI_MATH_PI_F - theta;
} }
return convex_sum >= (2 * AI_MATH_PI_F); return convex_sum >= (2 * AI_MATH_PI_F);
} }
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Compute the normal of an arbitrary polygon in R3. /** Compute the normal of an arbitrary polygon in R3.
* *
@ -185,9 +179,14 @@ inline bool IsCCW(T* in, size_t npoints) {
* @note The data arrays must have storage for at least num+2 elements. Using * @note The data arrays must have storage for at least num+2 elements. Using
* this method is much faster than the 'other' NewellNormal() * this method is much faster than the 'other' NewellNormal()
*/ */
template <int ofs_x, int ofs_y, int ofs_z, typename TReal> template <size_t ofs_x, size_t ofs_y, size_t ofs_z, typename TReal>
inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z) inline void NewellNormal(aiVector3t<TReal> &out, size_t num, TReal *x, TReal *y, TReal *z, size_t bufferSize) {
{ ai_assert(bufferSize > num);
if (nullptr == x || nullptr == y || nullptr == z || 0 == bufferSize || 0 == num) {
return;
}
// Duplicate the first two vertices at the end // Duplicate the first two vertices at the end
x[(num + 0) * ofs_x] = x[0]; x[(num + 0) * ofs_x] = x[0];
x[(num + 1) * ofs_x] = x[ofs_x]; x[(num + 1) * ofs_x] = x[ofs_x];
@ -204,7 +203,7 @@ inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, T
TReal *yptr = y + ofs_y, *ylow = y, *yhigh = y + ofs_y * 2; TReal *yptr = y + ofs_y, *ylow = y, *yhigh = y + ofs_y * 2;
TReal *zptr = z + ofs_z, *zlow = z, *zhigh = z + ofs_z * 2; TReal *zptr = z + ofs_z, *zlow = z, *zhigh = z + ofs_z * 2;
for (int tmp=0; tmp < num; tmp++) { for (size_t tmp = 0; tmp < num; ++tmp ) {
sum_xy += (*xptr) * ((*yhigh) - (*ylow)); sum_xy += (*xptr) * ((*yhigh) - (*ylow));
sum_yz += (*yptr) * ((*zhigh) - (*zlow)); sum_yz += (*yptr) * ((*zhigh) - (*zlow));
sum_zx += (*zptr) * ((*xhigh) - (*xlow)); sum_zx += (*zptr) * ((*xhigh) - (*xlow));
@ -224,6 +223,6 @@ inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, T
out = aiVector3t<TReal>(sum_yz, sum_zx, sum_xy); out = aiVector3t<TReal>(sum_yz, sum_zx, sum_xy);
} }
} // ! Assimp } // namespace Assimp
#endif #endif

View File

@ -60,14 +60,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS #ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
#include "PostProcessing/TriangulateProcess.h" #include "PostProcessing/TriangulateProcess.h"
#include "PostProcessing/ProcessHelper.h"
#include "Common/PolyTools.h" #include "Common/PolyTools.h"
#include "PostProcessing/ProcessHelper.h"
#include <memory>
#include <cstdint> #include <cstdint>
#include <memory>
//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING //#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
//#define AI_BUILD_TRIANGULATE_DEBUG_POLYS #define AI_BUILD_TRIANGULATE_DEBUG_POLYS
#define POLY_GRID_Y 40 #define POLY_GRID_Y 40
#define POLY_GRID_X 70 #define POLY_GRID_X 70
@ -78,34 +78,29 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
TriangulateProcess::TriangulateProcess() TriangulateProcess::TriangulateProcess() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
TriangulateProcess::~TriangulateProcess() TriangulateProcess::~TriangulateProcess() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool TriangulateProcess::IsActive( unsigned int pFlags) const bool TriangulateProcess::IsActive(unsigned int pFlags) const {
{
return (pFlags & aiProcess_Triangulate) != 0; return (pFlags & aiProcess_Triangulate) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void TriangulateProcess::Execute( aiScene* pScene) void TriangulateProcess::Execute(aiScene *pScene) {
{
ASSIMP_LOG_DEBUG("TriangulateProcess begin"); ASSIMP_LOG_DEBUG("TriangulateProcess begin");
bool bHas = false; bool bHas = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
{
if (pScene->mMeshes[a]) { if (pScene->mMeshes[a]) {
if (TriangulateMesh(pScene->mMeshes[a])) { if (TriangulateMesh(pScene->mMeshes[a])) {
bHas = true; bHas = true;
@ -120,44 +115,54 @@ void TriangulateProcess::Execute( aiScene* pScene)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Triangulates the given mesh. static bool validateNumIndices(aiMesh *mesh) {
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
{
// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
if (!pMesh->mPrimitiveTypes) {
bool bNeed = false; bool bNeed = false;
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { const aiFace &face = mesh->mFaces[a];
const aiFace& face = pMesh->mFaces[a];
if (face.mNumIndices != 3) { if (face.mNumIndices != 3) {
bNeed = true; bNeed = true;
break;
} }
} }
if (!bNeed)
return false;
}
else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
return false;
}
// Find out how many output faces we'll get return bNeed;
uint32_t numOut = 0, max_out = 0; }
bool get_normals = true;
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { static void calulateNumOutputFaces(aiMesh *mesh, size_t &numOut, size_t &maxOut, bool &getNormals) {
aiFace& face = pMesh->mFaces[a]; numOut = maxOut = 0;
getNormals = true;
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
aiFace &face = mesh->mFaces[a];
if (face.mNumIndices <= 4) { if (face.mNumIndices <= 4) {
get_normals = false; getNormals = false;
} }
if (face.mNumIndices <= 3) { if (face.mNumIndices <= 3) {
numOut++; numOut++;
} } else {
else {
numOut += face.mNumIndices - 2; numOut += face.mNumIndices - 2;
max_out = std::max(max_out,face.mNumIndices); maxOut = std::max(maxOut, static_cast<size_t>(face.mNumIndices));
} }
} }
}
// ------------------------------------------------------------------------------------------------
// Triangulates the given mesh.
bool TriangulateProcess::TriangulateMesh(aiMesh *pMesh) {
// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
if (!pMesh->mPrimitiveTypes) {
if (!validateNumIndices(pMesh)) {
return false;
}
} else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
return false;
}
// Find out how many output faces we'll get
size_t numOut = 0, max_out = 0;
bool getNormals = true;
calulateNumOutputFaces(pMesh, numOut, max_out, getNormals);
// Just another check whether aiMesh::mPrimitiveTypes is correct // Just another check whether aiMesh::mPrimitiveTypes is correct
ai_assert(numOut != pMesh->mNumFaces); ai_assert(numOut != pMesh->mNumFaces);
@ -166,7 +171,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
// if we don't have normals yet, but expect them to be a cheap side // if we don't have normals yet, but expect them to be a cheap side
// product of triangulation anyway, allocate storage for them. // product of triangulation anyway, allocate storage for them.
if (!pMesh->mNormals && get_normals) { if (!pMesh->mNormals && getNormals) {
// XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
// nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; // nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
} }
@ -176,6 +181,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON; pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
aiFace *out = new aiFace[numOut](), *curOut = out; aiFace *out = new aiFace[numOut](), *curOut = out;
const size_t Capa = max_out + 2;
std::vector<aiVector3D> temp_verts3d(max_out + 2); /* temporary storage for vertices */ std::vector<aiVector3D> temp_verts3d(max_out + 2); /* temporary storage for vertices */
std::vector<aiVector2D> temp_verts(max_out + 2); std::vector<aiVector2D> temp_verts(max_out + 2);
@ -215,8 +221,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
aiFace *const last_face = curOut; aiFace *const last_face = curOut;
// if it's a simple point,line or triangle: just copy it // if it's a simple point,line or triangle: just copy it
if( face.mNumIndices <= 3) if (face.mNumIndices <= 3) {
{
aiFace &nface = *curOut++; aiFace &nface = *curOut++;
nface.mNumIndices = face.mNumIndices; nface.mNumIndices = face.mNumIndices;
nface.mIndices = face.mIndices; nface.mIndices = face.mIndices;
@ -275,9 +280,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
// prevent double deletion of the indices field // prevent double deletion of the indices field
face.mIndices = nullptr; face.mIndices = nullptr;
continue; continue;
} } else {
else
{
// A polygon with more than 3 vertices can be either concave or convex. // A polygon with more than 3 vertices can be either concave or convex.
// Usually everything we're getting is convex and we could easily // Usually everything we're getting is convex and we could easily
// triangulate by tri-fanning. However, LightWave is probably the only // triangulate by tri-fanning. However, LightWave is probably the only
@ -292,9 +295,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
temp_verts3d[tmp] = verts[idx[tmp]]; temp_verts3d[tmp] = verts[idx[tmp]];
} }
// Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh // Get Newell-Normal of the polygon. Store it for future use if it's a polygon-only mesh
aiVector3D n; aiVector3D n;
NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z); NewellNormal<3, 3, 3>(n, max, &temp_verts3d.front().x, &temp_verts3d.front().y, &temp_verts3d.front().z, Capa);
if (nor_out) { if (nor_out) {
for (tmp = 0; tmp < max; ++tmp) for (tmp = 0; tmp < max; ++tmp)
nor_out[idx[tmp]] = n; nor_out[idx[tmp]] = n;
@ -305,16 +308,17 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
const float ay = (n.y > 0 ? n.y : -n.y); const float ay = (n.y > 0 ? n.y : -n.y);
const float az = (n.z > 0 ? n.z : -n.z); const float az = (n.z > 0 ? n.z : -n.z);
unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */ unsigned int ac = 0, bc = 1; // no z coord. projection to xy
float inv = n.z; float inv = n.z;
if (ax > ay) { if (ax > ay) {
if (ax > az) { /* no x coord. projection to yz */ if (ax > az) { // no x coord. projection to yz
ac = 1; bc = 2; ac = 1;
bc = 2;
inv = n.x; inv = n.x;
} }
} } else if (ay > az) { // no y coord. projection to zy
else if (ay > az) { /* no y coord. projection to zy */ ac = 2;
ac = 2; bc = 0; bc = 0;
inv = n.y; inv = n.y;
} }
@ -342,13 +346,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
const size_t x = static_cast<size_t>(v.x * (POLY_GRID_X - 1)), y = static_cast<size_t>(v.y * (POLY_GRID_Y - 1)); const size_t x = static_cast<size_t>(v.x * (POLY_GRID_X - 1)), y = static_cast<size_t>(v.y * (POLY_GRID_Y - 1));
char *loc = grid[y] + x; char *loc = grid[y] + x;
if (grid[y][x] != ' ') { if (grid[y][x] != ' ') {
for(;*loc != ' '; ++loc); for (; *loc != ' '; ++loc)
;
*loc++ = '_'; *loc++ = '_';
} }
*(loc + ::ai_snprintf(loc, POLY_GRID_XPAD, "%i", i)) = ' '; *(loc + ::ai_snprintf(loc, POLY_GRID_XPAD, "%i", i)) = ' ';
} }
for (size_t y = 0; y < POLY_GRID_Y; ++y) { for (size_t y = 0; y < POLY_GRID_Y; ++y) {
grid[y][POLY_GRID_X + POLY_GRID_XPAD - 1] = '\0'; grid[y][POLY_GRID_X + POLY_GRID_XPAD - 1] = '\0';
fprintf(fout, "%s\n", grid[y]); fprintf(fout, "%s\n", grid[y]);
@ -367,7 +371,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
for (ear = next;; prev = ear, ear = next) { for (ear = next;; prev = ear, ear = next) {
// break after we looped two times without a positive match // break after we looped two times without a positive match
for (next=ear+1;done[(next>=max?next=0:next)];++next); for (next = ear + 1; done[(next >= max ? next = 0 : next)]; ++next)
;
if (next < ear) { if (next < ear) {
if (++num_found == 2) { if (++num_found == 2) {
break; break;
@ -419,22 +424,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
#endif #endif
num = 0; num = 0;
break; break;
/*curOut -= (max-num); // undo all previous work
for (tmp = 0; tmp < max-2; ++tmp) {
aiFace& nface = *curOut++;
nface.mNumIndices = 3;
if (!nface.mIndices)
nface.mIndices = new unsigned int[3];
nface.mIndices[0] = 0;
nface.mIndices[1] = tmp+1;
nface.mIndices[2] = tmp+2;
}
num = 0;
break;*/
} }
aiFace &nface = *curOut++; aiFace &nface = *curOut++;
@ -461,15 +450,17 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
nface.mIndices = new unsigned int[3]; nface.mIndices = new unsigned int[3];
} }
for (tmp = 0; done[tmp]; ++tmp); for (tmp = 0; done[tmp]; ++tmp)
;
nface.mIndices[0] = tmp; nface.mIndices[0] = tmp;
for (++tmp; done[tmp]; ++tmp); for (++tmp; done[tmp]; ++tmp)
;
nface.mIndices[1] = tmp; nface.mIndices[1] = tmp;
for (++tmp; done[tmp]; ++tmp); for (++tmp; done[tmp]; ++tmp)
;
nface.mIndices[2] = tmp; nface.mIndices[2] = tmp;
} }
} }
@ -487,24 +478,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
for (aiFace *f = last_face; f != curOut;) { for (aiFace *f = last_face; f != curOut;) {
unsigned int *i = f->mIndices; unsigned int *i = f->mIndices;
// drop dumb 0-area triangles - deactivated for now:
//FindDegenerates post processing step can do the same thing
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
// ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0");
// --curOut;
// delete[] f->mIndices;
// f->mIndices = nullptr;
// for(aiFace* ff = f; ff != curOut; ++ff) {
// ff->mNumIndices = (ff+1)->mNumIndices;
// ff->mIndices = (ff+1)->mIndices;
// (ff+1)->mIndices = nullptr;
// }
// continue;
//}
i[0] = idx[i[0]]; i[0] = idx[i[0]];
i[1] = idx[i[1]]; i[1] = idx[i[1]];
i[2] = idx[i[2]]; i[2] = idx[i[2]];

View File

@ -96,6 +96,7 @@ SET( COMMON
unit/Common/utSpatialSort.cpp unit/Common/utSpatialSort.cpp
unit/Common/utAssertHandler.cpp unit/Common/utAssertHandler.cpp
unit/Common/utXmlParser.cpp unit/Common/utXmlParser.cpp
unit/Common/utPolyTools.cpp
) )
SET( IMPORTERS SET( IMPORTERS

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -43,9 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AV_ANIMEVALUATOR_H_INCLUDED #ifndef AV_ANIMEVALUATOR_H_INCLUDED
#define AV_ANIMEVALUATOR_H_INCLUDED #define AV_ANIMEVALUATOR_H_INCLUDED
#include <assimp/matrix4x4.h>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
struct aiAnimation;
namespace AssimpView { namespace AssimpView {
/** /**
@ -74,7 +78,7 @@ public:
* the aiAnimation. */ * the aiAnimation. */
const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; } const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; }
protected: private:
const aiAnimation *mAnim; const aiAnimation *mAnim;
double mLastTime; double mLastTime;
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions; std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions;

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AV_SCENEANIMATOR_H_INCLUDED #ifndef AV_SCENEANIMATOR_H_INCLUDED
#define AV_SCENEANIMATOR_H_INCLUDED #define AV_SCENEANIMATOR_H_INCLUDED
#include <assimp/scene.h>
#include <map> #include <map>
#include <string>
namespace AssimpView { namespace AssimpView {
@ -72,13 +75,23 @@ struct SceneAnimNode {
//! Default construction //! Default construction
SceneAnimNode() : SceneAnimNode() :
mName(), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) { mName(),
mParent(nullptr),
mChildren(),
mLocalTransform(),
mGlobalTransform(),
mChannelIndex(-1) {
// empty // empty
} }
//! Construction from a given name //! Construction from a given name
SceneAnimNode(const std::string &pName) : SceneAnimNode(const std::string &pName) :
mName(pName), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) { mName(pName),
mParent(nullptr),
mChildren(),
mLocalTransform(),
mGlobalTransform(),
mChannelIndex(-1) {
// empty // empty
} }
@ -125,7 +138,7 @@ public:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Calculates the node transformations for the scene. Call this to get /** Calculates the node transformations for the scene. Call this to get
* uptodate results before calling one of the getters. * up-to-date results before calling one of the getters.
* @param pTime Current time. Can be an arbitrary range. * @param pTime Current time. Can be an arbitrary range.
*/ */
void Calculate(double pTime); void Calculate(double pTime);
@ -136,7 +149,7 @@ public:
* The returned matrix is in the node's parent's local space, just like the * The returned matrix is in the node's parent's local space, just like the
* original node's transformation matrix. If the node is not animated, the * original node's transformation matrix. If the node is not animated, the
* node's original transformation is returned so that you can safely use or * node's original transformation is returned so that you can safely use or
* assign it to the node itsself. If there is no node with the given name, * assign it to the node itself. If there is no node with the given name,
* the identity matrix is returned. All transformations are updated whenever * the identity matrix is returned. All transformations are updated whenever
* Calculate() is called. * Calculate() is called.
* @param pNodeName Name of the node * @param pNodeName Name of the node
@ -151,7 +164,7 @@ public:
* The returned matrix is in world space, which is the same coordinate space * The returned matrix is in world space, which is the same coordinate space
* as the transformation of the scene's root node. If the node is not animated, * as the transformation of the scene's root node. If the node is not animated,
* the node's original transformation is returned so that you can safely use or * the node's original transformation is returned so that you can safely use or
* assign it to the node itsself. If there is no node with the given name, the * assign it to the node itself. If there is no node with the given name, the
* identity matrix is returned. All transformations are updated whenever * identity matrix is returned. All transformations are updated whenever
* Calculate() is called. * Calculate() is called.
* @param pNodeName Name of the node * @param pNodeName Name of the node
@ -190,7 +203,7 @@ public:
/** @brief Get the current animation or NULL /** @brief Get the current animation or NULL
*/ */
aiAnimation *CurrentAnim() const { aiAnimation *CurrentAnim() const {
return static_cast<unsigned int>(mCurrentAnimIndex) < mScene->mNumAnimations ? mScene->mAnimations[mCurrentAnimIndex] : NULL; return static_cast<unsigned int>(mCurrentAnimIndex) < mScene->mNumAnimations ? mScene->mAnimations[mCurrentAnimIndex] : nullptr;
} }
protected: protected: