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
|
// Setup configuration properties for the loader
|
||||||
void FBXImporter::SetupProperties(const Importer *pImp) {
|
void FBXImporter::SetupProperties(const Importer *pImp) {
|
||||||
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||||
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||||
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||||
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||||
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||||
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||||
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||||
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||||
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||||
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||||
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||||
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||||
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||||
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -181,10 +181,10 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||||
Parser parser(tokens, is_binary);
|
Parser parser(tokens, is_binary);
|
||||||
|
|
||||||
// take the raw parse-tree and convert it to a FBX DOM
|
// take the raw parse-tree and convert it to a FBX DOM
|
||||||
Document doc(parser, settings);
|
Document doc(parser, mSettings);
|
||||||
|
|
||||||
// convert the FBX DOM to aiScene
|
// convert the FBX DOM to aiScene
|
||||||
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
|
ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
|
||||||
|
|
||||||
// size relative to cm
|
// size relative to cm
|
||||||
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
||||||
|
|
|
@ -70,27 +70,16 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
|
||||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
||||||
public:
|
public:
|
||||||
FBXImporter();
|
FBXImporter();
|
||||||
virtual ~FBXImporter();
|
~FBXImporter() override;
|
||||||
|
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
|
||||||
// --------------------
|
|
||||||
bool CanRead(const std::string &pFile,
|
|
||||||
IOSystem *pIOHandler,
|
|
||||||
bool checkSig) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --------------------
|
|
||||||
const aiImporterDesc *GetInfo() const;
|
const aiImporterDesc *GetInfo() const;
|
||||||
|
|
||||||
// --------------------
|
|
||||||
void SetupProperties(const Importer *pImp);
|
void SetupProperties(const Importer *pImp);
|
||||||
|
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||||
// --------------------
|
|
||||||
void InternReadFile(const std::string &pFile,
|
|
||||||
aiScene *pScene,
|
|
||||||
IOSystem *pIOHandler);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FBX::ImportSettings settings;
|
FBX::ImportSettings mSettings;
|
||||||
}; // !class FBXImporter
|
}; // !class FBXImporter
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -48,12 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "FBXMeshGeometry.h"
|
|
||||||
#include "FBXDocument.h"
|
#include "FBXDocument.h"
|
||||||
#include "FBXImporter.h"
|
|
||||||
#include "FBXImportSettings.h"
|
|
||||||
#include "FBXDocumentUtil.h"
|
#include "FBXDocumentUtil.h"
|
||||||
|
#include "FBXImportSettings.h"
|
||||||
|
#include "FBXImporter.h"
|
||||||
|
#include "FBXMeshGeometry.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
@ -61,17 +60,15 @@ namespace FBX {
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
Geometry::Geometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||||
: Object(id, element, name)
|
Object(id, element, name), skin() {
|
||||||
, skin()
|
const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
|
||||||
{
|
for (const Connection *con : conns) {
|
||||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
|
const Skin *const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
||||||
for(const Connection* con : conns) {
|
if (sk) {
|
||||||
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
|
||||||
if(sk) {
|
|
||||||
skin = sk;
|
skin = sk;
|
||||||
}
|
}
|
||||||
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
const BlendShape *const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
||||||
if (bsp) {
|
if (bsp) {
|
||||||
blendShapes.push_back(bsp);
|
blendShapes.push_back(bsp);
|
||||||
}
|
}
|
||||||
|
@ -79,48 +76,46 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Geometry::~Geometry()
|
Geometry::~Geometry() {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
const std::vector<const BlendShape *> &Geometry::GetBlendShapes() const {
|
||||||
return blendShapes;
|
return blendShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const Skin* Geometry::DeformerSkin() const {
|
const Skin *Geometry::DeformerSkin() const {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
MeshGeometry::MeshGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||||
: Geometry(id, element,name, doc)
|
Geometry(id, element, name, doc) {
|
||||||
{
|
const Scope *sc = element.Compound();
|
||||||
const Scope* sc = element.Compound();
|
|
||||||
if (!sc) {
|
if (!sc) {
|
||||||
DOMError("failed to read Geometry object (class: Mesh), no data scope found");
|
DOMError("failed to read Geometry object (class: Mesh), no data scope found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// must have Mesh elements:
|
// must have Mesh elements:
|
||||||
const Element& Vertices = GetRequiredElement(*sc,"Vertices",&element);
|
const Element &Vertices = GetRequiredElement(*sc, "Vertices", &element);
|
||||||
const Element& PolygonVertexIndex = GetRequiredElement(*sc,"PolygonVertexIndex",&element);
|
const Element &PolygonVertexIndex = GetRequiredElement(*sc, "PolygonVertexIndex", &element);
|
||||||
|
|
||||||
// optional Mesh elements:
|
// optional Mesh elements:
|
||||||
const ElementCollection& Layer = sc->GetCollection("Layer");
|
const ElementCollection &Layer = sc->GetCollection("Layer");
|
||||||
|
|
||||||
std::vector<aiVector3D> tempVerts;
|
std::vector<aiVector3D> tempVerts;
|
||||||
ParseVectorDataArray(tempVerts,Vertices);
|
ParseVectorDataArray(tempVerts, Vertices);
|
||||||
|
|
||||||
if(tempVerts.empty()) {
|
if (tempVerts.empty()) {
|
||||||
FBXImporter::LogWarn("encountered mesh with no vertices");
|
FBXImporter::LogWarn("encountered mesh with no vertices");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> tempFaces;
|
std::vector<int> tempFaces;
|
||||||
ParseVectorDataArray(tempFaces,PolygonVertexIndex);
|
ParseVectorDataArray(tempFaces, PolygonVertexIndex);
|
||||||
|
|
||||||
if(tempFaces.empty()) {
|
if (tempFaces.empty()) {
|
||||||
FBXImporter::LogWarn("encountered mesh with no faces");
|
FBXImporter::LogWarn("encountered mesh with no faces");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +123,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
m_faces.reserve(tempFaces.size() / 3);
|
m_faces.reserve(tempFaces.size() / 3);
|
||||||
|
|
||||||
m_mapping_offsets.resize(tempVerts.size());
|
m_mapping_offsets.resize(tempVerts.size());
|
||||||
m_mapping_counts.resize(tempVerts.size(),0);
|
m_mapping_counts.resize(tempVerts.size(), 0);
|
||||||
m_mappings.resize(tempFaces.size());
|
m_mappings.resize(tempFaces.size());
|
||||||
|
|
||||||
const size_t vertex_count = tempVerts.size();
|
const size_t vertex_count = tempVerts.size();
|
||||||
|
@ -136,10 +131,10 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
// generate output vertices, computing an adjacency table to
|
// generate output vertices, computing an adjacency table to
|
||||||
// preserve the mapping from fbx indices to *this* indexing.
|
// preserve the mapping from fbx indices to *this* indexing.
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
for(int index : tempFaces) {
|
for (int index : tempFaces) {
|
||||||
const int absi = index < 0 ? (-index - 1) : index;
|
const int absi = index < 0 ? (-index - 1) : index;
|
||||||
if(static_cast<size_t>(absi) >= vertex_count) {
|
if (static_cast<size_t>(absi) >= vertex_count) {
|
||||||
DOMError("polygon vertex index out of range",&PolygonVertexIndex);
|
DOMError("polygon vertex index out of range", &PolygonVertexIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vertices.push_back(tempVerts[absi]);
|
m_vertices.push_back(tempVerts[absi]);
|
||||||
|
@ -162,7 +157,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
for(int index : tempFaces) {
|
for (int index : tempFaces) {
|
||||||
const int absi = index < 0 ? (-index - 1) : index;
|
const int absi = index < 0 ? (-index - 1) : index;
|
||||||
m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
|
m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
|
||||||
}
|
}
|
||||||
|
@ -172,19 +167,18 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
// if settings.readAllLayers is false:
|
// if settings.readAllLayers is false:
|
||||||
// * read only the layer with index 0, but warn about any further layers
|
// * read only the layer with index 0, but warn about any further layers
|
||||||
for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
|
for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
|
||||||
const TokenList& tokens = (*it).second->Tokens();
|
const TokenList &tokens = (*it).second->Tokens();
|
||||||
|
|
||||||
const char* err;
|
const char *err;
|
||||||
const int index = ParseTokenAsInt(*tokens[0], err);
|
const int index = ParseTokenAsInt(*tokens[0], err);
|
||||||
if(err) {
|
if (err) {
|
||||||
DOMError(err,&element);
|
DOMError(err, &element);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.Settings().readAllLayers || index == 0) {
|
if (doc.Settings().readAllLayers || index == 0) {
|
||||||
const Scope& layer = GetRequiredScope(*(*it).second);
|
const Scope &layer = GetRequiredScope(*(*it).second);
|
||||||
ReadLayer(layer);
|
ReadLayer(layer);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FBXImporter::LogWarn("ignoring additional geometry layers");
|
FBXImporter::LogWarn("ignoring additional geometry layers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,151 +190,142 @@ MeshGeometry::~MeshGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
|
const std::vector<aiVector3D> &MeshGeometry::GetVertices() const {
|
||||||
return m_vertices;
|
return m_vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
|
const std::vector<aiVector3D> &MeshGeometry::GetNormals() const {
|
||||||
return m_normals;
|
return m_normals;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
|
const std::vector<aiVector3D> &MeshGeometry::GetTangents() const {
|
||||||
return m_tangents;
|
return m_tangents;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
|
const std::vector<aiVector3D> &MeshGeometry::GetBinormals() const {
|
||||||
return m_binormals;
|
return m_binormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
|
const std::vector<unsigned int> &MeshGeometry::GetFaceIndexCounts() const {
|
||||||
return m_faces;
|
return m_faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector2D>& MeshGeometry::GetTextureCoords( unsigned int index ) const {
|
const std::vector<aiVector2D> &MeshGeometry::GetTextureCoords(unsigned int index) const {
|
||||||
static const std::vector<aiVector2D> empty;
|
static const std::vector<aiVector2D> empty;
|
||||||
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ];
|
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
|
std::string MeshGeometry::GetTextureCoordChannelName(unsigned int index) const {
|
||||||
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[ index ];
|
return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index ) const {
|
const std::vector<aiColor4D> &MeshGeometry::GetVertexColors(unsigned int index) const {
|
||||||
static const std::vector<aiColor4D> empty;
|
static const std::vector<aiColor4D> empty;
|
||||||
return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ];
|
return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
|
const MatIndexArray &MeshGeometry::GetMaterialIndices() const {
|
||||||
return m_materials;
|
return m_materials;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
|
const unsigned int *MeshGeometry::ToOutputVertexIndex(unsigned int in_index, unsigned int &count) const {
|
||||||
if ( in_index >= m_mapping_counts.size() ) {
|
if (in_index >= m_mapping_counts.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
|
ai_assert(m_mapping_counts.size() == m_mapping_offsets.size());
|
||||||
count = m_mapping_counts[ in_index ];
|
count = m_mapping_counts[in_index];
|
||||||
|
|
||||||
ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
|
ai_assert(m_mapping_offsets[in_index] + count <= m_mappings.size());
|
||||||
|
|
||||||
return &m_mappings[ m_mapping_offsets[ in_index ] ];
|
return &m_mappings[m_mapping_offsets[in_index]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
|
unsigned int MeshGeometry::FaceForVertexIndex(unsigned int in_index) const {
|
||||||
ai_assert( in_index < m_vertices.size() );
|
ai_assert(in_index < m_vertices.size());
|
||||||
|
|
||||||
// in the current conversion pattern this will only be needed if
|
// in the current conversion pattern this will only be needed if
|
||||||
// weights are present, so no need to always pre-compute this table
|
// weights are present, so no need to always pre-compute this table
|
||||||
if ( m_facesVertexStartIndices.empty() ) {
|
if (m_facesVertexStartIndices.empty()) {
|
||||||
m_facesVertexStartIndices.resize( m_faces.size() + 1, 0 );
|
m_facesVertexStartIndices.resize(m_faces.size() + 1, 0);
|
||||||
|
|
||||||
std::partial_sum( m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1 );
|
std::partial_sum(m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1);
|
||||||
m_facesVertexStartIndices.pop_back();
|
m_facesVertexStartIndices.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
ai_assert( m_facesVertexStartIndices.size() == m_faces.size() );
|
ai_assert(m_facesVertexStartIndices.size() == m_faces.size());
|
||||||
const std::vector<unsigned int>::iterator it = std::upper_bound(
|
const std::vector<unsigned int>::iterator it = std::upper_bound(
|
||||||
m_facesVertexStartIndices.begin(),
|
m_facesVertexStartIndices.begin(),
|
||||||
m_facesVertexStartIndices.end(),
|
m_facesVertexStartIndices.end(),
|
||||||
in_index
|
in_index);
|
||||||
);
|
|
||||||
|
|
||||||
return static_cast< unsigned int >( std::distance( m_facesVertexStartIndices.begin(), it - 1 ) );
|
return static_cast<unsigned int>(std::distance(m_facesVertexStartIndices.begin(), it - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadLayer(const Scope& layer)
|
void MeshGeometry::ReadLayer(const Scope &layer) {
|
||||||
{
|
const ElementCollection &LayerElement = layer.GetCollection("LayerElement");
|
||||||
const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
|
|
||||||
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
|
for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
|
||||||
const Scope& elayer = GetRequiredScope(*(*eit).second);
|
const Scope &elayer = GetRequiredScope(*(*eit).second);
|
||||||
|
|
||||||
ReadLayerElement(elayer);
|
ReadLayerElement(elayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
|
void MeshGeometry::ReadLayerElement(const Scope &layerElement) {
|
||||||
{
|
const Element &Type = GetRequiredElement(layerElement, "Type");
|
||||||
const Element& Type = GetRequiredElement(layerElement,"Type");
|
const Element &TypedIndex = GetRequiredElement(layerElement, "TypedIndex");
|
||||||
const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
|
|
||||||
|
|
||||||
const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
|
const std::string &type = ParseTokenAsString(GetRequiredToken(Type, 0));
|
||||||
const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
|
const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex, 0));
|
||||||
|
|
||||||
const Scope& top = GetRequiredScope(element);
|
const Scope &top = GetRequiredScope(element);
|
||||||
const ElementCollection candidates = top.GetCollection(type);
|
const ElementCollection candidates = top.GetCollection(type);
|
||||||
|
|
||||||
for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
|
for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
|
||||||
const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
|
const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second, 0));
|
||||||
if(index == typedIndex) {
|
if (index == typedIndex) {
|
||||||
ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
|
ReadVertexData(type, typedIndex, GetRequiredScope(*(*it).second));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
|
FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
|
||||||
<< type << ", index: " << typedIndex);
|
<< type << ", index: " << typedIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
|
void MeshGeometry::ReadVertexData(const std::string &type, int index, const Scope &source) {
|
||||||
{
|
const std::string &MappingInformationType = ParseTokenAsString(GetRequiredToken(
|
||||||
const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(
|
GetRequiredElement(source, "MappingInformationType"), 0));
|
||||||
GetRequiredElement(source,"MappingInformationType"),0)
|
|
||||||
);
|
|
||||||
|
|
||||||
const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
|
const std::string &ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
|
||||||
GetRequiredElement(source,"ReferenceInformationType"),0)
|
GetRequiredElement(source, "ReferenceInformationType"), 0));
|
||||||
);
|
|
||||||
|
|
||||||
if (type == "LayerElementUV") {
|
if (type == "LayerElementUV") {
|
||||||
if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
||||||
FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
|
FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
|
||||||
<< index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
|
<< index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Element* Name = source["Name"];
|
const Element *Name = source["Name"];
|
||||||
m_uvNames[index] = "";
|
m_uvNames[index] = "";
|
||||||
if(Name) {
|
if (Name) {
|
||||||
m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
|
m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadVertexDataUV(m_uvs[index],source,
|
ReadVertexDataUV(m_uvs[index], source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
} else if (type == "LayerElementMaterial") {
|
||||||
}
|
|
||||||
else if (type == "LayerElementMaterial") {
|
|
||||||
if (m_materials.size() > 0) {
|
if (m_materials.size() > 0) {
|
||||||
FBXImporter::LogError("ignoring additional material layer");
|
FBXImporter::LogError("ignoring additional material layer");
|
||||||
return;
|
return;
|
||||||
|
@ -348,10 +333,9 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
||||||
|
|
||||||
std::vector<int> temp_materials;
|
std::vector<int> temp_materials;
|
||||||
|
|
||||||
ReadVertexDataMaterials(temp_materials,source,
|
ReadVertexDataMaterials(temp_materials, source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
|
||||||
|
|
||||||
// sometimes, there will be only negative entries. Drop the material
|
// sometimes, there will be only negative entries. Drop the material
|
||||||
// layer in such a case (I guess it means a default material should
|
// layer in such a case (I guess it means a default material should
|
||||||
|
@ -359,58 +343,50 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
||||||
// avoids losing the material if there are more material layers
|
// avoids losing the material if there are more material layers
|
||||||
// coming of which at least one contains actual data (did observe
|
// coming of which at least one contains actual data (did observe
|
||||||
// that with one test file).
|
// that with one test file).
|
||||||
const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
|
const size_t count_neg = std::count_if(temp_materials.begin(), temp_materials.end(), [](int n) { return n < 0; });
|
||||||
if(count_neg == temp_materials.size()) {
|
if (count_neg == temp_materials.size()) {
|
||||||
FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
|
FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(temp_materials, m_materials);
|
std::swap(temp_materials, m_materials);
|
||||||
}
|
} else if (type == "LayerElementNormal") {
|
||||||
else if (type == "LayerElementNormal") {
|
|
||||||
if (m_normals.size() > 0) {
|
if (m_normals.size() > 0) {
|
||||||
FBXImporter::LogError("ignoring additional normal layer");
|
FBXImporter::LogError("ignoring additional normal layer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadVertexDataNormals(m_normals,source,
|
ReadVertexDataNormals(m_normals, source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
} else if (type == "LayerElementTangent") {
|
||||||
}
|
|
||||||
else if (type == "LayerElementTangent") {
|
|
||||||
if (m_tangents.size() > 0) {
|
if (m_tangents.size() > 0) {
|
||||||
FBXImporter::LogError("ignoring additional tangent layer");
|
FBXImporter::LogError("ignoring additional tangent layer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadVertexDataTangents(m_tangents,source,
|
ReadVertexDataTangents(m_tangents, source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
} else if (type == "LayerElementBinormal") {
|
||||||
}
|
|
||||||
else if (type == "LayerElementBinormal") {
|
|
||||||
if (m_binormals.size() > 0) {
|
if (m_binormals.size() > 0) {
|
||||||
FBXImporter::LogError("ignoring additional binormal layer");
|
FBXImporter::LogError("ignoring additional binormal layer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadVertexDataBinormals(m_binormals,source,
|
ReadVertexDataBinormals(m_binormals, source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
} else if (type == "LayerElementColor") {
|
||||||
}
|
if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
|
||||||
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: ")
|
FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
|
||||||
<< index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" );
|
<< index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadVertexDataColors(m_colors[index],source,
|
ReadVertexDataColors(m_colors[index], source,
|
||||||
MappingInformationType,
|
MappingInformationType,
|
||||||
ReferenceInformationType
|
ReferenceInformationType);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,21 +395,20 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
|
||||||
// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
|
// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
|
||||||
// tangents ..
|
// tangents ..
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
void ResolveVertexDataArray(std::vector<T> &data_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType,
|
const std::string &ReferenceInformationType,
|
||||||
const char* dataElementName,
|
const char *dataElementName,
|
||||||
const char* indexDataElementName,
|
const char *indexDataElementName,
|
||||||
size_t vertex_count,
|
size_t vertex_count,
|
||||||
const std::vector<unsigned int>& mapping_counts,
|
const std::vector<unsigned int> &mapping_counts,
|
||||||
const std::vector<unsigned int>& mapping_offsets,
|
const std::vector<unsigned int> &mapping_offsets,
|
||||||
const std::vector<unsigned int>& mappings)
|
const std::vector<unsigned int> &mappings) {
|
||||||
{
|
|
||||||
bool isDirect = ReferenceInformationType == "Direct";
|
bool isDirect = ReferenceInformationType == "Direct";
|
||||||
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
||||||
|
|
||||||
// fall-back to direct data if there is no index data element
|
// fall-back to direct data if there is no index data element
|
||||||
if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
|
if (isIndexToDirect && !HasElement(source, indexDataElementName)) {
|
||||||
isDirect = true;
|
isDirect = true;
|
||||||
isIndexToDirect = false;
|
isIndexToDirect = false;
|
||||||
}
|
}
|
||||||
|
@ -461,13 +436,12 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
data_out[mappings[j]] = tempData[i];
|
data_out[mappings[j]] = tempData[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||||
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
std::vector<T> tempData;
|
||||||
std::vector<T> tempData;
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
|
||||||
|
|
||||||
std::vector<int> uvIndices;
|
std::vector<int> uvIndices;
|
||||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
ParseVectorDataArray(uvIndices, GetRequiredElement(source, indexDataElementName));
|
||||||
|
|
||||||
if (uvIndices.size() != vertex_count) {
|
if (uvIndices.size() != vertex_count) {
|
||||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ")
|
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ")
|
||||||
|
@ -481,32 +455,29 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
|
|
||||||
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
|
||||||
for (unsigned int j = istart; j < iend; ++j) {
|
for (unsigned int j = istart; j < iend; ++j) {
|
||||||
if (static_cast<size_t>(uvIndices[i]) >= tempData.size()) {
|
if (static_cast<size_t>(uvIndices[i]) >= tempData.size()) {
|
||||||
DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
|
DOMError("index out of range", &GetRequiredElement(source, indexDataElementName));
|
||||||
}
|
}
|
||||||
data_out[mappings[j]] = tempData[uvIndices[i]];
|
data_out[mappings[j]] = tempData[uvIndices[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||||
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
std::vector<T> tempData;
|
||||||
std::vector<T> tempData;
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
|
||||||
|
|
||||||
if (tempData.size() != vertex_count) {
|
if (tempData.size() != vertex_count) {
|
||||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
||||||
<< tempData.size() << ", expected " << vertex_count
|
<< tempData.size() << ", expected " << vertex_count);
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data_out.swap(tempData);
|
data_out.swap(tempData);
|
||||||
}
|
} else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||||
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
std::vector<T> tempData;
|
||||||
std::vector<T> tempData;
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
|
||||||
|
|
||||||
std::vector<int> uvIndices;
|
std::vector<int> uvIndices;
|
||||||
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
|
ParseVectorDataArray(uvIndices, GetRequiredElement(source, indexDataElementName));
|
||||||
|
|
||||||
if (uvIndices.size() != vertex_count) {
|
if (uvIndices.size() != vertex_count) {
|
||||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ")
|
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ")
|
||||||
|
@ -518,120 +489,111 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
|
|
||||||
const T empty;
|
const T empty;
|
||||||
unsigned int next = 0;
|
unsigned int next = 0;
|
||||||
for(int i : uvIndices) {
|
for (int i : uvIndices) {
|
||||||
if ( -1 == i ) {
|
if (-1 == i) {
|
||||||
data_out[ next++ ] = empty;
|
data_out[next++] = empty;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (static_cast<size_t>(i) >= tempData.size()) {
|
if (static_cast<size_t>(i) >= tempData.size()) {
|
||||||
DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
|
DOMError("index out of range", &GetRequiredElement(source, indexDataElementName));
|
||||||
}
|
}
|
||||||
|
|
||||||
data_out[next++] = tempData[i];
|
data_out[next++] = tempData[i];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
|
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
|
||||||
<< MappingInformationType << "," << ReferenceInformationType);
|
<< MappingInformationType << "," << ReferenceInformationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D> &normals_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
ResolveVertexDataArray(normals_out, source, MappingInformationType, ReferenceInformationType,
|
||||||
ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
|
"Normals",
|
||||||
"Normals",
|
"NormalsIndex",
|
||||||
"NormalsIndex",
|
m_vertices.size(),
|
||||||
m_vertices.size(),
|
m_mapping_counts,
|
||||||
m_mapping_counts,
|
m_mapping_offsets,
|
||||||
m_mapping_offsets,
|
m_mappings);
|
||||||
m_mappings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D> &uv_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
ResolveVertexDataArray(uv_out, source, MappingInformationType, ReferenceInformationType,
|
||||||
ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
|
"UV",
|
||||||
"UV",
|
"UVIndex",
|
||||||
"UVIndex",
|
m_vertices.size(),
|
||||||
m_vertices.size(),
|
m_mapping_counts,
|
||||||
m_mapping_counts,
|
m_mapping_offsets,
|
||||||
m_mapping_offsets,
|
m_mappings);
|
||||||
m_mappings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D> &colors_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
ResolveVertexDataArray(colors_out, source, MappingInformationType, ReferenceInformationType,
|
||||||
ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
|
"Colors",
|
||||||
"Colors",
|
"ColorIndex",
|
||||||
"ColorIndex",
|
m_vertices.size(),
|
||||||
m_vertices.size(),
|
m_mapping_counts,
|
||||||
m_mapping_counts,
|
m_mapping_offsets,
|
||||||
m_mapping_offsets,
|
m_mappings);
|
||||||
m_mappings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static const char *TangentIndexToken = "TangentIndex";
|
static const char *TangentIndexToken = "TangentIndex";
|
||||||
static const char *TangentsIndexToken = "TangentsIndex";
|
static const char *TangentsIndexToken = "TangentsIndex";
|
||||||
|
|
||||||
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D> &tangents_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
const char *str = source.Elements().count("Tangents") > 0 ? "Tangents" : "Tangent";
|
||||||
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
|
const char *strIdx = source.Elements().count("Tangents") > 0 ? TangentsIndexToken : TangentIndexToken;
|
||||||
const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken;
|
ResolveVertexDataArray(tangents_out, source, MappingInformationType, ReferenceInformationType,
|
||||||
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
|
str,
|
||||||
str,
|
strIdx,
|
||||||
strIdx,
|
m_vertices.size(),
|
||||||
m_vertices.size(),
|
m_mapping_counts,
|
||||||
m_mapping_counts,
|
m_mapping_offsets,
|
||||||
m_mapping_offsets,
|
m_mappings);
|
||||||
m_mappings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
static const std::string BinormalIndexToken = "BinormalIndex";
|
static const std::string BinormalIndexToken = "BinormalIndex";
|
||||||
static const std::string BinormalsIndexToken = "BinormalsIndex";
|
static const std::string BinormalsIndexToken = "BinormalsIndex";
|
||||||
|
|
||||||
void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D> &binormals_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
const char *str = source.Elements().count("Binormals") > 0 ? "Binormals" : "Binormal";
|
||||||
const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
|
const char *strIdx = source.Elements().count("Binormals") > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
|
||||||
const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
|
ResolveVertexDataArray(binormals_out, source, MappingInformationType, ReferenceInformationType,
|
||||||
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
|
str,
|
||||||
str,
|
strIdx,
|
||||||
strIdx,
|
m_vertices.size(),
|
||||||
m_vertices.size(),
|
m_mapping_counts,
|
||||||
m_mapping_counts,
|
m_mapping_offsets,
|
||||||
m_mapping_offsets,
|
m_mappings);
|
||||||
m_mappings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
|
void MeshGeometry::ReadVertexDataMaterials(std::vector<int> &materials_out, const Scope &source,
|
||||||
const std::string& MappingInformationType,
|
const std::string &MappingInformationType,
|
||||||
const std::string& ReferenceInformationType)
|
const std::string &ReferenceInformationType) {
|
||||||
{
|
|
||||||
const size_t face_count = m_faces.size();
|
const size_t face_count = m_faces.size();
|
||||||
if( 0 == face_count )
|
if (0 == face_count) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// materials are handled separately. First of all, they are assigned per-face
|
// materials are handled separately. First of all, they are assigned per-face
|
||||||
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
|
||||||
// has a slightly different meaning for materials.
|
// has a slightly different meaning for materials.
|
||||||
ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
|
ParseVectorDataArray(materials_out, GetRequiredElement(source, "Materials"));
|
||||||
|
|
||||||
if (MappingInformationType == "AllSame") {
|
if (MappingInformationType == "AllSame") {
|
||||||
// easy - same material for all faces
|
// easy - same material for all faces
|
||||||
|
@ -648,27 +610,26 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
||||||
} else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
|
} else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
|
||||||
materials_out.resize(face_count);
|
materials_out.resize(face_count);
|
||||||
|
|
||||||
if(materials_out.size() != face_count) {
|
if (materials_out.size() != face_count) {
|
||||||
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
|
||||||
<< materials_out.size() << ", expected " << face_count
|
<< materials_out.size() << ", expected " << face_count);
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
|
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
|
||||||
<< MappingInformationType << "," << ReferenceInformationType);
|
<< MappingInformationType << "," << ReferenceInformationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
ShapeGeometry::ShapeGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||||
: Geometry(id, element, name, doc) {
|
Geometry(id, element, name, doc) {
|
||||||
const Scope *sc = element.Compound();
|
const Scope *sc = element.Compound();
|
||||||
if (nullptr == sc) {
|
if (nullptr == sc) {
|
||||||
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
||||||
}
|
}
|
||||||
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
const Element &Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
||||||
const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
|
const Element &Normals = GetRequiredElement(*sc, "Normals", &element);
|
||||||
const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
|
const Element &Vertices = GetRequiredElement(*sc, "Vertices", &element);
|
||||||
ParseVectorDataArray(m_indices, Indexes);
|
ParseVectorDataArray(m_indices, Indexes);
|
||||||
ParseVectorDataArray(m_vertices, Vertices);
|
ParseVectorDataArray(m_vertices, Vertices);
|
||||||
ParseVectorDataArray(m_normals, Normals);
|
ParseVectorDataArray(m_normals, Normals);
|
||||||
|
@ -679,27 +640,26 @@ ShapeGeometry::~ShapeGeometry() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
|
const std::vector<aiVector3D> &ShapeGeometry::GetVertices() const {
|
||||||
return m_vertices;
|
return m_vertices;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
|
const std::vector<aiVector3D> &ShapeGeometry::GetNormals() const {
|
||||||
return m_normals;
|
return m_normals;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
|
const std::vector<unsigned int> &ShapeGeometry::GetIndices() const {
|
||||||
return m_indices;
|
return m_indices;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
LineGeometry::LineGeometry(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
|
||||||
: Geometry(id, element, name, doc)
|
Geometry(id, element, name, doc) {
|
||||||
{
|
const Scope *sc = element.Compound();
|
||||||
const Scope* sc = element.Compound();
|
|
||||||
if (!sc) {
|
if (!sc) {
|
||||||
DOMError("failed to read Geometry object (class: Line), no data scope found");
|
DOMError("failed to read Geometry object (class: Line), no data scope found");
|
||||||
}
|
}
|
||||||
const Element& Points = GetRequiredElement(*sc, "Points", &element);
|
const Element &Points = GetRequiredElement(*sc, "Points", &element);
|
||||||
const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
|
const Element &PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
|
||||||
ParseVectorDataArray(m_vertices, Points);
|
ParseVectorDataArray(m_vertices, Points);
|
||||||
ParseVectorDataArray(m_indices, PointsIndex);
|
ParseVectorDataArray(m_indices, PointsIndex);
|
||||||
}
|
}
|
||||||
|
@ -709,14 +669,13 @@ LineGeometry::~LineGeometry() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
|
const std::vector<aiVector3D> &LineGeometry::GetVertices() const {
|
||||||
return m_vertices;
|
return m_vertices;
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<int>& LineGeometry::GetIndices() const {
|
const std::vector<int> &LineGeometry::GetIndices() const {
|
||||||
return m_indices;
|
return m_indices;
|
||||||
}
|
}
|
||||||
} // !FBX
|
} // namespace FBX
|
||||||
} // !Assimp
|
} // namespace Assimp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -55,20 +55,19 @@ namespace Assimp {
|
||||||
namespace IFC {
|
namespace IFC {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempOpening::Transform(const IfcMatrix4& mat) {
|
void TempOpening::Transform(const IfcMatrix4 &mat) {
|
||||||
if(profileMesh) {
|
if (profileMesh) {
|
||||||
profileMesh->Transform(mat);
|
profileMesh->Transform(mat);
|
||||||
}
|
}
|
||||||
if(profileMesh2D) {
|
if (profileMesh2D) {
|
||||||
profileMesh2D->Transform(mat);
|
profileMesh2D->Transform(mat);
|
||||||
}
|
}
|
||||||
extrusionDir *= IfcMatrix3(mat);
|
extrusionDir *= IfcMatrix3(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiMesh* TempMesh::ToMesh()
|
aiMesh *TempMesh::ToMesh() {
|
||||||
{
|
ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(), mVertcnt.end(), size_t(0)));
|
||||||
ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0)));
|
|
||||||
|
|
||||||
if (mVerts.empty()) {
|
if (mVerts.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -79,14 +78,14 @@ aiMesh* TempMesh::ToMesh()
|
||||||
// copy vertices
|
// copy vertices
|
||||||
mesh->mNumVertices = static_cast<unsigned int>(mVerts.size());
|
mesh->mNumVertices = static_cast<unsigned int>(mVerts.size());
|
||||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||||
std::copy(mVerts.begin(),mVerts.end(),mesh->mVertices);
|
std::copy(mVerts.begin(), mVerts.end(), mesh->mVertices);
|
||||||
|
|
||||||
// and build up faces
|
// and build up faces
|
||||||
mesh->mNumFaces = static_cast<unsigned int>(mVertcnt.size());
|
mesh->mNumFaces = static_cast<unsigned int>(mVertcnt.size());
|
||||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||||
|
|
||||||
for(unsigned int i = 0,n=0, acc = 0; i < mesh->mNumFaces; ++n) {
|
for (unsigned int i = 0, n = 0, acc = 0; i < mesh->mNumFaces; ++n) {
|
||||||
aiFace& f = mesh->mFaces[i];
|
aiFace &f = mesh->mFaces[i];
|
||||||
if (!mVertcnt[n]) {
|
if (!mVertcnt[n]) {
|
||||||
--mesh->mNumFaces;
|
--mesh->mNumFaces;
|
||||||
continue;
|
continue;
|
||||||
|
@ -94,7 +93,7 @@ aiMesh* TempMesh::ToMesh()
|
||||||
|
|
||||||
f.mNumIndices = mVertcnt[n];
|
f.mNumIndices = mVertcnt[n];
|
||||||
f.mIndices = new unsigned int[f.mNumIndices];
|
f.mIndices = new unsigned int[f.mNumIndices];
|
||||||
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
for (unsigned int a = 0; a < f.mNumIndices; ++a) {
|
||||||
f.mIndices[a] = acc++;
|
f.mIndices[a] = acc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,36 +104,31 @@ aiMesh* TempMesh::ToMesh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::Clear()
|
void TempMesh::Clear() {
|
||||||
{
|
|
||||||
mVerts.clear();
|
mVerts.clear();
|
||||||
mVertcnt.clear();
|
mVertcnt.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::Transform(const IfcMatrix4& mat)
|
void TempMesh::Transform(const IfcMatrix4 &mat) {
|
||||||
{
|
for (IfcVector3 &v : mVerts) {
|
||||||
for(IfcVector3& v : mVerts) {
|
|
||||||
v *= mat;
|
v *= mat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
IfcVector3 TempMesh::Center() const
|
IfcVector3 TempMesh::Center() const {
|
||||||
{
|
return (mVerts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(), mVerts.end(), IfcVector3()) / static_cast<IfcFloat>(mVerts.size()));
|
||||||
return (mVerts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(mVerts.begin(),mVerts.end(),IfcVector3()) / static_cast<IfcFloat>(mVerts.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::Append(const TempMesh& other)
|
void TempMesh::Append(const TempMesh &other) {
|
||||||
{
|
mVerts.insert(mVerts.end(), other.mVerts.begin(), other.mVerts.end());
|
||||||
mVerts.insert(mVerts.end(),other.mVerts.begin(),other.mVerts.end());
|
mVertcnt.insert(mVertcnt.end(), other.mVertcnt.begin(), other.mVertcnt.end());
|
||||||
mVertcnt.insert(mVertcnt.end(),other.mVertcnt.begin(),other.mVertcnt.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::RemoveDegenerates()
|
void TempMesh::RemoveDegenerates() {
|
||||||
{
|
|
||||||
// The strategy is simple: walk the mesh and compute normals using
|
// The strategy is simple: walk the mesh and compute normals using
|
||||||
// Newell's algorithm. The length of the normals gives the area
|
// Newell's algorithm. The length of the normals gives the area
|
||||||
// of the polygons, which is close to zero for lines.
|
// of the polygons, which is close to zero for lines.
|
||||||
|
@ -161,52 +155,48 @@ void TempMesh::RemoveDegenerates()
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(drop) {
|
if (drop) {
|
||||||
IFCImporter::LogVerboseDebug("removing degenerate faces");
|
IFCImporter::LogVerboseDebug("removing degenerate faces");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize)
|
IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3 *vtcs, size_t cnt, bool normalize) {
|
||||||
{
|
const size_t Capa = cnt + 2;
|
||||||
std::vector<IfcFloat> temp((cnt+2)*3);
|
std::vector<IfcFloat> temp((Capa)*3);
|
||||||
for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs )
|
for (size_t vofs = 0, i = 0; vofs < cnt; ++vofs) {
|
||||||
{
|
const IfcVector3 &v = vtcs[vofs];
|
||||||
const IfcVector3& v = vtcs[vofs];
|
|
||||||
temp[i++] = v.x;
|
temp[i++] = v.x;
|
||||||
temp[i++] = v.y;
|
temp[i++] = v.y;
|
||||||
temp[i++] = v.z;
|
temp[i++] = v.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcVector3 nor;
|
IfcVector3 nor;
|
||||||
NewellNormal<3, 3, 3>(nor, static_cast<int>(cnt), &temp[0], &temp[1], &temp[2]);
|
NewellNormal<3, 3, 3>(nor, static_cast<int>(cnt), &temp[0], &temp[1], &temp[2], Capa);
|
||||||
return normalize ? nor.Normalize() : nor;
|
return normalize ? nor.Normalize() : nor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
void TempMesh::ComputePolygonNormals(std::vector<IfcVector3> &normals, bool normalize, size_t ofs) const {
|
||||||
bool normalize,
|
|
||||||
size_t ofs) const
|
|
||||||
{
|
|
||||||
size_t max_vcount = 0;
|
size_t max_vcount = 0;
|
||||||
std::vector<unsigned int>::const_iterator begin = mVertcnt.begin()+ofs, end = mVertcnt.end(), iit;
|
std::vector<unsigned int>::const_iterator begin = mVertcnt.begin() + ofs, end = mVertcnt.end(), iit;
|
||||||
for(iit = begin; iit != end; ++iit) {
|
for (iit = begin; iit != end; ++iit) {
|
||||||
max_vcount = std::max(max_vcount,static_cast<size_t>(*iit));
|
max_vcount = std::max(max_vcount, static_cast<size_t>(*iit));
|
||||||
}
|
}
|
||||||
|
const size_t Capa = max_vcount + 2;
|
||||||
std::vector<IfcFloat> temp((max_vcount+2)*4);
|
std::vector<IfcFloat> temp(Capa * 4);
|
||||||
normals.reserve( normals.size() + mVertcnt.size()-ofs );
|
normals.reserve(normals.size() + mVertcnt.size() - ofs);
|
||||||
|
|
||||||
// `NewellNormal()` currently has a relatively strange interface and need to
|
// `NewellNormal()` currently has a relatively strange interface and need to
|
||||||
// re-structure things a bit to meet them.
|
// re-structure things a bit to meet them.
|
||||||
size_t vidx = std::accumulate(mVertcnt.begin(),begin,0);
|
size_t vidx = std::accumulate(mVertcnt.begin(), begin, 0);
|
||||||
for(iit = begin; iit != end; vidx += *iit++) {
|
for (iit = begin; iit != end; vidx += *iit++) {
|
||||||
if (!*iit) {
|
if (!*iit) {
|
||||||
normals.push_back(IfcVector3());
|
normals.push_back(IfcVector3());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
|
for (size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
|
||||||
const IfcVector3& v = mVerts[vidx+vofs];
|
const IfcVector3 &v = mVerts[vidx + vofs];
|
||||||
temp[cnt++] = v.x;
|
temp[cnt++] = v.x;
|
||||||
temp[cnt++] = v.y;
|
temp[cnt++] = v.y;
|
||||||
temp[cnt++] = v.z;
|
temp[cnt++] = v.z;
|
||||||
|
@ -217,11 +207,11 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||||
}
|
}
|
||||||
|
|
||||||
normals.push_back(IfcVector3());
|
normals.push_back(IfcVector3());
|
||||||
NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
|
NewellNormal<4, 4, 4>(normals.back(), *iit, &temp[0], &temp[1], &temp[2], Capa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(normalize) {
|
if (normalize) {
|
||||||
for(IfcVector3& n : normals) {
|
for (IfcVector3 &n : normals) {
|
||||||
n.Normalize();
|
n.Normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,62 +219,55 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Compute the normal of the last polygon in the given mesh
|
// Compute the normal of the last polygon in the given mesh
|
||||||
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
|
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
|
||||||
{
|
|
||||||
return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize);
|
return ComputePolygonNormal(&mVerts[mVerts.size() - mVertcnt.back()], mVertcnt.back(), normalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompareVector
|
struct CompareVector {
|
||||||
{
|
bool operator()(const IfcVector3 &a, const IfcVector3 &b) const {
|
||||||
bool operator () (const IfcVector3& a, const IfcVector3& b) const
|
|
||||||
{
|
|
||||||
IfcVector3 d = a - b;
|
IfcVector3 d = a - b;
|
||||||
IfcFloat eps = 1e-6;
|
IfcFloat eps = 1e-6;
|
||||||
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
|
return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct FindVector
|
struct FindVector {
|
||||||
{
|
|
||||||
IfcVector3 v;
|
IfcVector3 v;
|
||||||
FindVector(const IfcVector3& p) : v(p) { }
|
FindVector(const IfcVector3 &p) :
|
||||||
bool operator () (const IfcVector3& p) { return FuzzyVectorCompare(1e-6)(p, v); }
|
v(p) {}
|
||||||
|
bool operator()(const IfcVector3 &p) { return FuzzyVectorCompare(1e-6)(p, v); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::FixupFaceOrientation()
|
void TempMesh::FixupFaceOrientation() {
|
||||||
{
|
|
||||||
const IfcVector3 vavg = Center();
|
const IfcVector3 vavg = Center();
|
||||||
|
|
||||||
// create a list of start indices for all faces to allow random access to faces
|
// create a list of start indices for all faces to allow random access to faces
|
||||||
std::vector<size_t> faceStartIndices(mVertcnt.size());
|
std::vector<size_t> faceStartIndices(mVertcnt.size());
|
||||||
for( size_t i = 0, a = 0; a < mVertcnt.size(); i += mVertcnt[a], ++a )
|
for (size_t i = 0, a = 0; a < mVertcnt.size(); i += mVertcnt[a], ++a)
|
||||||
faceStartIndices[a] = i;
|
faceStartIndices[a] = i;
|
||||||
|
|
||||||
// list all faces on a vertex
|
// list all faces on a vertex
|
||||||
std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
|
std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
|
||||||
for( size_t a = 0; a < mVertcnt.size(); ++a )
|
for (size_t a = 0; a < mVertcnt.size(); ++a) {
|
||||||
{
|
for (size_t b = 0; b < mVertcnt[a]; ++b)
|
||||||
for( size_t b = 0; b < mVertcnt[a]; ++b )
|
|
||||||
facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a);
|
facesByVertex[mVerts[faceStartIndices[a] + b]].push_back(a);
|
||||||
}
|
}
|
||||||
// determine neighbourhood for all polys
|
// determine neighbourhood for all polys
|
||||||
std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX);
|
std::vector<size_t> neighbour(mVerts.size(), SIZE_MAX);
|
||||||
std::vector<size_t> tempIntersect(10);
|
std::vector<size_t> tempIntersect(10);
|
||||||
for( size_t a = 0; a < mVertcnt.size(); ++a )
|
for (size_t a = 0; a < mVertcnt.size(); ++a) {
|
||||||
{
|
for (size_t b = 0; b < mVertcnt[a]; ++b) {
|
||||||
for( size_t b = 0; b < mVertcnt[a]; ++b )
|
|
||||||
{
|
|
||||||
size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a];
|
size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % mVertcnt[a];
|
||||||
const std::vector<size_t>& facesOnB = facesByVertex[mVerts[ib]];
|
const std::vector<size_t> &facesOnB = facesByVertex[mVerts[ib]];
|
||||||
const std::vector<size_t>& facesOnNB = facesByVertex[mVerts[nib]];
|
const std::vector<size_t> &facesOnNB = facesByVertex[mVerts[nib]];
|
||||||
// there should be exactly one or two faces which appear in both lists. Our face and the other side
|
// there should be exactly one or two faces which appear in both lists. Our face and the other side
|
||||||
std::vector<size_t>::iterator sectstart = tempIntersect.begin();
|
std::vector<size_t>::iterator sectstart = tempIntersect.begin();
|
||||||
std::vector<size_t>::iterator sectend = std::set_intersection(
|
std::vector<size_t>::iterator sectend = std::set_intersection(
|
||||||
facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart);
|
facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart);
|
||||||
|
|
||||||
if( std::distance(sectstart, sectend) != 2 )
|
if (std::distance(sectstart, sectend) != 2)
|
||||||
continue;
|
continue;
|
||||||
if( *sectstart == a )
|
if (*sectstart == a)
|
||||||
++sectstart;
|
++sectstart;
|
||||||
neighbour[ib] = *sectstart;
|
neighbour[ib] = *sectstart;
|
||||||
}
|
}
|
||||||
|
@ -294,30 +277,31 @@ void TempMesh::FixupFaceOrientation()
|
||||||
// facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
|
// facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
|
||||||
// faces to have the same winding until all faces have been tested.
|
// faces to have the same winding until all faces have been tested.
|
||||||
std::vector<bool> faceDone(mVertcnt.size(), false);
|
std::vector<bool> faceDone(mVertcnt.size(), false);
|
||||||
while( std::count(faceDone.begin(), faceDone.end(), false) != 0 )
|
while (std::count(faceDone.begin(), faceDone.end(), false) != 0) {
|
||||||
{
|
|
||||||
// find the farthest of the remaining faces
|
// find the farthest of the remaining faces
|
||||||
size_t farthestIndex = SIZE_MAX;
|
size_t farthestIndex = SIZE_MAX;
|
||||||
IfcFloat farthestDistance = -1.0;
|
IfcFloat farthestDistance = -1.0;
|
||||||
for( size_t a = 0; a < mVertcnt.size(); ++a )
|
for (size_t a = 0; a < mVertcnt.size(); ++a) {
|
||||||
{
|
if (faceDone[a])
|
||||||
if( faceDone[a] )
|
|
||||||
continue;
|
continue;
|
||||||
IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a],
|
IfcVector3 faceCenter = std::accumulate(mVerts.begin() + faceStartIndices[a],
|
||||||
mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) / IfcFloat(mVertcnt[a]);
|
mVerts.begin() + faceStartIndices[a] + mVertcnt[a], IfcVector3(0.0)) /
|
||||||
|
IfcFloat(mVertcnt[a]);
|
||||||
IfcFloat dst = (faceCenter - vavg).SquareLength();
|
IfcFloat dst = (faceCenter - vavg).SquareLength();
|
||||||
if( dst > farthestDistance ) { farthestDistance = dst; farthestIndex = a; }
|
if (dst > farthestDistance) {
|
||||||
|
farthestDistance = dst;
|
||||||
|
farthestIndex = a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate its normal and reverse the poly if its facing towards the mesh center
|
// calculate its normal and reverse the poly if its facing towards the mesh center
|
||||||
IfcVector3 farthestNormal = ComputePolygonNormal(mVerts.data() + faceStartIndices[farthestIndex], mVertcnt[farthestIndex]);
|
IfcVector3 farthestNormal = ComputePolygonNormal(mVerts.data() + faceStartIndices[farthestIndex], mVertcnt[farthestIndex]);
|
||||||
IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
|
IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
|
||||||
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0))
|
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0)) /
|
||||||
/ IfcFloat(mVertcnt[farthestIndex]);
|
IfcFloat(mVertcnt[farthestIndex]);
|
||||||
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
|
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
|
||||||
// the file.
|
// the file.
|
||||||
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
|
if ((farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4) {
|
||||||
{
|
|
||||||
size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex];
|
size_t fsi = faceStartIndices[farthestIndex], fvc = mVertcnt[farthestIndex];
|
||||||
std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc);
|
std::reverse(mVerts.begin() + fsi, mVerts.begin() + fsi + fvc);
|
||||||
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
|
std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
|
||||||
|
@ -326,7 +310,7 @@ void TempMesh::FixupFaceOrientation()
|
||||||
// Before: points A - B - C - D with edge neighbour p - q - r - s
|
// Before: points A - B - C - D with edge neighbour p - q - r - s
|
||||||
// After: points D - C - B - A, reversed neighbours are s - r - q - p, but the should be
|
// After: points D - C - B - A, reversed neighbours are s - r - q - p, but the should be
|
||||||
// r q p s
|
// r q p s
|
||||||
for( size_t a = 0; a < fvc - 1; ++a )
|
for (size_t a = 0; a < fvc - 1; ++a)
|
||||||
std::swap(neighbour[fsi + a], neighbour[fsi + a + 1]);
|
std::swap(neighbour[fsi + a], neighbour[fsi + a + 1]);
|
||||||
}
|
}
|
||||||
faceDone[farthestIndex] = true;
|
faceDone[farthestIndex] = true;
|
||||||
|
@ -334,21 +318,19 @@ void TempMesh::FixupFaceOrientation()
|
||||||
todo.push_back(farthestIndex);
|
todo.push_back(farthestIndex);
|
||||||
|
|
||||||
// go over its neighbour faces recursively and adapt their winding order to match the farthest face
|
// go over its neighbour faces recursively and adapt their winding order to match the farthest face
|
||||||
while( !todo.empty() )
|
while (!todo.empty()) {
|
||||||
{
|
|
||||||
size_t tdf = todo.back();
|
size_t tdf = todo.back();
|
||||||
size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf];
|
size_t vsi = faceStartIndices[tdf], vc = mVertcnt[tdf];
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
|
|
||||||
// check its neighbours
|
// check its neighbours
|
||||||
for( size_t a = 0; a < vc; ++a )
|
for (size_t a = 0; a < vc; ++a) {
|
||||||
{
|
|
||||||
// ignore neighbours if we already checked them
|
// ignore neighbours if we already checked them
|
||||||
size_t nbi = neighbour[vsi + a];
|
size_t nbi = neighbour[vsi + a];
|
||||||
if( nbi == SIZE_MAX || faceDone[nbi] )
|
if (nbi == SIZE_MAX || faceDone[nbi])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const IfcVector3& vp = mVerts[vsi + a];
|
const IfcVector3 &vp = mVerts[vsi + a];
|
||||||
size_t nbvsi = faceStartIndices[nbi], nbvc = mVertcnt[nbi];
|
size_t nbvsi = faceStartIndices[nbi], nbvc = mVertcnt[nbi];
|
||||||
std::vector<IfcVector3>::iterator it = std::find_if(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc, FindVector(vp));
|
std::vector<IfcVector3>::iterator it = std::find_if(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc, FindVector(vp));
|
||||||
ai_assert(it != mVerts.begin() + nbvsi + nbvc);
|
ai_assert(it != mVerts.begin() + nbvsi + nbvc);
|
||||||
|
@ -358,8 +340,7 @@ void TempMesh::FixupFaceOrientation()
|
||||||
// to reverse the neighbour
|
// to reverse the neighbour
|
||||||
nb_vidx = (nb_vidx + 1) % nbvc;
|
nb_vidx = (nb_vidx + 1) % nbvc;
|
||||||
size_t oursideidx = (a + 1) % vc;
|
size_t oursideidx = (a + 1) % vc;
|
||||||
if( FuzzyVectorCompare(1e-6)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx]) )
|
if (FuzzyVectorCompare(1e-6)(mVerts[vsi + oursideidx], mVerts[nbvsi + nb_vidx])) {
|
||||||
{
|
|
||||||
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
|
std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc);
|
||||||
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
|
std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
|
||||||
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
|
for (size_t aa = 0; aa < nbvc - 1; ++aa) {
|
||||||
|
@ -381,17 +362,16 @@ void TempMesh::FixupFaceOrientation()
|
||||||
void TempMesh::RemoveAdjacentDuplicates() {
|
void TempMesh::RemoveAdjacentDuplicates() {
|
||||||
bool drop = false;
|
bool drop = false;
|
||||||
std::vector<IfcVector3>::iterator base = mVerts.begin();
|
std::vector<IfcVector3>::iterator base = mVerts.begin();
|
||||||
for(unsigned int& cnt : mVertcnt) {
|
for (unsigned int &cnt : mVertcnt) {
|
||||||
if (cnt < 2){
|
if (cnt < 2) {
|
||||||
base += cnt;
|
base += cnt;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcVector3 vmin,vmax;
|
IfcVector3 vmin, vmax;
|
||||||
ArrayBounds(&*base, cnt ,vmin,vmax);
|
ArrayBounds(&*base, cnt, vmin, vmax);
|
||||||
|
|
||||||
|
const IfcFloat epsilon = (vmax - vmin).SquareLength() / static_cast<IfcFloat>(1e9);
|
||||||
const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
|
|
||||||
//const IfcFloat dotepsilon = 1e-9;
|
//const IfcFloat dotepsilon = 1e-9;
|
||||||
|
|
||||||
//// look for vertices that lie directly on the line between their predecessor and their
|
//// look for vertices that lie directly on the line between their predecessor and their
|
||||||
|
@ -419,153 +399,127 @@ void TempMesh::RemoveAdjacentDuplicates() {
|
||||||
// drop any identical, adjacent vertices. this pass will collect the dropouts
|
// drop any identical, adjacent vertices. this pass will collect the dropouts
|
||||||
// of the previous pass as a side-effect.
|
// of the previous pass as a side-effect.
|
||||||
FuzzyVectorCompare fz(epsilon);
|
FuzzyVectorCompare fz(epsilon);
|
||||||
std::vector<IfcVector3>::iterator end = base+cnt, e = std::unique( base, end, fz );
|
std::vector<IfcVector3>::iterator end = base + cnt, e = std::unique(base, end, fz);
|
||||||
if (e != end) {
|
if (e != end) {
|
||||||
cnt -= static_cast<unsigned int>(std::distance(e, end));
|
cnt -= static_cast<unsigned int>(std::distance(e, end));
|
||||||
mVerts.erase(e,end);
|
mVerts.erase(e, end);
|
||||||
drop = true;
|
drop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check front and back vertices for this polygon
|
// check front and back vertices for this polygon
|
||||||
if (cnt > 1 && fz(*base,*(base+cnt-1))) {
|
if (cnt > 1 && fz(*base, *(base + cnt - 1))) {
|
||||||
mVerts.erase(base+ --cnt);
|
mVerts.erase(base + --cnt);
|
||||||
drop = true;
|
drop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// removing adjacent duplicates shouldn't erase everything :-)
|
// removing adjacent duplicates shouldn't erase everything :-)
|
||||||
ai_assert(cnt>0);
|
ai_assert(cnt > 0);
|
||||||
base += cnt;
|
base += cnt;
|
||||||
}
|
}
|
||||||
if(drop) {
|
if (drop) {
|
||||||
IFCImporter::LogVerboseDebug("removing duplicate vertices");
|
IFCImporter::LogVerboseDebug("removing duplicate vertices");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void TempMesh::Swap(TempMesh& other)
|
void TempMesh::Swap(TempMesh &other) {
|
||||||
{
|
|
||||||
mVertcnt.swap(other.mVertcnt);
|
mVertcnt.swap(other.mVertcnt);
|
||||||
mVerts.swap(other.mVerts);
|
mVerts.swap(other.mVerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN& in)
|
bool IsTrue(const ::Assimp::STEP::EXPRESS::BOOLEAN &in) {
|
||||||
{
|
|
||||||
return (std::string)in == "TRUE" || (std::string)in == "T";
|
return (std::string)in == "TRUE" || (std::string)in == "T";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
IfcFloat ConvertSIPrefix(const std::string& prefix)
|
IfcFloat ConvertSIPrefix(const std::string &prefix) {
|
||||||
{
|
|
||||||
if (prefix == "EXA") {
|
if (prefix == "EXA") {
|
||||||
return 1e18f;
|
return 1e18f;
|
||||||
}
|
} else if (prefix == "PETA") {
|
||||||
else if (prefix == "PETA") {
|
|
||||||
return 1e15f;
|
return 1e15f;
|
||||||
}
|
} else if (prefix == "TERA") {
|
||||||
else if (prefix == "TERA") {
|
|
||||||
return 1e12f;
|
return 1e12f;
|
||||||
}
|
} else if (prefix == "GIGA") {
|
||||||
else if (prefix == "GIGA") {
|
|
||||||
return 1e9f;
|
return 1e9f;
|
||||||
}
|
} else if (prefix == "MEGA") {
|
||||||
else if (prefix == "MEGA") {
|
|
||||||
return 1e6f;
|
return 1e6f;
|
||||||
}
|
} else if (prefix == "KILO") {
|
||||||
else if (prefix == "KILO") {
|
|
||||||
return 1e3f;
|
return 1e3f;
|
||||||
}
|
} else if (prefix == "HECTO") {
|
||||||
else if (prefix == "HECTO") {
|
|
||||||
return 1e2f;
|
return 1e2f;
|
||||||
}
|
} else if (prefix == "DECA") {
|
||||||
else if (prefix == "DECA") {
|
|
||||||
return 1e-0f;
|
return 1e-0f;
|
||||||
}
|
} else if (prefix == "DECI") {
|
||||||
else if (prefix == "DECI") {
|
|
||||||
return 1e-1f;
|
return 1e-1f;
|
||||||
}
|
} else if (prefix == "CENTI") {
|
||||||
else if (prefix == "CENTI") {
|
|
||||||
return 1e-2f;
|
return 1e-2f;
|
||||||
}
|
} else if (prefix == "MILLI") {
|
||||||
else if (prefix == "MILLI") {
|
|
||||||
return 1e-3f;
|
return 1e-3f;
|
||||||
}
|
} else if (prefix == "MICRO") {
|
||||||
else if (prefix == "MICRO") {
|
|
||||||
return 1e-6f;
|
return 1e-6f;
|
||||||
}
|
} else if (prefix == "NANO") {
|
||||||
else if (prefix == "NANO") {
|
|
||||||
return 1e-9f;
|
return 1e-9f;
|
||||||
}
|
} else if (prefix == "PICO") {
|
||||||
else if (prefix == "PICO") {
|
|
||||||
return 1e-12f;
|
return 1e-12f;
|
||||||
}
|
} else if (prefix == "FEMTO") {
|
||||||
else if (prefix == "FEMTO") {
|
|
||||||
return 1e-15f;
|
return 1e-15f;
|
||||||
}
|
} else if (prefix == "ATTO") {
|
||||||
else if (prefix == "ATTO") {
|
|
||||||
return 1e-18f;
|
return 1e-18f;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
|
IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourRgb& in)
|
void ConvertColor(aiColor4D &out, const Schema_2x3::IfcColourRgb &in) {
|
||||||
{
|
out.r = static_cast<float>(in.Red);
|
||||||
out.r = static_cast<float>( in.Red );
|
out.g = static_cast<float>(in.Green);
|
||||||
out.g = static_cast<float>( in.Green );
|
out.b = static_cast<float>(in.Blue);
|
||||||
out.b = static_cast<float>( in.Blue );
|
out.a = static_cast<float>(1.f);
|
||||||
out.a = static_cast<float>( 1.f );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertColor(aiColor4D& out, const Schema_2x3::IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base)
|
void ConvertColor(aiColor4D &out, const Schema_2x3::IfcColourOrFactor &in, ConversionData &conv, const aiColor4D *base) {
|
||||||
{
|
if (const ::Assimp::STEP::EXPRESS::REAL *const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
||||||
if (const ::Assimp::STEP::EXPRESS::REAL* const r = in.ToPtr<::Assimp::STEP::EXPRESS::REAL>()) {
|
|
||||||
out.r = out.g = out.b = static_cast<float>(*r);
|
out.r = out.g = out.b = static_cast<float>(*r);
|
||||||
if(base) {
|
if (base) {
|
||||||
out.r *= static_cast<float>( base->r );
|
out.r *= static_cast<float>(base->r);
|
||||||
out.g *= static_cast<float>( base->g );
|
out.g *= static_cast<float>(base->g);
|
||||||
out.b *= static_cast<float>( base->b );
|
out.b *= static_cast<float>(base->b);
|
||||||
out.a = static_cast<float>( base->a );
|
out.a = static_cast<float>(base->a);
|
||||||
}
|
} else
|
||||||
else out.a = 1.0;
|
out.a = 1.0;
|
||||||
}
|
} else if (const Schema_2x3::IfcColourRgb *const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
|
||||||
else if (const Schema_2x3::IfcColourRgb* const rgb = in.ResolveSelectPtr<Schema_2x3::IfcColourRgb>(conv.db)) {
|
ConvertColor(out, *rgb);
|
||||||
ConvertColor(out,*rgb);
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
|
IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertCartesianPoint(IfcVector3& out, const Schema_2x3::IfcCartesianPoint& in)
|
void ConvertCartesianPoint(IfcVector3 &out, const Schema_2x3::IfcCartesianPoint &in) {
|
||||||
{
|
|
||||||
out = IfcVector3();
|
out = IfcVector3();
|
||||||
for(size_t i = 0; i < in.Coordinates.size(); ++i) {
|
for (size_t i = 0; i < in.Coordinates.size(); ++i) {
|
||||||
out[static_cast<unsigned int>(i)] = in.Coordinates[i];
|
out[static_cast<unsigned int>(i)] = in.Coordinates[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertVector(IfcVector3& out, const Schema_2x3::IfcVector& in)
|
void ConvertVector(IfcVector3 &out, const Schema_2x3::IfcVector &in) {
|
||||||
{
|
ConvertDirection(out, in.Orientation);
|
||||||
ConvertDirection(out,in.Orientation);
|
|
||||||
out *= in.Magnitude;
|
out *= in.Magnitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
|
void ConvertDirection(IfcVector3 &out, const Schema_2x3::IfcDirection &in) {
|
||||||
{
|
|
||||||
out = IfcVector3();
|
out = IfcVector3();
|
||||||
for(size_t i = 0; i < in.DirectionRatios.size(); ++i) {
|
for (size_t i = 0; i < in.DirectionRatios.size(); ++i) {
|
||||||
out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
|
out[static_cast<unsigned int>(i)] = in.DirectionRatios[i];
|
||||||
}
|
}
|
||||||
const IfcFloat len = out.Length();
|
const IfcFloat len = out.Length();
|
||||||
if (len<1e-6) {
|
if (len < 1e-6) {
|
||||||
IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
|
IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -573,8 +527,7 @@ void ConvertDirection(IfcVector3& out, const Schema_2x3::IfcDirection& in)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z)
|
void AssignMatrixAxes(IfcMatrix4 &out, const IfcVector3 &x, const IfcVector3 &y, const IfcVector3 &z) {
|
||||||
{
|
|
||||||
out.a1 = x.x;
|
out.a1 = x.x;
|
||||||
out.b1 = x.y;
|
out.b1 = x.y;
|
||||||
out.c1 = x.z;
|
out.c1 = x.z;
|
||||||
|
@ -589,116 +542,105 @@ void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement3D& in)
|
void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement3D &in) {
|
||||||
{
|
|
||||||
IfcVector3 loc;
|
IfcVector3 loc;
|
||||||
ConvertCartesianPoint(loc,in.Location);
|
ConvertCartesianPoint(loc, in.Location);
|
||||||
|
|
||||||
IfcVector3 z(0.f,0.f,1.f),r(1.f,0.f,0.f),x;
|
IfcVector3 z(0.f, 0.f, 1.f), r(1.f, 0.f, 0.f), x;
|
||||||
|
|
||||||
if (in.Axis) {
|
if (in.Axis) {
|
||||||
ConvertDirection(z,*in.Axis.Get());
|
ConvertDirection(z, *in.Axis.Get());
|
||||||
}
|
}
|
||||||
if (in.RefDirection) {
|
if (in.RefDirection) {
|
||||||
ConvertDirection(r,*in.RefDirection.Get());
|
ConvertDirection(r, *in.RefDirection.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcVector3 v = r.Normalize();
|
IfcVector3 v = r.Normalize();
|
||||||
IfcVector3 tmpx = z * (v*z);
|
IfcVector3 tmpx = z * (v * z);
|
||||||
|
|
||||||
x = (v-tmpx).Normalize();
|
x = (v - tmpx).Normalize();
|
||||||
IfcVector3 y = (z^x);
|
IfcVector3 y = (z ^ x);
|
||||||
|
|
||||||
IfcMatrix4::Translation(loc,out);
|
IfcMatrix4::Translation(loc, out);
|
||||||
AssignMatrixAxes(out,x,y,z);
|
AssignMatrixAxes(out, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement2D& in)
|
void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement2D &in) {
|
||||||
{
|
|
||||||
IfcVector3 loc;
|
IfcVector3 loc;
|
||||||
ConvertCartesianPoint(loc,in.Location);
|
ConvertCartesianPoint(loc, in.Location);
|
||||||
|
|
||||||
IfcVector3 x(1.f,0.f,0.f);
|
IfcVector3 x(1.f, 0.f, 0.f);
|
||||||
if (in.RefDirection) {
|
if (in.RefDirection) {
|
||||||
ConvertDirection(x,*in.RefDirection.Get());
|
ConvertDirection(x, *in.RefDirection.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
const IfcVector3 y = IfcVector3(x.y,-x.x,0.f);
|
const IfcVector3 y = IfcVector3(x.y, -x.x, 0.f);
|
||||||
|
|
||||||
IfcMatrix4::Translation(loc,out);
|
IfcMatrix4::Translation(loc, out);
|
||||||
AssignMatrixAxes(out,x,y,IfcVector3(0.f,0.f,1.f));
|
AssignMatrixAxes(out, x, y, IfcVector3(0.f, 0.f, 1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const Schema_2x3::IfcAxis1Placement& in)
|
void ConvertAxisPlacement(IfcVector3 &axis, IfcVector3 &pos, const Schema_2x3::IfcAxis1Placement &in) {
|
||||||
{
|
ConvertCartesianPoint(pos, in.Location);
|
||||||
ConvertCartesianPoint(pos,in.Location);
|
|
||||||
if (in.Axis) {
|
if (in.Axis) {
|
||||||
ConvertDirection(axis,in.Axis.Get());
|
ConvertDirection(axis, in.Axis.Get());
|
||||||
}
|
} else {
|
||||||
else {
|
axis = IfcVector3(0.f, 0.f, 1.f);
|
||||||
axis = IfcVector3(0.f,0.f,1.f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAxisPlacement(IfcMatrix4& out, const Schema_2x3::IfcAxis2Placement& in, ConversionData& conv)
|
void ConvertAxisPlacement(IfcMatrix4 &out, const Schema_2x3::IfcAxis2Placement &in, ConversionData &conv) {
|
||||||
{
|
if (const Schema_2x3::IfcAxis2Placement3D *pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) {
|
||||||
if(const Schema_2x3::IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement3D>(conv.db)) {
|
ConvertAxisPlacement(out, *pl3);
|
||||||
ConvertAxisPlacement(out,*pl3);
|
} else if (const Schema_2x3::IfcAxis2Placement2D *pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
|
||||||
}
|
ConvertAxisPlacement(out, *pl2);
|
||||||
else if(const Schema_2x3::IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<Schema_2x3::IfcAxis2Placement2D>(conv.db)) {
|
} else {
|
||||||
ConvertAxisPlacement(out,*pl2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
|
IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertTransformOperator(IfcMatrix4& out, const Schema_2x3::IfcCartesianTransformationOperator& op)
|
void ConvertTransformOperator(IfcMatrix4 &out, const Schema_2x3::IfcCartesianTransformationOperator &op) {
|
||||||
{
|
|
||||||
IfcVector3 loc;
|
IfcVector3 loc;
|
||||||
ConvertCartesianPoint(loc,op.LocalOrigin);
|
ConvertCartesianPoint(loc, op.LocalOrigin);
|
||||||
|
|
||||||
IfcVector3 x(1.f,0.f,0.f),y(0.f,1.f,0.f),z(0.f,0.f,1.f);
|
IfcVector3 x(1.f, 0.f, 0.f), y(0.f, 1.f, 0.f), z(0.f, 0.f, 1.f);
|
||||||
if (op.Axis1) {
|
if (op.Axis1) {
|
||||||
ConvertDirection(x,*op.Axis1.Get());
|
ConvertDirection(x, *op.Axis1.Get());
|
||||||
}
|
}
|
||||||
if (op.Axis2) {
|
if (op.Axis2) {
|
||||||
ConvertDirection(y,*op.Axis2.Get());
|
ConvertDirection(y, *op.Axis2.Get());
|
||||||
}
|
}
|
||||||
if (const Schema_2x3::IfcCartesianTransformationOperator3D* op2 = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3D>()) {
|
if (const Schema_2x3::IfcCartesianTransformationOperator3D *op2 = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3D>()) {
|
||||||
if(op2->Axis3) {
|
if (op2->Axis3) {
|
||||||
ConvertDirection(z,*op2->Axis3.Get());
|
ConvertDirection(z, *op2->Axis3.Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcMatrix4 locm;
|
IfcMatrix4 locm;
|
||||||
IfcMatrix4::Translation(loc,locm);
|
IfcMatrix4::Translation(loc, locm);
|
||||||
AssignMatrixAxes(out,x,y,z);
|
AssignMatrixAxes(out, x, y, z);
|
||||||
|
|
||||||
|
|
||||||
IfcVector3 vscale;
|
IfcVector3 vscale;
|
||||||
if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) {
|
if (const Schema_2x3::IfcCartesianTransformationOperator3DnonUniform *nuni = op.ToPtr<Schema_2x3::IfcCartesianTransformationOperator3DnonUniform>()) {
|
||||||
vscale.x = nuni->Scale?op.Scale.Get():1.f;
|
vscale.x = nuni->Scale ? op.Scale.Get() : 1.f;
|
||||||
vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f;
|
vscale.y = nuni->Scale2 ? nuni->Scale2.Get() : 1.f;
|
||||||
vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f;
|
vscale.z = nuni->Scale3 ? nuni->Scale3.Get() : 1.f;
|
||||||
}
|
} else {
|
||||||
else {
|
const IfcFloat sc = op.Scale ? op.Scale.Get() : 1.f;
|
||||||
const IfcFloat sc = op.Scale?op.Scale.Get():1.f;
|
vscale = IfcVector3(sc, sc, sc);
|
||||||
vscale = IfcVector3(sc,sc,sc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcMatrix4 s;
|
IfcMatrix4 s;
|
||||||
IfcMatrix4::Scaling(vscale,s);
|
IfcMatrix4::Scaling(vscale, s);
|
||||||
|
|
||||||
out = locm * out * s;
|
out = locm * out * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace IFC
|
||||||
} // ! IFC
|
} // namespace Assimp
|
||||||
} // ! Assimp
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,20 +44,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef INCLUDED_AI_IMPORTER_H
|
#ifndef INCLUDED_AI_IMPORTER_H
|
||||||
#define INCLUDED_AI_IMPORTER_H
|
#define INCLUDED_AI_IMPORTER_H
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <assimp/matrix4x4.h>
|
#include <assimp/matrix4x4.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct aiScene;
|
struct aiScene;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
class ProgressHandler;
|
class ProgressHandler;
|
||||||
class IOSystem;
|
class IOSystem;
|
||||||
class BaseImporter;
|
class BaseImporter;
|
||||||
class BaseProcess;
|
class BaseProcess;
|
||||||
class SharedPostProcessInfo;
|
class SharedPostProcessInfo;
|
||||||
|
|
||||||
|
|
||||||
//! @cond never
|
//! @cond never
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -70,7 +69,7 @@ namespace Assimp {
|
||||||
class ImporterPimpl {
|
class ImporterPimpl {
|
||||||
public:
|
public:
|
||||||
// Data type to store the key hash
|
// Data type to store the key hash
|
||||||
typedef unsigned int KeyType;
|
using KeyType = unsigned int;
|
||||||
|
|
||||||
// typedefs for our four configuration maps.
|
// typedefs for our four configuration maps.
|
||||||
// We don't need more, so there is no need for a generic solution
|
// We don't need more, so there is no need for a generic solution
|
||||||
|
@ -80,21 +79,21 @@ public:
|
||||||
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
|
typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
|
||||||
|
|
||||||
/** IO handler to use for all file accesses. */
|
/** IO handler to use for all file accesses. */
|
||||||
IOSystem* mIOHandler;
|
IOSystem *mIOHandler;
|
||||||
bool mIsDefaultHandler;
|
bool mIsDefaultHandler;
|
||||||
|
|
||||||
/** Progress handler for feedback. */
|
/** Progress handler for feedback. */
|
||||||
ProgressHandler* mProgressHandler;
|
ProgressHandler *mProgressHandler;
|
||||||
bool mIsDefaultProgressHandler;
|
bool mIsDefaultProgressHandler;
|
||||||
|
|
||||||
/** Format-specific importer worker objects - one for each format we can read.*/
|
/** Format-specific importer worker objects - one for each format we can read.*/
|
||||||
std::vector< BaseImporter* > mImporter;
|
std::vector<BaseImporter *> mImporter;
|
||||||
|
|
||||||
/** Post processing steps we can apply at the imported data. */
|
/** Post processing steps we can apply at the imported data. */
|
||||||
std::vector< BaseProcess* > mPostProcessingSteps;
|
std::vector<BaseProcess *> mPostProcessingSteps;
|
||||||
|
|
||||||
/** The imported data, if ReadFile() was successful, nullptr otherwise. */
|
/** The imported data, if ReadFile() was successful, nullptr otherwise. */
|
||||||
aiScene* mScene;
|
aiScene *mScene;
|
||||||
|
|
||||||
/** The error description, if there was one. In the case of an exception,
|
/** The error description, if there was one. In the case of an exception,
|
||||||
* mException will carry the full details. */
|
* mException will carry the full details. */
|
||||||
|
@ -120,29 +119,27 @@ public:
|
||||||
bool bExtraVerbose;
|
bool bExtraVerbose;
|
||||||
|
|
||||||
/** Used by post-process steps to share data */
|
/** Used by post-process steps to share data */
|
||||||
SharedPostProcessInfo* mPPShared;
|
SharedPostProcessInfo *mPPShared;
|
||||||
|
|
||||||
/// The default class constructor.
|
/// The default class constructor.
|
||||||
ImporterPimpl() AI_NO_EXCEPT;
|
ImporterPimpl() AI_NO_EXCEPT;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT : mIOHandler(nullptr),
|
||||||
ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT :
|
mIsDefaultHandler(false),
|
||||||
mIOHandler( nullptr ),
|
mProgressHandler(nullptr),
|
||||||
mIsDefaultHandler( false ),
|
mIsDefaultProgressHandler(false),
|
||||||
mProgressHandler( nullptr ),
|
mImporter(),
|
||||||
mIsDefaultProgressHandler( false ),
|
mPostProcessingSteps(),
|
||||||
mImporter(),
|
mScene(nullptr),
|
||||||
mPostProcessingSteps(),
|
mErrorString(),
|
||||||
mScene( nullptr ),
|
mException(),
|
||||||
mErrorString(),
|
mIntProperties(),
|
||||||
mException(),
|
mFloatProperties(),
|
||||||
mIntProperties(),
|
mStringProperties(),
|
||||||
mFloatProperties(),
|
mMatrixProperties(),
|
||||||
mStringProperties(),
|
bExtraVerbose(false),
|
||||||
mMatrixProperties(),
|
mPPShared(nullptr) {
|
||||||
bExtraVerbose( false ),
|
|
||||||
mPPShared( nullptr ) {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
//! @endcond
|
//! @endcond
|
||||||
|
@ -164,17 +161,17 @@ public:
|
||||||
/** Wraps a full list of configuration properties for an importer.
|
/** Wraps a full list of configuration properties for an importer.
|
||||||
* Properties can be set using SetGenericProperty */
|
* Properties can be set using SetGenericProperty */
|
||||||
struct PropertyMap {
|
struct PropertyMap {
|
||||||
ImporterPimpl::IntPropertyMap ints;
|
ImporterPimpl::IntPropertyMap ints;
|
||||||
ImporterPimpl::FloatPropertyMap floats;
|
ImporterPimpl::FloatPropertyMap floats;
|
||||||
ImporterPimpl::StringPropertyMap strings;
|
ImporterPimpl::StringPropertyMap strings;
|
||||||
ImporterPimpl::MatrixPropertyMap matrices;
|
ImporterPimpl::MatrixPropertyMap matrices;
|
||||||
|
|
||||||
bool operator == (const PropertyMap& prop) const {
|
bool operator==(const PropertyMap &prop) const {
|
||||||
// fixme: really isocpp? gcc complains
|
// fixme: really isocpp? gcc complains
|
||||||
return ints == prop.ints && floats == prop.floats && strings == prop.strings && matrices == prop.matrices;
|
return ints == prop.ints && floats == prop.floats && strings == prop.strings && matrices == prop.matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty () const {
|
bool empty() const {
|
||||||
return ints.empty() && floats.empty() && strings.empty() && matrices.empty();
|
return ints.empty() && floats.empty() && strings.empty() && matrices.empty();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -184,7 +181,7 @@ public:
|
||||||
/** Construct a batch loader from a given IO system to be used
|
/** Construct a batch loader from a given IO system to be used
|
||||||
* to access external files
|
* to access external files
|
||||||
*/
|
*/
|
||||||
explicit BatchLoader(IOSystem* pIO, bool validate = false );
|
explicit BatchLoader(IOSystem *pIO, bool validate = false);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** The class destructor.
|
/** The class destructor.
|
||||||
|
@ -195,14 +192,14 @@ public:
|
||||||
/** Sets the validation step. True for enable validation during postprocess.
|
/** Sets the validation step. True for enable validation during postprocess.
|
||||||
* @param enable True for validation.
|
* @param enable True for validation.
|
||||||
*/
|
*/
|
||||||
void setValidation( bool enabled );
|
void setValidation(bool enabled);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Returns the current validation step.
|
/** Returns the current validation step.
|
||||||
* @return The current validation step.
|
* @return The current validation step.
|
||||||
*/
|
*/
|
||||||
bool getValidation() const;
|
bool getValidation() const;
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Add a new file to the list of files to be loaded.
|
/** Add a new file to the list of files to be loaded.
|
||||||
* @param file File to be loaded
|
* @param file File to be loaded
|
||||||
|
@ -211,11 +208,10 @@ public:
|
||||||
* @return 'Load request channel' - an unique ID that can later
|
* @return 'Load request channel' - an unique ID that can later
|
||||||
* be used to access the imported file data.
|
* be used to access the imported file data.
|
||||||
* @see GetImport */
|
* @see GetImport */
|
||||||
unsigned int AddLoadRequest (
|
unsigned int AddLoadRequest(
|
||||||
const std::string& file,
|
const std::string &file,
|
||||||
unsigned int steps = 0,
|
unsigned int steps = 0,
|
||||||
const PropertyMap *map = nullptr
|
const PropertyMap *map = nullptr);
|
||||||
);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Get an imported scene.
|
/** Get an imported scene.
|
||||||
|
@ -226,9 +222,8 @@ public:
|
||||||
* @param which LRWC returned by AddLoadRequest().
|
* @param which LRWC returned by AddLoadRequest().
|
||||||
* @return nullptr if there is no scene with this file name
|
* @return nullptr if there is no scene with this file name
|
||||||
* in the queue of the scene hasn't been loaded yet. */
|
* in the queue of the scene hasn't been loaded yet. */
|
||||||
aiScene* GetImport(
|
aiScene *GetImport(
|
||||||
unsigned int which
|
unsigned int which);
|
||||||
);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Waits until all scenes have been loaded. This returns
|
/** Waits until all scenes have been loaded. This returns
|
||||||
|
|
|
@ -45,8 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef AI_POLYTOOLS_H_INCLUDED
|
#ifndef AI_POLYTOOLS_H_INCLUDED
|
||||||
#define AI_POLYTOOLS_H_INCLUDED
|
#define AI_POLYTOOLS_H_INCLUDED
|
||||||
|
|
||||||
#include <assimp/material.h>
|
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
|
#include <assimp/material.h>
|
||||||
|
#include <assimp/vector3.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
@ -55,8 +56,7 @@ namespace Assimp {
|
||||||
* The function accepts an unconstrained template parameter for use with
|
* The function accepts an unconstrained template parameter for use with
|
||||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline double GetArea2D(const T& v1, const T& v2, const T& v3)
|
inline double GetArea2D(const T &v1, const T &v2, const T &v3) {
|
||||||
{
|
|
||||||
return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
|
return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,9 +65,8 @@ inline double GetArea2D(const T& v1, const T& v2, const T& v3)
|
||||||
* The function accepts an unconstrained template parameter for use with
|
* The function accepts an unconstrained template parameter for use with
|
||||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
|
inline bool OnLeftSideOfLine2D(const T &p0, const T &p1, const T &p2) {
|
||||||
{
|
return GetArea2D(p0, p2, p1) > 0;
|
||||||
return GetArea2D(p0,p2,p1) > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
|
@ -75,8 +74,7 @@ inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
|
||||||
* The function accepts an unconstrained template parameter for use with
|
* The function accepts an unconstrained template parameter for use with
|
||||||
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
* both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
|
inline bool PointInTriangle2D(const T &p0, const T &p1, const T &p2, const T &pp) {
|
||||||
{
|
|
||||||
// Point in triangle test using baryzentric coordinates
|
// Point in triangle test using baryzentric coordinates
|
||||||
const aiVector2D v0 = p1 - p0;
|
const aiVector2D v0 = p1 - p0;
|
||||||
const aiVector2D v1 = p2 - p0;
|
const aiVector2D v1 = p2 - p0;
|
||||||
|
@ -95,7 +93,6 @@ inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
|
||||||
return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1);
|
return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
/** Check whether the winding order of a given polygon is counter-clockwise.
|
/** Check whether the winding order of a given polygon is counter-clockwise.
|
||||||
* The function accepts an unconstrained template parameter, but is intended
|
* The function accepts an unconstrained template parameter, but is intended
|
||||||
|
@ -104,7 +101,7 @@ inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
|
||||||
* @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
|
* @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool IsCCW(T* in, size_t npoints) {
|
inline bool IsCCW(T *in, size_t npoints) {
|
||||||
double aa, bb, cc, b, c, theta;
|
double aa, bb, cc, b, c, theta;
|
||||||
double convex_turn;
|
double convex_turn;
|
||||||
double convex_sum = 0;
|
double convex_sum = 0;
|
||||||
|
@ -112,44 +109,43 @@ inline bool IsCCW(T* in, size_t npoints) {
|
||||||
ai_assert(npoints >= 3);
|
ai_assert(npoints >= 3);
|
||||||
|
|
||||||
for (size_t i = 0; i < npoints - 2; i++) {
|
for (size_t i = 0; i < npoints - 2; i++) {
|
||||||
aa = ((in[i+2].x - in[i].x) * (in[i+2].x - in[i].x)) +
|
aa = ((in[i + 2].x - in[i].x) * (in[i + 2].x - in[i].x)) +
|
||||||
((-in[i+2].y + in[i].y) * (-in[i+2].y + in[i].y));
|
((-in[i + 2].y + in[i].y) * (-in[i + 2].y + in[i].y));
|
||||||
|
|
||||||
bb = ((in[i+1].x - in[i].x) * (in[i+1].x - in[i].x)) +
|
bb = ((in[i + 1].x - in[i].x) * (in[i + 1].x - in[i].x)) +
|
||||||
((-in[i+1].y + in[i].y) * (-in[i+1].y + in[i].y));
|
((-in[i + 1].y + in[i].y) * (-in[i + 1].y + in[i].y));
|
||||||
|
|
||||||
cc = ((in[i+2].x - in[i+1].x) *
|
cc = ((in[i + 2].x - in[i + 1].x) *
|
||||||
(in[i+2].x - in[i+1].x)) +
|
(in[i + 2].x - in[i + 1].x)) +
|
||||||
((-in[i+2].y + in[i+1].y) *
|
((-in[i + 2].y + in[i + 1].y) *
|
||||||
(-in[i+2].y + in[i+1].y));
|
(-in[i + 2].y + in[i + 1].y));
|
||||||
|
|
||||||
b = std::sqrt(bb);
|
b = std::sqrt(bb);
|
||||||
c = std::sqrt(cc);
|
c = std::sqrt(cc);
|
||||||
theta = std::acos((bb + cc - aa) / (2 * b * c));
|
theta = std::acos((bb + cc - aa) / (2 * b * c));
|
||||||
|
|
||||||
if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
|
if (OnLeftSideOfLine2D(in[i], in[i + 2], in[i + 1])) {
|
||||||
// if (convex(in[i].x, in[i].y,
|
// if (convex(in[i].x, in[i].y,
|
||||||
// in[i+1].x, in[i+1].y,
|
// in[i+1].x, in[i+1].y,
|
||||||
// in[i+2].x, in[i+2].y)) {
|
// in[i+2].x, in[i+2].y)) {
|
||||||
convex_turn = AI_MATH_PI_F - theta;
|
convex_turn = AI_MATH_PI_F - theta;
|
||||||
convex_sum += convex_turn;
|
convex_sum += convex_turn;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
convex_sum -= AI_MATH_PI_F - theta;
|
convex_sum -= AI_MATH_PI_F - theta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aa = ((in[1].x - in[npoints-2].x) *
|
aa = ((in[1].x - in[npoints - 2].x) *
|
||||||
(in[1].x - in[npoints-2].x)) +
|
(in[1].x - in[npoints - 2].x)) +
|
||||||
((-in[1].y + in[npoints-2].y) *
|
((-in[1].y + in[npoints - 2].y) *
|
||||||
(-in[1].y + in[npoints-2].y));
|
(-in[1].y + in[npoints - 2].y));
|
||||||
|
|
||||||
bb = ((in[0].x - in[npoints-2].x) *
|
bb = ((in[0].x - in[npoints - 2].x) *
|
||||||
(in[0].x - in[npoints-2].x)) +
|
(in[0].x - in[npoints - 2].x)) +
|
||||||
((-in[0].y + in[npoints-2].y) *
|
((-in[0].y + in[npoints - 2].y) *
|
||||||
(-in[0].y + in[npoints-2].y));
|
(-in[0].y + in[npoints - 2].y));
|
||||||
|
|
||||||
cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
|
cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
|
||||||
((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
|
((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
|
||||||
|
|
||||||
b = std::sqrt(bb);
|
b = std::sqrt(bb);
|
||||||
c = std::sqrt(cc);
|
c = std::sqrt(cc);
|
||||||
|
@ -158,18 +154,16 @@ inline bool IsCCW(T* in, size_t npoints) {
|
||||||
//if (convex(in[npoints-2].x, in[npoints-2].y,
|
//if (convex(in[npoints-2].x, in[npoints-2].y,
|
||||||
// in[0].x, in[0].y,
|
// in[0].x, in[0].y,
|
||||||
// in[1].x, in[1].y)) {
|
// in[1].x, in[1].y)) {
|
||||||
if (OnLeftSideOfLine2D(in[npoints-2],in[1],in[0])) {
|
if (OnLeftSideOfLine2D(in[npoints - 2], in[1], in[0])) {
|
||||||
convex_turn = AI_MATH_PI_F - theta;
|
convex_turn = AI_MATH_PI_F - theta;
|
||||||
convex_sum += convex_turn;
|
convex_sum += convex_turn;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
convex_sum -= AI_MATH_PI_F - theta;
|
convex_sum -= AI_MATH_PI_F - theta;
|
||||||
}
|
}
|
||||||
|
|
||||||
return convex_sum >= (2 * AI_MATH_PI_F);
|
return convex_sum >= (2 * AI_MATH_PI_F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
/** Compute the normal of an arbitrary polygon in R3.
|
/** Compute the normal of an arbitrary polygon in R3.
|
||||||
*
|
*
|
||||||
|
@ -185,45 +179,50 @@ inline bool IsCCW(T* in, size_t npoints) {
|
||||||
* @note The data arrays must have storage for at least num+2 elements. Using
|
* @note The data arrays must have storage for at least num+2 elements. Using
|
||||||
* this method is much faster than the 'other' NewellNormal()
|
* this method is much faster than the 'other' NewellNormal()
|
||||||
*/
|
*/
|
||||||
template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
|
template <size_t ofs_x, size_t ofs_y, size_t ofs_z, typename TReal>
|
||||||
inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z)
|
inline void NewellNormal(aiVector3t<TReal> &out, size_t num, TReal *x, TReal *y, TReal *z, size_t bufferSize) {
|
||||||
{
|
ai_assert(bufferSize > num);
|
||||||
|
|
||||||
|
if (nullptr == x || nullptr == y || nullptr == z || 0 == bufferSize || 0 == num) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Duplicate the first two vertices at the end
|
// Duplicate the first two vertices at the end
|
||||||
x[(num+0)*ofs_x] = x[0];
|
x[(num + 0) * ofs_x] = x[0];
|
||||||
x[(num+1)*ofs_x] = x[ofs_x];
|
x[(num + 1) * ofs_x] = x[ofs_x];
|
||||||
|
|
||||||
y[(num+0)*ofs_y] = y[0];
|
y[(num + 0) * ofs_y] = y[0];
|
||||||
y[(num+1)*ofs_y] = y[ofs_y];
|
y[(num + 1) * ofs_y] = y[ofs_y];
|
||||||
|
|
||||||
z[(num+0)*ofs_z] = z[0];
|
z[(num + 0) * ofs_z] = z[0];
|
||||||
z[(num+1)*ofs_z] = z[ofs_z];
|
z[(num + 1) * ofs_z] = z[ofs_z];
|
||||||
|
|
||||||
TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
|
TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
|
||||||
|
|
||||||
TReal *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2;
|
TReal *xptr = x + ofs_x, *xlow = x, *xhigh = x + ofs_x * 2;
|
||||||
TReal *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2;
|
TReal *yptr = y + ofs_y, *ylow = y, *yhigh = y + ofs_y * 2;
|
||||||
TReal *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2;
|
TReal *zptr = z + ofs_z, *zlow = z, *zhigh = z + ofs_z * 2;
|
||||||
|
|
||||||
for (int tmp=0; tmp < num; tmp++) {
|
for (size_t tmp = 0; tmp < num; ++tmp ) {
|
||||||
sum_xy += (*xptr) * ( (*yhigh) - (*ylow) );
|
sum_xy += (*xptr) * ((*yhigh) - (*ylow));
|
||||||
sum_yz += (*yptr) * ( (*zhigh) - (*zlow) );
|
sum_yz += (*yptr) * ((*zhigh) - (*zlow));
|
||||||
sum_zx += (*zptr) * ( (*xhigh) - (*xlow) );
|
sum_zx += (*zptr) * ((*xhigh) - (*xlow));
|
||||||
|
|
||||||
xptr += ofs_x;
|
xptr += ofs_x;
|
||||||
xlow += ofs_x;
|
xlow += ofs_x;
|
||||||
xhigh += ofs_x;
|
xhigh += ofs_x;
|
||||||
|
|
||||||
yptr += ofs_y;
|
yptr += ofs_y;
|
||||||
ylow += ofs_y;
|
ylow += ofs_y;
|
||||||
yhigh += ofs_y;
|
yhigh += ofs_y;
|
||||||
|
|
||||||
zptr += ofs_z;
|
zptr += ofs_z;
|
||||||
zlow += ofs_z;
|
zlow += ofs_z;
|
||||||
zhigh += ofs_z;
|
zhigh += ofs_z;
|
||||||
}
|
}
|
||||||
out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
|
out = aiVector3t<TReal>(sum_yz, sum_zx, sum_xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ! Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,14 +60,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
|
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
|
||||||
|
|
||||||
#include "PostProcessing/TriangulateProcess.h"
|
#include "PostProcessing/TriangulateProcess.h"
|
||||||
#include "PostProcessing/ProcessHelper.h"
|
|
||||||
#include "Common/PolyTools.h"
|
#include "Common/PolyTools.h"
|
||||||
|
#include "PostProcessing/ProcessHelper.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
||||||
//#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||||
|
|
||||||
#define POLY_GRID_Y 40
|
#define POLY_GRID_Y 40
|
||||||
#define POLY_GRID_X 70
|
#define POLY_GRID_X 70
|
||||||
|
@ -78,86 +78,91 @@ using namespace Assimp;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
TriangulateProcess::TriangulateProcess()
|
TriangulateProcess::TriangulateProcess() {
|
||||||
{
|
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Destructor, private as well
|
// Destructor, private as well
|
||||||
TriangulateProcess::~TriangulateProcess()
|
TriangulateProcess::~TriangulateProcess() {
|
||||||
{
|
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns whether the processing step is present in the given flag field.
|
// Returns whether the processing step is present in the given flag field.
|
||||||
bool TriangulateProcess::IsActive( unsigned int pFlags) const
|
bool TriangulateProcess::IsActive(unsigned int pFlags) const {
|
||||||
{
|
|
||||||
return (pFlags & aiProcess_Triangulate) != 0;
|
return (pFlags & aiProcess_Triangulate) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void TriangulateProcess::Execute( aiScene* pScene)
|
void TriangulateProcess::Execute(aiScene *pScene) {
|
||||||
{
|
|
||||||
ASSIMP_LOG_DEBUG("TriangulateProcess begin");
|
ASSIMP_LOG_DEBUG("TriangulateProcess begin");
|
||||||
|
|
||||||
bool bHas = false;
|
bool bHas = false;
|
||||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
for (unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
||||||
{
|
if (pScene->mMeshes[a]) {
|
||||||
if (pScene->mMeshes[ a ]) {
|
if (TriangulateMesh(pScene->mMeshes[a])) {
|
||||||
if ( TriangulateMesh( pScene->mMeshes[ a ] ) ) {
|
|
||||||
bHas = true;
|
bHas = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( bHas ) {
|
if (bHas) {
|
||||||
ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." );
|
ASSIMP_LOG_INFO("TriangulateProcess finished. All polygons have been triangulated.");
|
||||||
} else {
|
} else {
|
||||||
ASSIMP_LOG_DEBUG( "TriangulateProcess finished. There was nothing to be done." );
|
ASSIMP_LOG_DEBUG("TriangulateProcess finished. There was nothing to be done.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static bool validateNumIndices(aiMesh *mesh) {
|
||||||
|
bool bNeed = false;
|
||||||
|
for (unsigned int a = 0; a < mesh->mNumFaces; a++) {
|
||||||
|
const aiFace &face = mesh->mFaces[a];
|
||||||
|
if (face.mNumIndices != 3) {
|
||||||
|
bNeed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
getNormals = false;
|
||||||
|
}
|
||||||
|
if (face.mNumIndices <= 3) {
|
||||||
|
numOut++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
numOut += face.mNumIndices - 2;
|
||||||
|
maxOut = std::max(maxOut, static_cast<size_t>(face.mNumIndices));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Triangulates the given mesh.
|
// Triangulates the given mesh.
|
||||||
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
bool TriangulateProcess::TriangulateMesh(aiMesh *pMesh) {
|
||||||
{
|
|
||||||
// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
|
// Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
|
||||||
if (!pMesh->mPrimitiveTypes) {
|
|
||||||
bool bNeed = false;
|
|
||||||
|
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
if (!pMesh->mPrimitiveTypes) {
|
||||||
const aiFace& face = pMesh->mFaces[a];
|
if (!validateNumIndices(pMesh)) {
|
||||||
|
|
||||||
if( face.mNumIndices != 3) {
|
|
||||||
bNeed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!bNeed)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
|
} else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find out how many output faces we'll get
|
// Find out how many output faces we'll get
|
||||||
uint32_t numOut = 0, max_out = 0;
|
size_t numOut = 0, max_out = 0;
|
||||||
bool get_normals = true;
|
bool getNormals = true;
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
calulateNumOutputFaces(pMesh, numOut, max_out, getNormals);
|
||||||
aiFace& face = pMesh->mFaces[a];
|
|
||||||
if (face.mNumIndices <= 4) {
|
|
||||||
get_normals = false;
|
|
||||||
}
|
|
||||||
if( face.mNumIndices <= 3) {
|
|
||||||
numOut++;
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numOut += face.mNumIndices-2;
|
|
||||||
max_out = std::max(max_out,face.mNumIndices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just another check whether aiMesh::mPrimitiveTypes is correct
|
// Just another check whether aiMesh::mPrimitiveTypes is correct
|
||||||
ai_assert(numOut != pMesh->mNumFaces);
|
ai_assert(numOut != pMesh->mNumFaces);
|
||||||
|
@ -166,87 +171,87 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
// if we don't have normals yet, but expect them to be a cheap side
|
// if we don't have normals yet, but expect them to be a cheap side
|
||||||
// product of triangulation anyway, allocate storage for them.
|
// product of triangulation anyway, allocate storage for them.
|
||||||
if (!pMesh->mNormals && get_normals) {
|
if (!pMesh->mNormals && getNormals) {
|
||||||
// XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
|
// XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
|
||||||
// nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
// nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
|
||||||
}
|
}
|
||||||
|
|
||||||
// the output mesh will contain triangles, but no polys anymore
|
// the output mesh will contain triangles, but no polys anymore
|
||||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||||
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
|
pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
|
||||||
|
|
||||||
aiFace* out = new aiFace[numOut](), *curOut = out;
|
aiFace *out = new aiFace[numOut](), *curOut = out;
|
||||||
std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
|
const size_t Capa = max_out + 2;
|
||||||
std::vector<aiVector2D> temp_verts(max_out+2);
|
std::vector<aiVector3D> temp_verts3d(max_out + 2); /* temporary storage for vertices */
|
||||||
|
std::vector<aiVector2D> temp_verts(max_out + 2);
|
||||||
|
|
||||||
// Apply vertex colors to represent the face winding?
|
// Apply vertex colors to represent the face winding?
|
||||||
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
||||||
if (!pMesh->mColors[0])
|
if (!pMesh->mColors[0])
|
||||||
pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
|
pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
|
||||||
else
|
else
|
||||||
new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
|
new (pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
|
||||||
|
|
||||||
aiColor4D* clr = pMesh->mColors[0];
|
aiColor4D *clr = pMesh->mColors[0];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||||
FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
|
FILE *fout = fopen(POLY_OUTPUT_FILE, "a");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const aiVector3D* verts = pMesh->mVertices;
|
const aiVector3D *verts = pMesh->mVertices;
|
||||||
|
|
||||||
// use std::unique_ptr to avoid slow std::vector<bool> specialiations
|
// use std::unique_ptr to avoid slow std::vector<bool> specialiations
|
||||||
std::unique_ptr<bool[]> done(new bool[max_out]);
|
std::unique_ptr<bool[]> done(new bool[max_out]);
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
for (unsigned int a = 0; a < pMesh->mNumFaces; a++) {
|
||||||
aiFace& face = pMesh->mFaces[a];
|
aiFace &face = pMesh->mFaces[a];
|
||||||
|
|
||||||
unsigned int* idx = face.mIndices;
|
unsigned int *idx = face.mIndices;
|
||||||
int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
|
int num = (int)face.mNumIndices, ear = 0, tmp, prev = num - 1, next = 0, max = num;
|
||||||
|
|
||||||
// Apply vertex colors to represent the face winding?
|
// Apply vertex colors to represent the face winding?
|
||||||
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
|
||||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||||
aiColor4D& c = clr[idx[i]];
|
aiColor4D &c = clr[idx[i]];
|
||||||
c.r = (i+1) / (float)max;
|
c.r = (i + 1) / (float)max;
|
||||||
c.b = 1.f - c.r;
|
c.b = 1.f - c.r;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
aiFace* const last_face = curOut;
|
aiFace *const last_face = curOut;
|
||||||
|
|
||||||
// if it's a simple point,line or triangle: just copy it
|
// if it's a simple point,line or triangle: just copy it
|
||||||
if( face.mNumIndices <= 3)
|
if (face.mNumIndices <= 3) {
|
||||||
{
|
aiFace &nface = *curOut++;
|
||||||
aiFace& nface = *curOut++;
|
|
||||||
nface.mNumIndices = face.mNumIndices;
|
nface.mNumIndices = face.mNumIndices;
|
||||||
nface.mIndices = face.mIndices;
|
nface.mIndices = face.mIndices;
|
||||||
|
|
||||||
face.mIndices = nullptr;
|
face.mIndices = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// optimized code for quadrilaterals
|
// optimized code for quadrilaterals
|
||||||
else if ( face.mNumIndices == 4) {
|
else if (face.mNumIndices == 4) {
|
||||||
|
|
||||||
// quads can have at maximum one concave vertex. Determine
|
// quads can have at maximum one concave vertex. Determine
|
||||||
// this vertex (if it exists) and start tri-fanning from
|
// this vertex (if it exists) and start tri-fanning from
|
||||||
// it.
|
// it.
|
||||||
unsigned int start_vertex = 0;
|
unsigned int start_vertex = 0;
|
||||||
for (unsigned int i = 0; i < 4; ++i) {
|
for (unsigned int i = 0; i < 4; ++i) {
|
||||||
const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
|
const aiVector3D &v0 = verts[face.mIndices[(i + 3) % 4]];
|
||||||
const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
|
const aiVector3D &v1 = verts[face.mIndices[(i + 2) % 4]];
|
||||||
const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
|
const aiVector3D &v2 = verts[face.mIndices[(i + 1) % 4]];
|
||||||
|
|
||||||
const aiVector3D& v = verts[face.mIndices[i]];
|
const aiVector3D &v = verts[face.mIndices[i]];
|
||||||
|
|
||||||
aiVector3D left = (v0-v);
|
aiVector3D left = (v0 - v);
|
||||||
aiVector3D diag = (v1-v);
|
aiVector3D diag = (v1 - v);
|
||||||
aiVector3D right = (v2-v);
|
aiVector3D right = (v2 - v);
|
||||||
|
|
||||||
left.Normalize();
|
left.Normalize();
|
||||||
diag.Normalize();
|
diag.Normalize();
|
||||||
right.Normalize();
|
right.Normalize();
|
||||||
|
|
||||||
const float angle = std::acos(left*diag) + std::acos(right*diag);
|
const float angle = std::acos(left * diag) + std::acos(right * diag);
|
||||||
if (angle > AI_MATH_PI_F) {
|
if (angle > AI_MATH_PI_F) {
|
||||||
// this is the concave point
|
// this is the concave point
|
||||||
start_vertex = i;
|
start_vertex = i;
|
||||||
|
@ -254,9 +259,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
|
const unsigned int temp[] = { face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3] };
|
||||||
|
|
||||||
aiFace& nface = *curOut++;
|
aiFace &nface = *curOut++;
|
||||||
nface.mNumIndices = 3;
|
nface.mNumIndices = 3;
|
||||||
nface.mIndices = face.mIndices;
|
nface.mIndices = face.mIndices;
|
||||||
|
|
||||||
|
@ -264,7 +269,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
nface.mIndices[1] = temp[(start_vertex + 1) % 4];
|
nface.mIndices[1] = temp[(start_vertex + 1) % 4];
|
||||||
nface.mIndices[2] = temp[(start_vertex + 2) % 4];
|
nface.mIndices[2] = temp[(start_vertex + 2) % 4];
|
||||||
|
|
||||||
aiFace& sface = *curOut++;
|
aiFace &sface = *curOut++;
|
||||||
sface.mNumIndices = 3;
|
sface.mNumIndices = 3;
|
||||||
sface.mIndices = new unsigned int[3];
|
sface.mIndices = new unsigned int[3];
|
||||||
|
|
||||||
|
@ -275,9 +280,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
// prevent double deletion of the indices field
|
// prevent double deletion of the indices field
|
||||||
face.mIndices = nullptr;
|
face.mIndices = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// A polygon with more than 3 vertices can be either concave or convex.
|
// A polygon with more than 3 vertices can be either concave or convex.
|
||||||
// Usually everything we're getting is convex and we could easily
|
// Usually everything we're getting is convex and we could easily
|
||||||
// triangulate by tri-fanning. However, LightWave is probably the only
|
// triangulate by tri-fanning. However, LightWave is probably the only
|
||||||
|
@ -288,42 +291,43 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
// We project it onto a plane to get a 2d triangle.
|
// We project it onto a plane to get a 2d triangle.
|
||||||
|
|
||||||
// Collect all vertices of of the polygon.
|
// Collect all vertices of of the polygon.
|
||||||
for (tmp = 0; tmp < max; ++tmp) {
|
for (tmp = 0; tmp < max; ++tmp) {
|
||||||
temp_verts3d[tmp] = verts[idx[tmp]];
|
temp_verts3d[tmp] = verts[idx[tmp]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
|
// Get Newell-Normal of the polygon. Store it for future use if it's a polygon-only mesh
|
||||||
aiVector3D n;
|
aiVector3D n;
|
||||||
NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
|
NewellNormal<3, 3, 3>(n, max, &temp_verts3d.front().x, &temp_verts3d.front().y, &temp_verts3d.front().z, Capa);
|
||||||
if (nor_out) {
|
if (nor_out) {
|
||||||
for (tmp = 0; tmp < max; ++tmp)
|
for (tmp = 0; tmp < max; ++tmp)
|
||||||
nor_out[idx[tmp]] = n;
|
nor_out[idx[tmp]] = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select largest normal coordinate to ignore for projection
|
// Select largest normal coordinate to ignore for projection
|
||||||
const float ax = (n.x>0 ? n.x : -n.x);
|
const float ax = (n.x > 0 ? n.x : -n.x);
|
||||||
const float ay = (n.y>0 ? n.y : -n.y);
|
const float ay = (n.y > 0 ? n.y : -n.y);
|
||||||
const float az = (n.z>0 ? n.z : -n.z);
|
const float az = (n.z > 0 ? n.z : -n.z);
|
||||||
|
|
||||||
unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
|
unsigned int ac = 0, bc = 1; // no z coord. projection to xy
|
||||||
float inv = n.z;
|
float inv = n.z;
|
||||||
if (ax > ay) {
|
if (ax > ay) {
|
||||||
if (ax > az) { /* no x coord. projection to yz */
|
if (ax > az) { // no x coord. projection to yz
|
||||||
ac = 1; bc = 2;
|
ac = 1;
|
||||||
|
bc = 2;
|
||||||
inv = n.x;
|
inv = n.x;
|
||||||
}
|
}
|
||||||
}
|
} else if (ay > az) { // no y coord. projection to zy
|
||||||
else if (ay > az) { /* no y coord. projection to zy */
|
ac = 2;
|
||||||
ac = 2; bc = 0;
|
bc = 0;
|
||||||
inv = n.y;
|
inv = n.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap projection axes to take the negated projection vector into account
|
// Swap projection axes to take the negated projection vector into account
|
||||||
if (inv < 0.f) {
|
if (inv < 0.f) {
|
||||||
std::swap(ac,bc);
|
std::swap(ac, bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tmp =0; tmp < max; ++tmp) {
|
for (tmp = 0; tmp < max; ++tmp) {
|
||||||
temp_verts[tmp].x = verts[idx[tmp]][ac];
|
temp_verts[tmp].x = verts[idx[tmp]][ac];
|
||||||
temp_verts[tmp].y = verts[idx[tmp]][bc];
|
temp_verts[tmp].y = verts[idx[tmp]][bc];
|
||||||
done[tmp] = false;
|
done[tmp] = false;
|
||||||
|
@ -331,30 +335,30 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||||
// plot the plane onto which we mapped the polygon to a 2D ASCII pic
|
// plot the plane onto which we mapped the polygon to a 2D ASCII pic
|
||||||
aiVector2D bmin,bmax;
|
aiVector2D bmin, bmax;
|
||||||
ArrayBounds(&temp_verts[0],max,bmin,bmax);
|
ArrayBounds(&temp_verts[0], max, bmin, bmax);
|
||||||
|
|
||||||
char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
|
char grid[POLY_GRID_Y][POLY_GRID_X + POLY_GRID_XPAD];
|
||||||
std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
|
std::fill_n((char *)grid, POLY_GRID_Y * (POLY_GRID_X + POLY_GRID_XPAD), ' ');
|
||||||
|
|
||||||
for (int i =0; i < max; ++i) {
|
for (int i = 0; i < max; ++i) {
|
||||||
const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
|
const aiVector2D &v = (temp_verts[i] - bmin) / (bmax - bmin);
|
||||||
const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
|
const size_t x = static_cast<size_t>(v.x * (POLY_GRID_X - 1)), y = static_cast<size_t>(v.y * (POLY_GRID_Y - 1));
|
||||||
char* loc = grid[y]+x;
|
char *loc = grid[y] + x;
|
||||||
if (grid[y][x] != ' ') {
|
if (grid[y][x] != ' ') {
|
||||||
for(;*loc != ' '; ++loc);
|
for (; *loc != ' '; ++loc)
|
||||||
|
;
|
||||||
*loc++ = '_';
|
*loc++ = '_';
|
||||||
}
|
}
|
||||||
*(loc+::ai_snprintf(loc, POLY_GRID_XPAD,"%i",i)) = ' ';
|
*(loc + ::ai_snprintf(loc, POLY_GRID_XPAD, "%i", i)) = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t y = 0; y < POLY_GRID_Y; ++y) {
|
||||||
for(size_t y = 0; y < POLY_GRID_Y; ++y) {
|
grid[y][POLY_GRID_X + POLY_GRID_XPAD - 1] = '\0';
|
||||||
grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
|
fprintf(fout, "%s\n", grid[y]);
|
||||||
fprintf(fout,"%s\n",grid[y]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fout,"\ntriangulation sequence: ");
|
fprintf(fout, "\ntriangulation sequence: ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -364,26 +368,27 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
|
|
||||||
// Find the next ear of the polygon
|
// Find the next ear of the polygon
|
||||||
int num_found = 0;
|
int num_found = 0;
|
||||||
for (ear = next;;prev = ear,ear = next) {
|
for (ear = next;; prev = ear, ear = next) {
|
||||||
|
|
||||||
// break after we looped two times without a positive match
|
// break after we looped two times without a positive match
|
||||||
for (next=ear+1;done[(next>=max?next=0:next)];++next);
|
for (next = ear + 1; done[(next >= max ? next = 0 : next)]; ++next)
|
||||||
|
;
|
||||||
if (next < ear) {
|
if (next < ear) {
|
||||||
if (++num_found == 2) {
|
if (++num_found == 2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const aiVector2D* pnt1 = &temp_verts[ear],
|
const aiVector2D *pnt1 = &temp_verts[ear],
|
||||||
*pnt0 = &temp_verts[prev],
|
*pnt0 = &temp_verts[prev],
|
||||||
*pnt2 = &temp_verts[next];
|
*pnt2 = &temp_verts[next];
|
||||||
|
|
||||||
// Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
|
// Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
|
||||||
if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
|
if (OnLeftSideOfLine2D(*pnt0, *pnt2, *pnt1)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and no other point may be contained in this triangle
|
// and no other point may be contained in this triangle
|
||||||
for ( tmp = 0; tmp < max; ++tmp) {
|
for (tmp = 0; tmp < max; ++tmp) {
|
||||||
|
|
||||||
// We need to compare the actual values because it's possible that multiple indexes in
|
// We need to compare the actual values because it's possible that multiple indexes in
|
||||||
// the polygon are referring to the same position. concave_polygon.obj is a sample
|
// the polygon are referring to the same position. concave_polygon.obj is a sample
|
||||||
|
@ -392,8 +397,8 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
// PointInTriangle() I'm guessing that it's actually possible to construct
|
// PointInTriangle() I'm guessing that it's actually possible to construct
|
||||||
// input data that would cause us to end up with no ears. The problem is,
|
// input data that would cause us to end up with no ears. The problem is,
|
||||||
// which epsilon? If we chose a too large value, we'd get wrong results
|
// which epsilon? If we chose a too large value, we'd get wrong results
|
||||||
const aiVector2D& vtmp = temp_verts[tmp];
|
const aiVector2D &vtmp = temp_verts[tmp];
|
||||||
if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
|
if (vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0, *pnt1, *pnt2, vtmp)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,29 +420,13 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
|
ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
|
||||||
|
|
||||||
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||||
fprintf(fout,"critical error here, no ear found! ");
|
fprintf(fout, "critical error here, no ear found! ");
|
||||||
#endif
|
#endif
|
||||||
num = 0;
|
num = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*curOut -= (max-num); // undo all previous work
|
|
||||||
for (tmp = 0; tmp < max-2; ++tmp) {
|
|
||||||
aiFace& nface = *curOut++;
|
|
||||||
|
|
||||||
nface.mNumIndices = 3;
|
|
||||||
if (!nface.mIndices)
|
|
||||||
nface.mIndices = new unsigned int[3];
|
|
||||||
|
|
||||||
nface.mIndices[0] = 0;
|
|
||||||
nface.mIndices[1] = tmp+1;
|
|
||||||
nface.mIndices[2] = tmp+2;
|
|
||||||
|
|
||||||
}
|
|
||||||
num = 0;
|
|
||||||
break;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aiFace& nface = *curOut++;
|
aiFace &nface = *curOut++;
|
||||||
nface.mNumIndices = 3;
|
nface.mNumIndices = 3;
|
||||||
|
|
||||||
if (!nface.mIndices) {
|
if (!nface.mIndices) {
|
||||||
|
@ -455,56 +444,40 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
}
|
}
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
// We have three indices forming the last 'ear' remaining. Collect them.
|
// We have three indices forming the last 'ear' remaining. Collect them.
|
||||||
aiFace& nface = *curOut++;
|
aiFace &nface = *curOut++;
|
||||||
nface.mNumIndices = 3;
|
nface.mNumIndices = 3;
|
||||||
if (!nface.mIndices) {
|
if (!nface.mIndices) {
|
||||||
nface.mIndices = new unsigned int[3];
|
nface.mIndices = new unsigned int[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tmp = 0; done[tmp]; ++tmp);
|
for (tmp = 0; done[tmp]; ++tmp)
|
||||||
|
;
|
||||||
nface.mIndices[0] = tmp;
|
nface.mIndices[0] = tmp;
|
||||||
|
|
||||||
for (++tmp; done[tmp]; ++tmp);
|
for (++tmp; done[tmp]; ++tmp)
|
||||||
|
;
|
||||||
nface.mIndices[1] = tmp;
|
nface.mIndices[1] = tmp;
|
||||||
|
|
||||||
for (++tmp; done[tmp]; ++tmp);
|
for (++tmp; done[tmp]; ++tmp)
|
||||||
|
;
|
||||||
nface.mIndices[2] = tmp;
|
nface.mIndices[2] = tmp;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
|
||||||
|
|
||||||
for(aiFace* f = last_face; f != curOut; ++f) {
|
for (aiFace *f = last_face; f != curOut; ++f) {
|
||||||
unsigned int* i = f->mIndices;
|
unsigned int *i = f->mIndices;
|
||||||
fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
|
fprintf(fout, " (%i %i %i)", i[0], i[1], i[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fout,"\n*********************************************************************\n");
|
fprintf(fout, "\n*********************************************************************\n");
|
||||||
fflush(fout);
|
fflush(fout);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(aiFace* f = last_face; f != curOut; ) {
|
for (aiFace *f = last_face; f != curOut;) {
|
||||||
unsigned int* i = f->mIndices;
|
unsigned int *i = f->mIndices;
|
||||||
|
|
||||||
// drop dumb 0-area triangles - deactivated for now:
|
|
||||||
//FindDegenerates post processing step can do the same thing
|
|
||||||
//if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
|
|
||||||
// ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0");
|
|
||||||
// --curOut;
|
|
||||||
|
|
||||||
// delete[] f->mIndices;
|
|
||||||
// f->mIndices = nullptr;
|
|
||||||
|
|
||||||
// for(aiFace* ff = f; ff != curOut; ++ff) {
|
|
||||||
// ff->mNumIndices = (ff+1)->mNumIndices;
|
|
||||||
// ff->mIndices = (ff+1)->mIndices;
|
|
||||||
// (ff+1)->mIndices = nullptr;
|
|
||||||
// }
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
|
|
||||||
i[0] = idx[i[0]];
|
i[0] = idx[i[0]];
|
||||||
i[1] = idx[i[1]];
|
i[1] = idx[i[1]];
|
||||||
i[2] = idx[i[2]];
|
i[2] = idx[i[2]];
|
||||||
|
@ -520,11 +493,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// kill the old faces
|
// kill the old faces
|
||||||
delete [] pMesh->mFaces;
|
delete[] pMesh->mFaces;
|
||||||
|
|
||||||
// ... and store the new ones
|
// ... and store the new ones
|
||||||
pMesh->mFaces = out;
|
pMesh->mFaces = out;
|
||||||
pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
|
pMesh->mNumFaces = (unsigned int)(curOut - out); /* not necessarily equal to numOut */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ SET( COMMON
|
||||||
unit/Common/utSpatialSort.cpp
|
unit/Common/utSpatialSort.cpp
|
||||||
unit/Common/utAssertHandler.cpp
|
unit/Common/utAssertHandler.cpp
|
||||||
unit/Common/utXmlParser.cpp
|
unit/Common/utXmlParser.cpp
|
||||||
|
unit/Common/utPolyTools.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SET( IMPORTERS
|
SET( IMPORTERS
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2020, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -43,9 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef AV_ANIMEVALUATOR_H_INCLUDED
|
#ifndef AV_ANIMEVALUATOR_H_INCLUDED
|
||||||
#define AV_ANIMEVALUATOR_H_INCLUDED
|
#define AV_ANIMEVALUATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <assimp/matrix4x4.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct aiAnimation;
|
||||||
|
|
||||||
namespace AssimpView {
|
namespace AssimpView {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +78,7 @@ public:
|
||||||
* the aiAnimation. */
|
* the aiAnimation. */
|
||||||
const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; }
|
const std::vector<aiMatrix4x4> &GetTransformations() const { return mTransforms; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
const aiAnimation *mAnim;
|
const aiAnimation *mAnim;
|
||||||
double mLastTime;
|
double mLastTime;
|
||||||
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions;
|
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>> mLastPositions;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,7 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef AV_SCENEANIMATOR_H_INCLUDED
|
#ifndef AV_SCENEANIMATOR_H_INCLUDED
|
||||||
#define AV_SCENEANIMATOR_H_INCLUDED
|
#define AV_SCENEANIMATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace AssimpView {
|
namespace AssimpView {
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ namespace AssimpView {
|
||||||
struct SceneAnimNode {
|
struct SceneAnimNode {
|
||||||
std::string mName;
|
std::string mName;
|
||||||
SceneAnimNode *mParent;
|
SceneAnimNode *mParent;
|
||||||
std::vector<SceneAnimNode *> mChildren;
|
std::vector<SceneAnimNode*> mChildren;
|
||||||
|
|
||||||
//! most recently calculated local transform
|
//! most recently calculated local transform
|
||||||
aiMatrix4x4 mLocalTransform;
|
aiMatrix4x4 mLocalTransform;
|
||||||
|
@ -72,13 +75,23 @@ struct SceneAnimNode {
|
||||||
|
|
||||||
//! Default construction
|
//! Default construction
|
||||||
SceneAnimNode() :
|
SceneAnimNode() :
|
||||||
mName(), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) {
|
mName(),
|
||||||
|
mParent(nullptr),
|
||||||
|
mChildren(),
|
||||||
|
mLocalTransform(),
|
||||||
|
mGlobalTransform(),
|
||||||
|
mChannelIndex(-1) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Construction from a given name
|
//! Construction from a given name
|
||||||
SceneAnimNode(const std::string &pName) :
|
SceneAnimNode(const std::string &pName) :
|
||||||
mName(pName), mParent(nullptr), mChildren(), mLocalTransform(), mGlobalTransform(), mChannelIndex(-1) {
|
mName(pName),
|
||||||
|
mParent(nullptr),
|
||||||
|
mChildren(),
|
||||||
|
mLocalTransform(),
|
||||||
|
mGlobalTransform(),
|
||||||
|
mChannelIndex(-1) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +138,7 @@ public:
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Calculates the node transformations for the scene. Call this to get
|
/** Calculates the node transformations for the scene. Call this to get
|
||||||
* uptodate results before calling one of the getters.
|
* up-to-date results before calling one of the getters.
|
||||||
* @param pTime Current time. Can be an arbitrary range.
|
* @param pTime Current time. Can be an arbitrary range.
|
||||||
*/
|
*/
|
||||||
void Calculate(double pTime);
|
void Calculate(double pTime);
|
||||||
|
@ -136,7 +149,7 @@ public:
|
||||||
* The returned matrix is in the node's parent's local space, just like the
|
* The returned matrix is in the node's parent's local space, just like the
|
||||||
* original node's transformation matrix. If the node is not animated, the
|
* original node's transformation matrix. If the node is not animated, the
|
||||||
* node's original transformation is returned so that you can safely use or
|
* node's original transformation is returned so that you can safely use or
|
||||||
* assign it to the node itsself. If there is no node with the given name,
|
* assign it to the node itself. If there is no node with the given name,
|
||||||
* the identity matrix is returned. All transformations are updated whenever
|
* the identity matrix is returned. All transformations are updated whenever
|
||||||
* Calculate() is called.
|
* Calculate() is called.
|
||||||
* @param pNodeName Name of the node
|
* @param pNodeName Name of the node
|
||||||
|
@ -151,7 +164,7 @@ public:
|
||||||
* The returned matrix is in world space, which is the same coordinate space
|
* The returned matrix is in world space, which is the same coordinate space
|
||||||
* as the transformation of the scene's root node. If the node is not animated,
|
* as the transformation of the scene's root node. If the node is not animated,
|
||||||
* the node's original transformation is returned so that you can safely use or
|
* the node's original transformation is returned so that you can safely use or
|
||||||
* assign it to the node itsself. If there is no node with the given name, the
|
* assign it to the node itself. If there is no node with the given name, the
|
||||||
* identity matrix is returned. All transformations are updated whenever
|
* identity matrix is returned. All transformations are updated whenever
|
||||||
* Calculate() is called.
|
* Calculate() is called.
|
||||||
* @param pNodeName Name of the node
|
* @param pNodeName Name of the node
|
||||||
|
@ -190,7 +203,7 @@ public:
|
||||||
/** @brief Get the current animation or NULL
|
/** @brief Get the current animation or NULL
|
||||||
*/
|
*/
|
||||||
aiAnimation *CurrentAnim() const {
|
aiAnimation *CurrentAnim() const {
|
||||||
return static_cast<unsigned int>(mCurrentAnimIndex) < mScene->mNumAnimations ? mScene->mAnimations[mCurrentAnimIndex] : NULL;
|
return static_cast<unsigned int>(mCurrentAnimIndex) < mScene->mNumAnimations ? mScene->mAnimations[mCurrentAnimIndex] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue