closes https://github.com/assimp/assimp/issues/1044: set default value in case of light intensity envelopes-
parent
de610b8ce9
commit
456b54988a
|
@ -123,20 +123,20 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties for the loader
|
||||
void FBXImporter::SetupProperties(const Importer *pImp) {
|
||||
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||
mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||
mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||
mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||
mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||
mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||
mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||
mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||
mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||
mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||
mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||
mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -181,10 +181,10 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
|||
Parser parser(tokens, is_binary);
|
||||
|
||||
// take the raw parse-tree and convert it to a FBX DOM
|
||||
Document doc(parser, settings);
|
||||
Document doc(parser, mSettings);
|
||||
|
||||
// convert the FBX DOM to aiScene
|
||||
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
|
||||
ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
|
||||
|
||||
// size relative to cm
|
||||
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
||||
|
|
|
@ -70,27 +70,16 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
|
|||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
||||
public:
|
||||
FBXImporter();
|
||||
virtual ~FBXImporter();
|
||||
|
||||
// --------------------
|
||||
bool CanRead(const std::string &pFile,
|
||||
IOSystem *pIOHandler,
|
||||
bool checkSig) const;
|
||||
~FBXImporter() override;
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
|
||||
|
||||
protected:
|
||||
// --------------------
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
|
||||
// --------------------
|
||||
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:
|
||||
FBX::ImportSettings settings;
|
||||
FBX::ImportSettings mSettings;
|
||||
}; // !class FBXImporter
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -48,12 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <functional>
|
||||
|
||||
#include "FBXMeshGeometry.h"
|
||||
#include "FBXDocument.h"
|
||||
#include "FBXImporter.h"
|
||||
#include "FBXImportSettings.h"
|
||||
#include "FBXDocumentUtil.h"
|
||||
|
||||
#include "FBXImportSettings.h"
|
||||
#include "FBXImporter.h"
|
||||
#include "FBXMeshGeometry.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
@ -61,10 +60,8 @@ namespace FBX {
|
|||
using namespace Util;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||
: Object(id, element, name)
|
||||
, skin()
|
||||
{
|
||||
Geometry::Geometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||
Object(id, element, name), skin() {
|
||||
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
|
||||
for (const Connection *con : conns) {
|
||||
const Skin *const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
||||
|
@ -79,8 +76,7 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Geometry::~Geometry()
|
||||
{
|
||||
Geometry::~Geometry() {
|
||||
// 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)
|
||||
: Geometry(id, element,name, doc)
|
||||
{
|
||||
MeshGeometry::MeshGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||
Geometry(id, element, name, doc) {
|
||||
const Scope *sc = element.Compound();
|
||||
if (!sc) {
|
||||
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) {
|
||||
const Scope &layer = GetRequiredScope(*(*it).second);
|
||||
ReadLayer(layer);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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(
|
||||
m_facesVertexStartIndices.begin(),
|
||||
m_facesVertexStartIndices.end(),
|
||||
in_index
|
||||
);
|
||||
in_index);
|
||||
|
||||
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");
|
||||
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
|
||||
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 &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(
|
||||
GetRequiredElement(source,"MappingInformationType"),0)
|
||||
);
|
||||
GetRequiredElement(source, "MappingInformationType"), 0));
|
||||
|
||||
const std::string &ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
|
||||
GetRequiredElement(source,"ReferenceInformationType"),0)
|
||||
);
|
||||
GetRequiredElement(source, "ReferenceInformationType"), 0));
|
||||
|
||||
if (type == "LayerElementUV") {
|
||||
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,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
}
|
||||
else if (type == "LayerElementMaterial") {
|
||||
ReferenceInformationType);
|
||||
} else if (type == "LayerElementMaterial") {
|
||||
if (m_materials.size() > 0) {
|
||||
FBXImporter::LogError("ignoring additional material layer");
|
||||
return;
|
||||
|
@ -350,8 +335,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
|
||||
ReadVertexDataMaterials(temp_materials, source,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
ReferenceInformationType);
|
||||
|
||||
// sometimes, there will be only negative entries. Drop the material
|
||||
// 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);
|
||||
}
|
||||
else if (type == "LayerElementNormal") {
|
||||
} else if (type == "LayerElementNormal") {
|
||||
if (m_normals.size() > 0) {
|
||||
FBXImporter::LogError("ignoring additional normal layer");
|
||||
return;
|
||||
|
@ -375,10 +358,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
|
||||
ReadVertexDataNormals(m_normals, source,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
}
|
||||
else if (type == "LayerElementTangent") {
|
||||
ReferenceInformationType);
|
||||
} else if (type == "LayerElementTangent") {
|
||||
if (m_tangents.size() > 0) {
|
||||
FBXImporter::LogError("ignoring additional tangent layer");
|
||||
return;
|
||||
|
@ -386,10 +367,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
|
||||
ReadVertexDataTangents(m_tangents, source,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
}
|
||||
else if (type == "LayerElementBinormal") {
|
||||
ReferenceInformationType);
|
||||
} else if (type == "LayerElementBinormal") {
|
||||
if (m_binormals.size() > 0) {
|
||||
FBXImporter::LogError("ignoring additional binormal layer");
|
||||
return;
|
||||
|
@ -397,10 +376,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
|||
|
||||
ReadVertexDataBinormals(m_binormals, source,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
}
|
||||
else if (type == "LayerElementColor") {
|
||||
ReferenceInformationType);
|
||||
} else if (type == "LayerElementColor") {
|
||||
if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
|
||||
FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
|
||||
<< 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,
|
||||
MappingInformationType,
|
||||
ReferenceInformationType
|
||||
);
|
||||
ReferenceInformationType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,8 +403,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
size_t vertex_count,
|
||||
const std::vector<unsigned int> &mapping_counts,
|
||||
const std::vector<unsigned int> &mapping_offsets,
|
||||
const std::vector<unsigned int>& mappings)
|
||||
{
|
||||
const std::vector<unsigned int> &mappings) {
|
||||
bool isDirect = ReferenceInformationType == "Direct";
|
||||
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
||||
|
||||
|
@ -461,8 +436,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
data_out[mappings[j]] = tempData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||
} else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
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]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||
} else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
if (tempData.size() != vertex_count) {
|
||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
||||
<< tempData.size() << ", expected " << vertex_count
|
||||
);
|
||||
<< tempData.size() << ", expected " << vertex_count);
|
||||
return;
|
||||
}
|
||||
|
||||
data_out.swap(tempData);
|
||||
}
|
||||
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||
} else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||
std::vector<T> tempData;
|
||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||
|
||||
|
@ -529,8 +500,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
|||
|
||||
data_out[next++] = tempData[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
|
||||
<< 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,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
ResolveVertexDataArray(normals_out, source, MappingInformationType, ReferenceInformationType,
|
||||
"Normals",
|
||||
"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,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
ResolveVertexDataArray(uv_out, source, MappingInformationType, ReferenceInformationType,
|
||||
"UV",
|
||||
"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,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
ResolveVertexDataArray(colors_out, source, MappingInformationType, ReferenceInformationType,
|
||||
"Colors",
|
||||
"ColorIndex",
|
||||
|
@ -584,8 +551,7 @@ static const char *TangentsIndexToken = "TangentsIndex";
|
|||
|
||||
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D> &tangents_out, const Scope &source,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
const char *str = source.Elements().count("Tangents") > 0 ? "Tangents" : "Tangent";
|
||||
const char *strIdx = source.Elements().count("Tangents") > 0 ? TangentsIndexToken : TangentIndexToken;
|
||||
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,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
const char *str = source.Elements().count("Binormals") > 0 ? "Binormals" : "Binormal";
|
||||
const char *strIdx = source.Elements().count("Binormals") > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
|
||||
ResolveVertexDataArray(binormals_out, source, MappingInformationType, ReferenceInformationType,
|
||||
|
@ -616,15 +581,12 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
|
|||
m_mappings);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void MeshGeometry::ReadVertexDataMaterials(std::vector<int> &materials_out, const Scope &source,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const std::string &ReferenceInformationType) {
|
||||
const size_t face_count = m_faces.size();
|
||||
if( 0 == face_count )
|
||||
{
|
||||
if (0 == face_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -650,8 +612,7 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
|||
|
||||
if (materials_out.size() != face_count) {
|
||||
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;
|
||||
}
|
||||
} 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)
|
||||
: Geometry(id, element, name, doc) {
|
||||
ShapeGeometry::ShapeGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||
Geometry(id, element, name, doc) {
|
||||
const Scope *sc = element.Compound();
|
||||
if (nullptr == sc) {
|
||||
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;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||
: Geometry(id, element, name, doc)
|
||||
{
|
||||
LineGeometry::LineGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||
Geometry(id, element, name, doc) {
|
||||
const Scope *sc = element.Compound();
|
||||
if (!sc) {
|
||||
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 {
|
||||
return m_indices;
|
||||
}
|
||||
} // !FBX
|
||||
} // !Assimp
|
||||
} // namespace FBX
|
||||
} // namespace Assimp
|
||||
#endif
|
||||
|
||||
|
|
|
@ -52,13 +52,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../contrib/zlib/zlib.h"
|
||||
#endif
|
||||
|
||||
#include "FBXTokenizer.h"
|
||||
#include "FBXParser.h"
|
||||
#include "FBXTokenizer.h"
|
||||
#include "FBXUtil.h"
|
||||
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
#include <assimp/ByteSwapper.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -71,25 +71,21 @@ namespace {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// 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 void ParseError(const std::string &message, const Token &token) {
|
||||
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)
|
||||
{
|
||||
AI_WONT_RETURN void ParseError(const std::string &message, const Element *element) {
|
||||
if (element) {
|
||||
ParseError(message, element->KeyToken());
|
||||
}
|
||||
throw DeadlyImportError("FBX-Parser ", message);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ParseError(const std::string& message, TokenPtr token)
|
||||
{
|
||||
void ParseError(const std::string &message, TokenPtr token) {
|
||||
if (token) {
|
||||
ParseError(message, *token);
|
||||
}
|
||||
|
@ -109,15 +105,14 @@ namespace {
|
|||
::memcpy(&result, data, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Assimp {
|
||||
namespace FBX {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Element::Element(const Token& key_token, Parser& parser)
|
||||
: key_token(key_token)
|
||||
{
|
||||
Element::Element(const Token &key_token, Parser &parser) :
|
||||
key_token(key_token) {
|
||||
TokenPtr n = nullptr;
|
||||
do {
|
||||
n = parser.AdvanceToNextToken();
|
||||
|
@ -160,19 +155,16 @@ Element::Element(const Token& key_token, Parser& parser)
|
|||
parser.AdvanceToNextToken();
|
||||
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
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Scope::Scope(Parser& parser,bool topLevel)
|
||||
{
|
||||
Scope::Scope(Parser &parser, bool topLevel) {
|
||||
if (!topLevel) {
|
||||
TokenPtr t = parser.CurrentToken();
|
||||
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) {
|
||||
delete v.second;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::Parser (const TokenList& tokens, bool is_binary)
|
||||
: tokens(tokens)
|
||||
, last()
|
||||
, current()
|
||||
, cursor(tokens.begin())
|
||||
, is_binary(is_binary)
|
||||
{
|
||||
Parser::Parser(const TokenList &tokens, bool is_binary) :
|
||||
tokens(tokens), last(), current(), cursor(tokens.begin()), is_binary(is_binary) {
|
||||
ASSIMP_LOG_DEBUG("Parsing FBX tokens");
|
||||
root.reset(new Scope(*this, true));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::~Parser()
|
||||
{
|
||||
Parser::~Parser() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::AdvanceToNextToken()
|
||||
{
|
||||
TokenPtr Parser::AdvanceToNextToken() {
|
||||
last = current;
|
||||
if (cursor == tokens.end()) {
|
||||
current = nullptr;
|
||||
|
@ -244,20 +228,17 @@ TokenPtr Parser::AdvanceToNextToken()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::CurrentToken() const
|
||||
{
|
||||
TokenPtr Parser::CurrentToken() const {
|
||||
return current;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::LastToken() const
|
||||
{
|
||||
TokenPtr Parser::LastToken() const {
|
||||
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;
|
||||
|
||||
if (t.Type() != TokenType_DATA) {
|
||||
|
@ -265,8 +246,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
|
|||
return 0L;
|
||||
}
|
||||
|
||||
if(t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'L') {
|
||||
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
|
||||
err_out = nullptr;
|
||||
|
||||
|
@ -303,8 +282,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'L') {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
float ParseTokenAsFloat(const Token& t, const char*& err_out)
|
||||
{
|
||||
float ParseTokenAsFloat(const Token &t, const char *&err_out) {
|
||||
err_out = nullptr;
|
||||
|
||||
if (t.Type() != TokenType_DATA) {
|
||||
|
@ -349,8 +325,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
if(t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'F' && data[0] != 'D') {
|
||||
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') {
|
||||
return SafeParse<float>(data + 1, t.end());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int ParseTokenAsInt(const Token& t, const char*& err_out)
|
||||
{
|
||||
int ParseTokenAsInt(const Token &t, const char *&err_out) {
|
||||
err_out = nullptr;
|
||||
|
||||
if (t.Type() != TokenType_DATA) {
|
||||
|
@ -392,8 +364,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'I') {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
|
||||
{
|
||||
int64_t ParseTokenAsInt64(const Token &t, const char *&err_out) {
|
||||
err_out = nullptr;
|
||||
|
||||
if (t.Type() != TokenType_DATA) {
|
||||
|
@ -428,8 +397,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
|
|||
return 0L;
|
||||
}
|
||||
|
||||
if (t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'L') {
|
||||
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;
|
||||
|
||||
if (t.Type() != TokenType_DATA) {
|
||||
|
@ -465,8 +432,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
|
|||
return "";
|
||||
}
|
||||
|
||||
if(t.IsBinary())
|
||||
{
|
||||
if (t.IsBinary()) {
|
||||
const char *data = t.begin();
|
||||
if (data[0] != 'S') {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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,
|
||||
const Element& el)
|
||||
{
|
||||
const Element &el) {
|
||||
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);
|
||||
}
|
||||
|
@ -519,13 +483,11 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
|
|||
data += 5;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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,
|
||||
std::vector<char> &buff,
|
||||
const Element& /*el*/)
|
||||
{
|
||||
const Element & /*el*/) {
|
||||
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
|
||||
AI_SWAP4(encmode);
|
||||
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
|
||||
uint32_t stride = 0;
|
||||
switch(type)
|
||||
{
|
||||
switch (type) {
|
||||
case 'f':
|
||||
case 'i':
|
||||
stride = 4;
|
||||
|
@ -563,8 +524,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
|
|||
|
||||
// plain data, no compression
|
||||
std::copy(data, end, buff.begin());
|
||||
}
|
||||
else if(encmode == 1) {
|
||||
} else if (encmode == 1) {
|
||||
// zlib/deflate, next comes ZIP head (0x78 0x01)
|
||||
// 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);
|
||||
}
|
||||
|
||||
} // !anon
|
||||
|
||||
} // namespace
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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);
|
||||
|
||||
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;
|
||||
DefaultLogger::get()->info( stream.str() );
|
||||
}*/
|
||||
}
|
||||
else if (type == 'f') {
|
||||
} else if (type == 'f') {
|
||||
const float *f = reinterpret_cast<const float *>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count3; ++i, f += 3) {
|
||||
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
|
||||
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
||||
{
|
||||
void ParseVectorDataArray(std::vector<aiColor4D> &out, const Element &el) {
|
||||
out.resize(0);
|
||||
const TokenList &tok = el.Tokens();
|
||||
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[3])));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
} else if (type == 'f') {
|
||||
const float *f = reinterpret_cast<const float *>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count4; ++i, f += 4) {
|
||||
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
|
||||
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
||||
{
|
||||
void ParseVectorDataArray(std::vector<aiVector2D> &out, const Element &el) {
|
||||
out.resize(0);
|
||||
const TokenList &tok = el.Tokens();
|
||||
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]),
|
||||
static_cast<float>(d[1])));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
} else if (type == 'f') {
|
||||
const float *f = reinterpret_cast<const float *>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count2; ++i, f += 2) {
|
||||
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
|
||||
void ParseVectorDataArray(std::vector<int>& out, const Element& el)
|
||||
{
|
||||
void ParseVectorDataArray(std::vector<int> &out, const Element &el) {
|
||||
out.resize(0);
|
||||
const TokenList &tok = el.Tokens();
|
||||
if (tok.empty()) {
|
||||
|
@ -907,11 +856,9 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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);
|
||||
const TokenList &tok = el.Tokens();
|
||||
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) {
|
||||
out.push_back(static_cast<float>(*d));
|
||||
}
|
||||
}
|
||||
else if (type == 'f') {
|
||||
} else if (type == 'f') {
|
||||
const float *f = reinterpret_cast<const float *>(&buff[0]);
|
||||
for (unsigned int i = 0; i < count; ++i, ++f) {
|
||||
out.push_back(*f);
|
||||
|
@ -971,8 +917,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// read an array of uints
|
||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
||||
{
|
||||
void ParseVectorDataArray(std::vector<unsigned int> &out, const Element &el) {
|
||||
out.resize(0);
|
||||
const TokenList &tok = el.Tokens();
|
||||
if (tok.empty()) {
|
||||
|
@ -1033,11 +978,9 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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);
|
||||
const TokenList &tok = el.Tokens();
|
||||
if (tok.empty()) {
|
||||
|
@ -1094,8 +1037,7 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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);
|
||||
const TokenList &tok = el.Tokens();
|
||||
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;
|
||||
ParseVectorDataArray(values, element);
|
||||
|
||||
|
@ -1162,7 +1103,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
|
|||
|
||||
aiMatrix4x4 result;
|
||||
|
||||
|
||||
result.a1 = values[0];
|
||||
result.a2 = values[1];
|
||||
result.a3 = values[2];
|
||||
|
@ -1187,11 +1127,9 @@ aiMatrix4x4 ReadMatrix(const Element& element)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsString() with ParseError handling
|
||||
std::string ParseTokenAsString(const Token& t)
|
||||
{
|
||||
std::string ParseTokenAsString(const Token &t) {
|
||||
const char *err;
|
||||
const std::string &i = ParseTokenAsString(t, 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
|
||||
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];
|
||||
if (!el) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// extract required compound scope
|
||||
const Scope& GetRequiredScope(const Element& el)
|
||||
{
|
||||
const Scope &GetRequiredScope(const Element &el) {
|
||||
const Scope *const s = el.Compound();
|
||||
if (!s) {
|
||||
ParseError("expected compound scope", &el);
|
||||
|
@ -1233,11 +1168,9 @@ const Scope& GetRequiredScope(const Element& el)
|
|||
return *s;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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();
|
||||
if (index >= t.size()) {
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsID() with ParseError handling
|
||||
uint64_t ParseTokenAsID(const Token& t)
|
||||
{
|
||||
uint64_t ParseTokenAsID(const Token &t) {
|
||||
const char *err;
|
||||
const uint64_t i = ParseTokenAsID(t, err);
|
||||
if (err) {
|
||||
|
@ -1259,11 +1190,9 @@ uint64_t ParseTokenAsID(const Token& t)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsDim() with ParseError handling
|
||||
size_t ParseTokenAsDim(const Token& t)
|
||||
{
|
||||
size_t ParseTokenAsDim(const Token &t) {
|
||||
const char *err;
|
||||
const size_t i = ParseTokenAsDim(t, err);
|
||||
if (err) {
|
||||
|
@ -1272,11 +1201,9 @@ size_t ParseTokenAsDim(const Token& t)
|
|||
return i;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsFloat() with ParseError handling
|
||||
float ParseTokenAsFloat(const Token& t)
|
||||
{
|
||||
float ParseTokenAsFloat(const Token &t) {
|
||||
const char *err;
|
||||
const float i = ParseTokenAsFloat(t, err);
|
||||
if (err) {
|
||||
|
@ -1287,8 +1214,7 @@ float ParseTokenAsFloat(const Token& t)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsInt() with ParseError handling
|
||||
int ParseTokenAsInt(const Token& t)
|
||||
{
|
||||
int ParseTokenAsInt(const Token &t) {
|
||||
const char *err;
|
||||
const int i = ParseTokenAsInt(t, err);
|
||||
if (err) {
|
||||
|
@ -1299,8 +1225,7 @@ int ParseTokenAsInt(const Token& t)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// wrapper around ParseTokenAsInt64() with ParseError handling
|
||||
int64_t ParseTokenAsInt64(const Token& t)
|
||||
{
|
||||
int64_t ParseTokenAsInt64(const Token &t) {
|
||||
const char *err;
|
||||
const int64_t i = ParseTokenAsInt64(t, err);
|
||||
if (err) {
|
||||
|
@ -1309,7 +1234,7 @@ int64_t ParseTokenAsInt64(const Token& t)
|
|||
return i;
|
||||
}
|
||||
|
||||
} // !FBX
|
||||
} // !Assimp
|
||||
} // namespace FBX
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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)));
|
||||
|
||||
if (mVerts.empty()) {
|
||||
|
@ -105,36 +104,31 @@ aiMesh* TempMesh::ToMesh()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::Clear()
|
||||
{
|
||||
void TempMesh::Clear() {
|
||||
mVerts.clear();
|
||||
mVertcnt.clear();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::Transform(const IfcMatrix4& mat)
|
||||
{
|
||||
void TempMesh::Transform(const IfcMatrix4 &mat) {
|
||||
for (IfcVector3 &v : mVerts) {
|
||||
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()));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::Append(const TempMesh& other)
|
||||
{
|
||||
void TempMesh::Append(const TempMesh &other) {
|
||||
mVerts.insert(mVerts.end(), other.mVerts.begin(), other.mVerts.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
|
||||
// Newell's algorithm. The length of the normals gives the area
|
||||
// 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)
|
||||
{
|
||||
std::vector<IfcFloat> temp((cnt+2)*3);
|
||||
for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs )
|
||||
{
|
||||
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3 *vtcs, size_t cnt, bool normalize) {
|
||||
const size_t Capa = cnt + 2;
|
||||
std::vector<IfcFloat> temp((Capa)*3);
|
||||
for (size_t vofs = 0, i = 0; vofs < cnt; ++vofs) {
|
||||
const IfcVector3 &v = vtcs[vofs];
|
||||
temp[i++] = v.x;
|
||||
temp[i++] = v.y;
|
||||
|
@ -179,22 +172,19 @@ IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bo
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||
bool normalize,
|
||||
size_t ofs) const
|
||||
{
|
||||
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3> &normals, bool normalize, size_t ofs) const {
|
||||
size_t max_vcount = 0;
|
||||
std::vector<unsigned int>::const_iterator begin = mVertcnt.begin() + ofs, end = mVertcnt.end(), iit;
|
||||
for (iit = begin; iit != end; ++iit) {
|
||||
max_vcount = std::max(max_vcount, static_cast<size_t>(*iit));
|
||||
}
|
||||
|
||||
std::vector<IfcFloat> temp((max_vcount+2)*4);
|
||||
const size_t Capa = max_vcount + 2;
|
||||
std::vector<IfcFloat> temp(Capa * 4);
|
||||
normals.reserve(normals.size() + mVertcnt.size() - ofs);
|
||||
|
||||
// `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());
|
||||
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) {
|
||||
|
@ -229,30 +219,26 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
|
||||
struct CompareVector
|
||||
{
|
||||
bool operator () (const IfcVector3& a, const IfcVector3& b) const
|
||||
{
|
||||
struct CompareVector {
|
||||
bool operator()(const IfcVector3 &a, const IfcVector3 &b) const {
|
||||
IfcVector3 d = a - b;
|
||||
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);
|
||||
}
|
||||
};
|
||||
struct FindVector
|
||||
{
|
||||
struct FindVector {
|
||||
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); }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void TempMesh::FixupFaceOrientation()
|
||||
{
|
||||
void TempMesh::FixupFaceOrientation() {
|
||||
const IfcVector3 vavg = Center();
|
||||
|
||||
// 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
|
||||
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)
|
||||
facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a);
|
||||
}
|
||||
// determine neighbourhood for all polys
|
||||
std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX);
|
||||
std::vector<size_t> tempIntersect(10);
|
||||
for( size_t a = 0; a < mVertcnt.size(); ++a )
|
||||
{
|
||||
for( size_t b = 0; b < mVertcnt[a]; ++b )
|
||||
{
|
||||
for (size_t a = 0; a < mVertcnt.size(); ++a) {
|
||||
for (size_t b = 0; b < mVertcnt[a]; ++b) {
|
||||
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> &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
|
||||
// faces to have the same winding until all faces have been tested.
|
||||
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
|
||||
size_t farthestIndex = SIZE_MAX;
|
||||
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])
|
||||
continue;
|
||||
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();
|
||||
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
|
||||
IfcVector3 farthestNormal = ComputePolygonNormal(mVerts.data() + faceStartIndices[farthestIndex], mVertcnt[farthestIndex]);
|
||||
IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
|
||||
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0))
|
||||
/ IfcFloat(mVertcnt[farthestIndex]);
|
||||
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0)) /
|
||||
IfcFloat(mVertcnt[farthestIndex]);
|
||||
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
|
||||
// the file.
|
||||
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
|
||||
{
|
||||
if ((farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4) {
|
||||
size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex];
|
||||
std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc);
|
||||
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
|
||||
|
@ -334,15 +318,13 @@ void TempMesh::FixupFaceOrientation()
|
|||
todo.push_back(farthestIndex);
|
||||
|
||||
// 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 vsi = faceStartIndices[tdf], vc = mVertcnt[tdf];
|
||||
todo.pop_back();
|
||||
|
||||
// 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
|
||||
size_t nbi = neighbour[vsi + a];
|
||||
if (nbi == SIZE_MAX || faceDone[nbi])
|
||||
|
@ -358,8 +340,7 @@ void TempMesh::FixupFaceOrientation()
|
|||
// to reverse the neighbour
|
||||
nb_vidx = (nb_vidx + 1) % nbvc;
|
||||
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(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
|
||||
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
|
||||
|
@ -390,7 +371,6 @@ void TempMesh::RemoveAdjacentDuplicates() {
|
|||
IfcVector3 vmin, vmax;
|
||||
ArrayBounds(&*base, cnt, vmin, vmax);
|
||||
|
||||
|
||||
const IfcFloat epsilon = (vmax - vmin).SquareLength() / static_cast<IfcFloat>(1e9);
|
||||
//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);
|
||||
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";
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
IfcFloat ConvertSIPrefix(const std::string& prefix)
|
||||
{
|
||||
IfcFloat ConvertSIPrefix(const std::string &prefix) {
|
||||
if (prefix == "EXA") {
|
||||
return 1e18f;
|
||||
}
|
||||
else if (prefix == "PETA") {
|
||||
} else if (prefix == "PETA") {
|
||||
return 1e15f;
|
||||
}
|
||||
else if (prefix == "TERA") {
|
||||
} else if (prefix == "TERA") {
|
||||
return 1e12f;
|
||||
}
|
||||
else if (prefix == "GIGA") {
|
||||
} else if (prefix == "GIGA") {
|
||||
return 1e9f;
|
||||
}
|
||||
else if (prefix == "MEGA") {
|
||||
} else if (prefix == "MEGA") {
|
||||
return 1e6f;
|
||||
}
|
||||
else if (prefix == "KILO") {
|
||||
} else if (prefix == "KILO") {
|
||||
return 1e3f;
|
||||
}
|
||||
else if (prefix == "HECTO") {
|
||||
} else if (prefix == "HECTO") {
|
||||
return 1e2f;
|
||||
}
|
||||
else if (prefix == "DECA") {
|
||||
} else if (prefix == "DECA") {
|
||||
return 1e-0f;
|
||||
}
|
||||
else if (prefix == "DECI") {
|
||||
} else if (prefix == "DECI") {
|
||||
return 1e-1f;
|
||||
}
|
||||
else if (prefix == "CENTI") {
|
||||
} else if (prefix == "CENTI") {
|
||||
return 1e-2f;
|
||||
}
|
||||
else if (prefix == "MILLI") {
|
||||
} else if (prefix == "MILLI") {
|
||||
return 1e-3f;
|
||||
}
|
||||
else if (prefix == "MICRO") {
|
||||
} else if (prefix == "MICRO") {
|
||||
return 1e-6f;
|
||||
}
|
||||
else if (prefix == "NANO") {
|
||||
} else if (prefix == "NANO") {
|
||||
return 1e-9f;
|
||||
}
|
||||
else if (prefix == "PICO") {
|
||||
} else if (prefix == "PICO") {
|
||||
return 1e-12f;
|
||||
}
|
||||
else if (prefix == "FEMTO") {
|
||||
} else if (prefix == "FEMTO") {
|
||||
return 1e-15f;
|
||||
}
|
||||
else if (prefix == "ATTO") {
|
||||
} else if (prefix == "ATTO") {
|
||||
return 1e-18f;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
|
||||
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.g = static_cast<float>(in.Green);
|
||||
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>()) {
|
||||
out.r = out.g = out.b = static_cast<float>(*r);
|
||||
if (base) {
|
||||
|
@ -530,20 +489,17 @@ void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,Conver
|
|||
out.g *= static_cast<float>(base->g);
|
||||
out.b *= static_cast<float>(base->b);
|
||||
out.a = static_cast<float>(base->a);
|
||||
}
|
||||
else out.a = 1.0;
|
||||
}
|
||||
else if (const Schema_2x3::IfcColourRgb* const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
|
||||
} else
|
||||
out.a = 1.0;
|
||||
} else if (const Schema_2x3::IfcColourRgb *const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
|
||||
ConvertColor(out, *rgb);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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();
|
||||
for (size_t i = 0; i < in.Coordinates.size(); ++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);
|
||||
out *= in.Magnitude;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
|
||||
{
|
||||
void ConvertDirection(IfcVector3 &out, const Schema_2x3::IfcDirection &in) {
|
||||
out = IfcVector3();
|
||||
for (size_t i = 0; i < in.DirectionRatios.size(); ++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.b1 = x.y;
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
if (in.Axis) {
|
||||
ConvertDirection(axis, in.Axis.Get());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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;
|
||||
ConvertCartesianPoint(loc, op.LocalOrigin);
|
||||
|
||||
|
@ -679,14 +624,12 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
|
|||
IfcMatrix4::Translation(loc, locm);
|
||||
AssignMatrixAxes(out, x, y, z);
|
||||
|
||||
|
||||
IfcVector3 vscale;
|
||||
if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform *nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) {
|
||||
vscale.x = nuni->Scale ? op.Scale.Get() : 1.f;
|
||||
vscale.y = nuni->Scale2 ? nuni->Scale2.Get() : 1.f;
|
||||
vscale.z = nuni->Scale3 ? nuni->Scale3.Get() : 1.f;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
const IfcFloat sc = op.Scale ? op.Scale.Get() : 1.f;
|
||||
vscale = IfcVector3(sc, sc, sc);
|
||||
}
|
||||
|
@ -697,8 +640,7 @@ void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTra
|
|||
out = locm * out * s;
|
||||
}
|
||||
|
||||
|
||||
} // ! IFC
|
||||
} // ! Assimp
|
||||
} // namespace IFC
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,9 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* @brief Implementation of the CPP-API class #Importer
|
||||
*/
|
||||
|
||||
#include <assimp/version.h>
|
||||
#include <assimp/config.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/version.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/* 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
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common/Importer.h"
|
||||
#include "Common/BaseProcess.h"
|
||||
#include "Common/DefaultProgressHandler.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
#include "Common/Importer.h"
|
||||
#include "Common/ScenePreprocessor.h"
|
||||
#include "Common/ScenePrivate.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/GenericProperty.h>
|
||||
#include <assimp/MemoryIOWrapper.h>
|
||||
#include <assimp/Profiler.h>
|
||||
#include <assimp/TinyFormatter.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/Profiler.h>
|
||||
#include <assimp/commonMetaData.h>
|
||||
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <cctype>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include <assimp/DefaultIOStream.h>
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
# include "PostProcessing/ValidateDataStructure.h"
|
||||
#endif
|
||||
|
@ -99,8 +100,9 @@ namespace Assimp {
|
|||
|
||||
// PostStepRegistry.cpp
|
||||
void GetPostProcessingStepInstanceList(std::vector<BaseProcess *> &out);
|
||||
}
|
||||
} // namespace Assimp
|
||||
|
||||
// clang-format on
|
||||
using namespace Assimp;
|
||||
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() {
|
||||
try {
|
||||
return AllocateFromAssimpHeap::operator new(num_bytes);
|
||||
}
|
||||
catch( ... ) {
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +146,8 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Importer constructor.
|
||||
Importer::Importer()
|
||||
: pimpl( new ImporterPimpl ) {
|
||||
Importer::Importer() :
|
||||
pimpl(new ImporterPimpl) {
|
||||
pimpl->mScene = nullptr;
|
||||
pimpl->mErrorString = "";
|
||||
|
||||
|
@ -652,8 +653,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
|
|||
// Get file size for progress handler
|
||||
IOStream *fileIO = pimpl->mIOHandler->Open(pFile);
|
||||
uint32_t fileSize = 0;
|
||||
if (fileIO)
|
||||
{
|
||||
if (fileIO) {
|
||||
fileSize = static_cast<uint32_t>(fileIO->FileSize());
|
||||
pimpl->mIOHandler->Close(fileIO);
|
||||
}
|
||||
|
@ -738,7 +738,8 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
|
|||
#endif
|
||||
|
||||
ASSIMP_LOG_ERROR(pimpl->mErrorString);
|
||||
delete pimpl->mScene; pimpl->mScene = nullptr;
|
||||
delete pimpl->mScene;
|
||||
pimpl->mScene = nullptr;
|
||||
}
|
||||
#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
||||
|
||||
|
@ -748,7 +749,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
|
|||
return pimpl->mScene;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Apply post-processing to the currently bound scene
|
||||
const aiScene *Importer::ApplyPostProcessing(unsigned int pFlags) {
|
||||
|
@ -781,8 +781,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
|
|||
}
|
||||
#endif // no validation
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
if (pimpl->bExtraVerbose)
|
||||
{
|
||||
if (pimpl->bExtraVerbose) {
|
||||
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
|
||||
#endif // no validation
|
||||
|
@ -870,8 +869,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
// 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.
|
||||
if ( requestValidation )
|
||||
{
|
||||
if (requestValidation) {
|
||||
ValidateDSProcess ds;
|
||||
ds.ExecuteOnScene(this);
|
||||
if (!pimpl->mScene) {
|
||||
|
@ -880,8 +878,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
|
|||
}
|
||||
#endif // no validation
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
if ( pimpl->bExtraVerbose )
|
||||
{
|
||||
if (pimpl->bExtraVerbose) {
|
||||
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
|
||||
ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
|
||||
#endif // no validation
|
||||
|
@ -947,7 +944,6 @@ const aiImporterDesc* Importer::GetImporterInfo(size_t index) const {
|
|||
return pimpl->mImporter[index]->GetInfo();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BaseImporter *Importer::GetImporter(size_t index) const {
|
||||
ai_assert(nullptr != pimpl);
|
||||
|
@ -975,7 +971,8 @@ size_t Importer::GetImporterIndex (const char* szExtension) const {
|
|||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// skip over wildcard and dot characters at string head --
|
||||
for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
|
||||
for (; *szExtension == '*' || *szExtension == '.'; ++szExtension)
|
||||
;
|
||||
|
||||
std::string ext(szExtension);
|
||||
if (ext.empty()) {
|
||||
|
@ -1106,8 +1103,7 @@ aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& i
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Get the memory requirements of a single node
|
||||
inline
|
||||
void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) {
|
||||
inline void AddNodeWeight(unsigned int &iScene, const aiNode *pcNode) {
|
||||
if (nullptr == pcNode) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef INCLUDED_AI_IMPORTER_H
|
||||
#define INCLUDED_AI_IMPORTER_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <assimp/matrix4x4.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct aiScene;
|
||||
|
||||
|
@ -58,7 +58,6 @@ namespace Assimp {
|
|||
class BaseProcess;
|
||||
class SharedPostProcessInfo;
|
||||
|
||||
|
||||
//! @cond never
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Internal PIMPL implementation for Assimp::Importer
|
||||
|
@ -70,7 +69,7 @@ namespace Assimp {
|
|||
class ImporterPimpl {
|
||||
public:
|
||||
// Data type to store the key hash
|
||||
typedef unsigned int KeyType;
|
||||
using KeyType = unsigned int;
|
||||
|
||||
// typedefs for our four configuration maps.
|
||||
// We don't need more, so there is no need for a generic solution
|
||||
|
@ -126,9 +125,7 @@ public:
|
|||
ImporterPimpl() AI_NO_EXCEPT;
|
||||
};
|
||||
|
||||
inline
|
||||
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
|
||||
mIOHandler( nullptr ),
|
||||
inline ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : mIOHandler(nullptr),
|
||||
mIsDefaultHandler(false),
|
||||
mProgressHandler(nullptr),
|
||||
mIsDefaultProgressHandler(false),
|
||||
|
@ -214,8 +211,7 @@ public:
|
|||
unsigned int AddLoadRequest(
|
||||
const std::string &file,
|
||||
unsigned int steps = 0,
|
||||
const PropertyMap *map = nullptr
|
||||
);
|
||||
const PropertyMap *map = nullptr);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Get an imported scene.
|
||||
|
@ -227,8 +223,7 @@ public:
|
|||
* @return nullptr if there is no scene with this file name
|
||||
* in the queue of the scene hasn't been loaded yet. */
|
||||
aiScene *GetImport(
|
||||
unsigned int which
|
||||
);
|
||||
unsigned int which);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Waits until all scenes have been loaded. This returns
|
||||
|
|
|
@ -45,8 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_POLYTOOLS_H_INCLUDED
|
||||
#define AI_POLYTOOLS_H_INCLUDED
|
||||
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/vector3.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -55,8 +56,7 @@ namespace Assimp {
|
|||
* The function accepts an unconstrained template parameter for use with
|
||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||
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
|
||||
const aiVector2D v0 = p1 - 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);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** Check whether the winding order of a given polygon is counter-clockwise.
|
||||
* 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)) {
|
||||
convex_turn = AI_MATH_PI_F - theta;
|
||||
convex_sum += convex_turn;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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])) {
|
||||
convex_turn = AI_MATH_PI_F - theta;
|
||||
convex_sum += convex_turn;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
convex_sum -= AI_MATH_PI_F - theta;
|
||||
}
|
||||
|
||||
return convex_sum >= (2 * AI_MATH_PI_F);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
/** 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
|
||||
* this method is much faster than the 'other' NewellNormal()
|
||||
*/
|
||||
template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
|
||||
inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z)
|
||||
{
|
||||
template <size_t ofs_x, size_t ofs_y, size_t ofs_z, typename TReal>
|
||||
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
|
||||
x[(num + 0) * ofs_x] = x[0];
|
||||
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 *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_yz += (*yptr) * ((*zhigh) - (*zlow));
|
||||
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);
|
||||
}
|
||||
|
||||
} // ! Assimp
|
||||
} // namespace Assimp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,14 +60,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
|
||||
|
||||
#include "PostProcessing/TriangulateProcess.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
#include "Common/PolyTools.h"
|
||||
#include "PostProcessing/ProcessHelper.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
//#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_X 70
|
||||
|
@ -78,34 +78,29 @@ using namespace Assimp;
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
TriangulateProcess::TriangulateProcess()
|
||||
{
|
||||
TriangulateProcess::TriangulateProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
TriangulateProcess::~TriangulateProcess()
|
||||
{
|
||||
TriangulateProcess::~TriangulateProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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");
|
||||
|
||||
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 (TriangulateMesh(pScene->mMeshes[a])) {
|
||||
bHas = true;
|
||||
|
@ -120,44 +115,54 @@ void TriangulateProcess::Execute( aiScene* pScene)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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) {
|
||||
static bool validateNumIndices(aiMesh *mesh) {
|
||||
bool bNeed = false;
|
||||
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
const aiFace& face = pMesh->mFaces[a];
|
||||
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
|
||||
const aiFace &face = mesh->mFaces[a];
|
||||
if (face.mNumIndices != 3) {
|
||||
bNeed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bNeed)
|
||||
return false;
|
||||
}
|
||||
else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find out how many output faces we'll get
|
||||
uint32_t numOut = 0, max_out = 0;
|
||||
bool get_normals = true;
|
||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||
aiFace& face = pMesh->mFaces[a];
|
||||
return bNeed;
|
||||
}
|
||||
|
||||
static void calulateNumOutputFaces(aiMesh *mesh, size_t &numOut, size_t &maxOut, bool &getNormals) {
|
||||
numOut = maxOut = 0;
|
||||
getNormals = true;
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
|
||||
aiFace &face = mesh->mFaces[a];
|
||||
if (face.mNumIndices <= 4) {
|
||||
get_normals = false;
|
||||
getNormals = false;
|
||||
}
|
||||
if (face.mNumIndices <= 3) {
|
||||
numOut++;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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
|
||||
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
|
||||
// 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
|
||||
// nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||
}
|
||||
|
@ -176,6 +181,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
|
||||
|
||||
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<aiVector2D> temp_verts(max_out + 2);
|
||||
|
||||
|
@ -215,8 +221,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
aiFace *const last_face = curOut;
|
||||
|
||||
// if it's a simple point,line or triangle: just copy it
|
||||
if( face.mNumIndices <= 3)
|
||||
{
|
||||
if (face.mNumIndices <= 3) {
|
||||
aiFace &nface = *curOut++;
|
||||
nface.mNumIndices = face.mNumIndices;
|
||||
nface.mIndices = face.mIndices;
|
||||
|
@ -275,9 +280,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
// prevent double deletion of the indices field
|
||||
face.mIndices = nullptr;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// A polygon with more than 3 vertices can be either concave or convex.
|
||||
// Usually everything we're getting is convex and we could easily
|
||||
// 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]];
|
||||
}
|
||||
|
||||
// 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;
|
||||
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) {
|
||||
for (tmp = 0; tmp < max; ++tmp)
|
||||
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 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;
|
||||
if (ax > ay) {
|
||||
if (ax > az) { /* no x coord. projection to yz */
|
||||
ac = 1; bc = 2;
|
||||
if (ax > az) { // no x coord. projection to yz
|
||||
ac = 1;
|
||||
bc = 2;
|
||||
inv = n.x;
|
||||
}
|
||||
}
|
||||
else if (ay > az) { /* no y coord. projection to zy */
|
||||
ac = 2; bc = 0;
|
||||
} else if (ay > az) { // no y coord. projection to zy
|
||||
ac = 2;
|
||||
bc = 0;
|
||||
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));
|
||||
char *loc = grid[y] + x;
|
||||
if (grid[y][x] != ' ') {
|
||||
for(;*loc != ' '; ++loc);
|
||||
for (; *loc != ' '; ++loc)
|
||||
;
|
||||
*loc++ = '_';
|
||||
}
|
||||
*(loc + ::ai_snprintf(loc, POLY_GRID_XPAD, "%i", i)) = ' ';
|
||||
}
|
||||
|
||||
|
||||
for (size_t y = 0; y < POLY_GRID_Y; ++y) {
|
||||
grid[y][POLY_GRID_X + POLY_GRID_XPAD - 1] = '\0';
|
||||
fprintf(fout, "%s\n", grid[y]);
|
||||
|
@ -367,7 +371,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
for (ear = next;; prev = ear, ear = next) {
|
||||
|
||||
// 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 (++num_found == 2) {
|
||||
break;
|
||||
|
@ -419,22 +424,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
#endif
|
||||
num = 0;
|
||||
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++;
|
||||
|
@ -461,15 +450,17 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
nface.mIndices = new unsigned int[3];
|
||||
}
|
||||
|
||||
for (tmp = 0; done[tmp]; ++tmp);
|
||||
for (tmp = 0; done[tmp]; ++tmp)
|
||||
;
|
||||
nface.mIndices[0] = tmp;
|
||||
|
||||
for (++tmp; done[tmp]; ++tmp);
|
||||
for (++tmp; done[tmp]; ++tmp)
|
||||
;
|
||||
nface.mIndices[1] = tmp;
|
||||
|
||||
for (++tmp; done[tmp]; ++tmp);
|
||||
for (++tmp; done[tmp]; ++tmp)
|
||||
;
|
||||
nface.mIndices[2] = tmp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,24 +478,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
|||
|
||||
for (aiFace *f = last_face; f != curOut;) {
|
||||
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[1] = idx[i[1]];
|
||||
i[2] = idx[i[2]];
|
||||
|
|
|
@ -96,6 +96,7 @@ SET( COMMON
|
|||
unit/Common/utSpatialSort.cpp
|
||||
unit/Common/utAssertHandler.cpp
|
||||
unit/Common/utXmlParser.cpp
|
||||
unit/Common/utPolyTools.cpp
|
||||
)
|
||||
|
||||
SET( IMPORTERS
|
||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
|
|
@ -43,9 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AV_ANIMEVALUATOR_H_INCLUDED
|
||||
#define AV_ANIMEVALUATOR_H_INCLUDED
|
||||
|
||||
#include <assimp/matrix4x4.h>
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
struct aiAnimation;
|
||||
|
||||
namespace AssimpView {
|
||||
|
||||
/**
|
||||
|
@ -74,7 +78,7 @@ public:
|
|||
* the aiAnimation. */
|
||||
const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
const aiAnimation *mAnim;
|
||||
double mLastTime;
|
||||
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,7 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AV_SCENEANIMATOR_H_INCLUDED
|
||||
#define AV_SCENEANIMATOR_H_INCLUDED
|
||||
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace AssimpView {
|
||||
|
||||
|
@ -72,13 +75,23 @@ struct SceneAnimNode {
|
|||
|
||||
//! Default construction
|
||||
SceneAnimNode() :
|
||||
mName(), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) {
|
||||
mName(),
|
||||
mParent(nullptr),
|
||||
mChildren(),
|
||||
mLocalTransform(),
|
||||
mGlobalTransform(),
|
||||
mChannelIndex(-1) {
|
||||
// empty
|
||||
}
|
||||
|
||||
//! Construction from a given name
|
||||
SceneAnimNode(const std::string &pName) :
|
||||
mName(pName), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) {
|
||||
mName(pName),
|
||||
mParent(nullptr),
|
||||
mChildren(),
|
||||
mLocalTransform(),
|
||||
mGlobalTransform(),
|
||||
mChannelIndex(-1) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -125,7 +138,7 @@ public:
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** 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.
|
||||
*/
|
||||
void Calculate(double pTime);
|
||||
|
@ -136,7 +149,7 @@ public:
|
|||
* 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
|
||||
* 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
|
||||
* Calculate() is called.
|
||||
* @param pNodeName Name of the node
|
||||
|
@ -151,7 +164,7 @@ public:
|
|||
* 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,
|
||||
* 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
|
||||
* Calculate() is called.
|
||||
* @param pNodeName Name of the node
|
||||
|
@ -190,7 +203,7 @@ public:
|
|||
/** @brief Get the current animation or NULL
|
||||
*/
|
||||
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:
|
||||
|
|
Loading…
Reference in New Issue