diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index f80fadff9..908f5e065 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -258,7 +258,7 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul return; } - const unsigned int cnt_segments = std::max(2u,static_cast(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); + const unsigned int cnt_segments = std::max(2u,static_cast(conv.settings.cylindricalTessellation * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); const IfcFloat delta = max_angle/cnt_segments; has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99; @@ -327,7 +327,7 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv return; } - const unsigned int cnt_segments = 16; + const unsigned int cnt_segments = conv.settings.cylindricalTessellation; const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments; const size_t samples = curve->EstimateSampleCount(solid.StartParam,solid.EndParam); diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 77b78d85b..0021ceb86 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -153,11 +153,10 @@ const aiImporterDesc* IFCImporter::GetInfo () const void IFCImporter::SetupProperties(const Importer* pImp) { settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true); - settings.skipCurveRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS,true); settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true); - - settings.conicSamplingAngle = 10.f; - settings.skipAnnotations = true; + settings.conicSamplingAngle = std::min(std::max(pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f); + settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180); + settings.skipAnnotations = true; } diff --git a/code/IFCLoader.h b/code/IFCLoader.h index e301a329d..9fa6cba38 100644 --- a/code/IFCLoader.h +++ b/code/IFCLoader.h @@ -107,18 +107,18 @@ public: { Settings() : skipSpaceRepresentations() - , skipCurveRepresentations() , useCustomTriangulation() , skipAnnotations() , conicSamplingAngle(10.f) + , cylindricalTessellation(32) {} bool skipSpaceRepresentations; - bool skipCurveRepresentations; bool useCustomTriangulation; bool skipAnnotations; float conicSamplingAngle; + int cylindricalTessellation; }; diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index c2a7439ee..f40b49fe4 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -901,13 +901,21 @@ size_t CloseWindows(ContourVector& contours, curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4); curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size()); + bool reverseCountourFaces = false; + // compare base poly normal and contour normal to detect if we need to reverse the face winding - IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal( curmesh.verts.data(), curmesh.vertcnt.front()); - std::vector worldSpaceContourVtx( it->contour.size()); - for( size_t a = 0; a < it->contour.size(); ++a ) - worldSpaceContourVtx[a] = minv * IfcVector3( it->contour[a].x, it->contour[a].y, 0.0); - IfcVector3 contourNormal = TempMesh::ComputePolygonNormal( worldSpaceContourVtx.data(), worldSpaceContourVtx.size()); - bool reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0; + if(curmesh.vertcnt.size() > 0) { + IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal(curmesh.verts.data(), curmesh.vertcnt.front()); + + std::vector worldSpaceContourVtx(it->contour.size()); + + for(size_t a = 0; a < it->contour.size(); ++a) + worldSpaceContourVtx[a] = minv * IfcVector3(it->contour[a].x, it->contour[a].y, 0.0); + + IfcVector3 contourNormal = TempMesh::ComputePolygonNormal(worldSpaceContourVtx.data(), worldSpaceContourVtx.size()); + + reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0; + } // XXX this algorithm is really a bit inefficient - both in terms // of constant factor and of asymptotic runtime. diff --git a/code/IFCProfile.cpp b/code/IFCProfile.cpp index a84f98f58..866b874c9 100644 --- a/code/IFCProfile.cpp +++ b/code/IFCProfile.cpp @@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout } // ------------------------------------------------------------------------------------------------ -void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/) +void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) { if(const IfcRectangleProfileDef* const cprofile = def.ToPtr()) { const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; @@ -117,7 +117,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& if(def.ToPtr()) { // TODO } - const size_t segments = 32; + const size_t segments = conv.settings.cylindricalTessellation; const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius; meshout.verts.reserve(segments); diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 148a68868..9f0e70704 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -844,14 +844,6 @@ enum aiComponent #define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME" -/** @brief Specifies whether the IFC loader skips over IfcSpace elements. - * - * IfcSpace elements (and their geometric representations) are used to - * represent, well, free space in a building storey.
- * Property type: Bool. Default value: true. - */ -#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS" - /** @brief Specifies whether the Android JNI asset extraction is supported. * * Turn on this option if you want to manage assets in native @@ -860,17 +852,14 @@ enum aiComponent */ #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT" - // --------------------------------------------------------------------------- -/** @brief Specifies whether the IFC loader skips over - * shape representations of type 'Curve2D'. +/** @brief Specifies whether the IFC loader skips over IfcSpace elements. * - * A lot of files contain both a faceted mesh representation and a outline - * with a presentation type of 'Curve2D'. Currently Assimp doesn't convert those, - * so turning this option off just clutters the log with errors.
+ * IfcSpace elements (and their geometric representations) are used to + * represent, well, free space in a building storey.
* Property type: Bool. Default value: true. */ -#define AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS "IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS" +#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS" // --------------------------------------------------------------------------- /** @brief Specifies whether the IFC loader will use its own, custom triangulation @@ -887,6 +876,38 @@ enum aiComponent */ #define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION" +// --------------------------------------------------------------------------- +/** @brief Set the tessellation conic angle for IFC smoothing curves. + * + * This is used by the IFC importer to determine the tessellation parameter + * for smoothing curves. + * @note The default value is AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE and the + * accepted values are in range [5.0, 120.0]. + * Property type: Float. + */ +#define AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE "IMPORT_IFC_SMOOTHING_ANGLE" + +// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE +#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE) +# define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f +#endif + +// --------------------------------------------------------------------------- +/** @brief Set the tessellation for IFC cylindrical shapes. + * + * This is used by the IFC importer to determine the tessellation parameter + * for cylindrical shapes, i.e. the number of segments used to aproximate a circle. + * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the + * accepted values are in range [3, 180]. + * Property type: Integer. + */ +#define AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION "IMPORT_IFC_CYLINDRICAL_TESSELLATION" + +// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION +#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION) +# define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32 +#endif + // --------------------------------------------------------------------------- /** @brief Specifies whether the Collada loader will ignore the provided up direction. * diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 3b52553b0..fbf950c72 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -198,6 +198,29 @@ struct aiMetadata { return data; } + template + inline void Add(const std::string& key, const T& value) + { + aiString* new_keys = new aiString[mNumProperties + 1]; + aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; + + for(unsigned int i = 0; i < mNumProperties; ++i) + { + new_keys[i] = mKeys[i]; + new_values[i] = mValues[i]; + } + + delete mKeys; + delete mValues; + + mKeys = new_keys; + mValues = new_values; + + mNumProperties++; + + Set(mNumProperties - 1, key, value); + } + template inline bool Set( unsigned index, const std::string& key, const T& value ) {