closes https://github.com/assimp/assimp/issues/1514: add postprocess step for scaling

pull/1520/head
Kim Kulling 2017-10-29 20:28:59 +01:00
parent 89d198399c
commit f49de6ecfe
9 changed files with 234 additions and 118 deletions

View File

@ -156,6 +156,8 @@ SET( Common_SRCS
SkeletonMeshBuilder.h
SplitByBoneCountProcess.cpp
SplitByBoneCountProcess.h
ScaleProcess.cpp
ScaleProcess.h
SmoothingGroups.h
StandardShapes.cpp
StandardShapes.h

View File

@ -1,4 +1,4 @@
/*
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------

View File

@ -56,14 +56,11 @@ namespace Assimp
* vectors of an object are facing inwards. In this case they will be
* flipped.
*/
class FixInfacingNormalsProcess : public BaseProcess
{
class FixInfacingNormalsProcess : public BaseProcess {
public:
FixInfacingNormalsProcess();
~FixInfacingNormalsProcess();
public:
// -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag field.
* @param pFlags The processing flags the importer was called with. A bitwise

View File

@ -43,28 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Read profile and curves entities from IFC files
*/
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
namespace Assimp {
namespace IFC {
namespace {
namespace IFC {
namespace {
// --------------------------------------------------------------------------------
// Conic is the base class for Circle and Ellipse
// --------------------------------------------------------------------------------
class Conic : public Curve
{
class Conic : public Curve {
public:
// --------------------------------------------------
Conic(const IfcConic& entity, ConversionData& conv)
: Curve(entity,conv)
{
: Curve(entity,conv) {
IfcMatrix4 trafo;
ConvertAxisPlacement(trafo,*entity.Position,conv);
@ -75,8 +69,6 @@ public:
p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
}
public:
// --------------------------------------------------
bool IsClosed() const {
return true;
@ -84,7 +76,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b));
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
a *= conv.angle_scale;
b *= conv.angle_scale;
@ -104,15 +97,11 @@ protected:
IfcVector3 location, p[3];
};
// --------------------------------------------------------------------------------
// Circle
// --------------------------------------------------------------------------------
class Circle : public Conic
{
class Circle : public Conic {
public:
// --------------------------------------------------
Circle(const IfcCircle& entity, ConversionData& conv)
: Conic(entity,conv)
@ -120,8 +109,6 @@ public:
{
}
public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
@ -137,20 +124,15 @@ private:
// --------------------------------------------------------------------------------
// Ellipse
// --------------------------------------------------------------------------------
class Ellipse : public Conic
{
class Ellipse : public Conic {
public:
// --------------------------------------------------
Ellipse(const IfcEllipse& entity, ConversionData& conv)
: Conic(entity,conv)
, entity(entity)
{
: Conic(entity,conv)
, entity(entity) {
// empty
}
public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u;
@ -162,25 +144,18 @@ private:
const IfcEllipse& entity;
};
// --------------------------------------------------------------------------------
// Line
// --------------------------------------------------------------------------------
class Line : public Curve
{
class Line : public Curve {
public:
// --------------------------------------------------
Line(const IfcLine& entity, ConversionData& conv)
: Curve(entity,conv)
{
: Curve(entity,conv) {
ConvertCartesianPoint(p,entity.Pnt);
ConvertVector(v,entity.Dir);
}
public:
// --------------------------------------------------
bool IsClosed() const {
return false;
@ -193,16 +168,17 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b));
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
// two points are always sufficient for a line segment
return a==b ? 1 : 2;
}
// --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
{
ai_assert(InRange(a) && InRange(b));
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
if (a == b) {
out.verts.push_back(Eval(a));
@ -227,18 +203,14 @@ private:
// --------------------------------------------------------------------------------
// CompositeCurve joins multiple smaller, bounded curves
// --------------------------------------------------------------------------------
class CompositeCurve : public BoundedCurve
{
class CompositeCurve : public BoundedCurve {
typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;
public:
// --------------------------------------------------
CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
: BoundedCurve(entity,conv)
, total()
{
: BoundedCurve(entity,conv)
, total() {
curves.reserve(entity.Segments.size());
for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) {
// according to the specification, this must be a bounded curve
@ -263,8 +235,6 @@ public:
}
}
public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const {
if (curves.empty()) {
@ -287,7 +257,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b));
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
size_t cnt = 0;
IfcFloat acc = 0;
@ -306,9 +277,9 @@ public:
}
// --------------------------------------------------
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
{
ai_assert(InRange(a) && InRange(b));
void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
const size_t cnt = EstimateSampleCount(a,b);
out.verts.reserve(out.verts.size() + cnt);
@ -330,19 +301,14 @@ public:
private:
std::vector< CurveEntry > curves;
IfcFloat total;
};
// --------------------------------------------------------------------------------
// TrimmedCurve can be used to trim an unbounded curve to a bounded range
// --------------------------------------------------------------------------------
class TrimmedCurve : public BoundedCurve
{
class TrimmedCurve : public BoundedCurve {
public:
// --------------------------------------------------
TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
: BoundedCurve(entity,conv)
@ -409,8 +375,6 @@ public:
ai_assert(maxval >= 0);
}
public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p));
@ -419,7 +383,8 @@ public:
// --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b));
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
}
@ -435,13 +400,11 @@ public:
}
private:
// --------------------------------------------------
IfcFloat TrimParam(IfcFloat f) const {
return agree_sense ? f + range.first : range.second - f;
}
private:
ParamRange range;
IfcFloat maxval;
@ -454,11 +417,8 @@ private:
// --------------------------------------------------------------------------------
// PolyLine is a 'curve' defined by linear interpolation over a set of discrete points
// --------------------------------------------------------------------------------
class PolyLine : public BoundedCurve
{
class PolyLine : public BoundedCurve {
public:
// --------------------------------------------------
PolyLine(const IfcPolyline& entity, ConversionData& conv)
: BoundedCurve(entity,conv)
@ -472,8 +432,6 @@ public:
}
}
public:
// --------------------------------------------------
IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p));
@ -502,13 +460,10 @@ private:
std::vector<IfcVector3> points;
};
} // anon
// ------------------------------------------------------------------------------------------------
Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
{
Curve* Curve::Convert(const IFC::IfcCurve& curve,ConversionData& conv) {
if(curve.ToPtr<IfcBoundedCurve>()) {
if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
return new PolyLine(*c,conv);
@ -519,9 +474,6 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
return new CompositeCurve(*c,conv);
}
//if(const IfcBSplineCurve* c = curve.ToPtr<IfcBSplineCurve>()) {
// return new BSplineCurve(*c,conv);
//}
}
if(curve.ToPtr<IfcConic>()) {
@ -543,8 +495,7 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
#ifdef ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------
bool Curve :: InRange(IfcFloat u) const
{
bool Curve::InRange(IfcFloat u) const {
const ParamRange range = GetParametricRange();
if (IsClosed()) {
return true;
@ -555,24 +506,23 @@ bool Curve :: InRange(IfcFloat u) const
#endif
// ------------------------------------------------------------------------------------------------
IfcFloat Curve :: GetParametricRangeDelta() const
{
IfcFloat Curve::GetParametricRangeDelta() const {
const ParamRange& range = GetParametricRange();
return std::abs(range.second - range.first);
}
// ------------------------------------------------------------------------------------------------
size_t Curve :: EstimateSampleCount(IfcFloat a, IfcFloat b) const
{
ai_assert(InRange(a) && InRange(b));
size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
// arbitrary default value, deriving classes should supply better suited values
return 16;
}
// ------------------------------------------------------------------------------------------------
IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b, unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15)
{
IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b,
unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15) {
ai_assert(samples>1);
const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
@ -594,7 +544,8 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
}
ai_assert(min_diff[0] != inf && min_diff[1] != inf);
ai_assert( min_diff[ 0 ] != inf );
ai_assert( min_diff[ 1 ] != inf );
if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
return min_point[0];
}
@ -615,15 +566,15 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
}
// ------------------------------------------------------------------------------------------------
bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
bool Curve::ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
{
// note: the following algorithm is not guaranteed to find the 'right' parameter value
// in all possible cases, but it will always return at least some value so this function
// will never fail in the default implementation.
// XXX derive threshold from curve topology
const IfcFloat threshold = 1e-4f;
const unsigned int samples = 16;
static const IfcFloat threshold = 1e-4f;
static const unsigned int samples = 16;
const ParamRange& range = GetParametricRange();
paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
@ -632,9 +583,9 @@ bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
}
// ------------------------------------------------------------------------------------------------
void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
{
ai_assert(InRange(a) && InRange(b));
void Curve::SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const {
ai_assert( InRange( a ) );
ai_assert( InRange( b ) );
const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
out.verts.reserve( out.verts.size() + cnt + 1);
@ -646,16 +597,15 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
}
// ------------------------------------------------------------------------------------------------
bool BoundedCurve :: IsClosed() const
{
bool BoundedCurve::IsClosed() const {
return false;
}
// ------------------------------------------------------------------------------------------------
void BoundedCurve :: SampleDiscrete(TempMesh& out) const
{
void BoundedCurve::SampleDiscrete(TempMesh& out) const {
const ParamRange& range = GetParametricRange();
ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
return SampleDiscrete(out,range.first,range.second);
}

View File

@ -69,27 +69,23 @@ for(LineSplitter splitter(stream);splitter;++splitter) {
std::cout << "Current line is: " << splitter.get_index() << std::endl;
}
@endcode */
@endcode
*/
// ------------------------------------------------------------------------------------------------
class LineSplitter
{
class LineSplitter {
public:
typedef size_t line_idx;
public:
// -----------------------------------------
/** construct from existing stream reader
note: trim is *always* assumed true if skyp_empty_lines==true
*/
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
: idx( 0 )
, stream(stream)
, swallow()
, skip_empty_lines(skip_empty_lines)
, trim(trim)
{
: idx( 0 )
, stream(stream)
, swallow()
, skip_empty_lines(skip_empty_lines)
, trim(trim) {
cur.reserve(1024);
operator++();

View File

@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# else
#else
# define step_unordered_map map
# define step_unordered_multimap multimap
#endif

View File

@ -0,0 +1,93 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "ScaleProcess.h"
#include <assimp/scene.h>
namespace Assimp {
ScaleProcess::ScaleProcess()
: BaseProcess()
, mScale( 1.0f ) {
// empty
}
ScaleProcess::~ScaleProcess() {
// empty
}
void ScaleProcess::setScale( ai_real scale ) {
mScale = scale;
}
ai_real ScaleProcess::getScale() const {
return mScale;
}
bool ScaleProcess::IsActive( unsigned int pFlags ) const {
return true;
}
void ScaleProcess::SetupProperties( const Importer* pImp ) {
mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT );
}
void ScaleProcess::Execute( aiScene* pScene ) {
if ( nullptr == pScene ) {
return;
}
if ( nullptr == pScene->mRootNode ) {
return;
}
for ( unsigned int i = 0; i < pScene->mRootNode->mNumChildren; ++i ) {
aiNode *currentNode = pScene->mRootNode->mChildren[ i ];
if ( nullptr != currentNode ) {
applyScaling( currentNode );
}
}
}
void ScaleProcess::applyScaling( aiNode *currentNode ) {
currentNode->mTransformation = currentNode->mTransformation * mScale;
}
} // Namespace Assimp

View File

@ -0,0 +1,70 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#pragma once
#include "BaseProcess.h"
struct aiNode;
#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
#endif // !! AI_DEBONE_THRESHOLD
namespace Assimp {
class ScaleProcess : public BaseProcess {
public:
ScaleProcess();
virtual ~ScaleProcess();
void setScale( ai_real scale );
ai_real getScale() const;
virtual bool IsActive( unsigned int pFlags ) const;
virtual void SetupProperties( const Importer* pImp );
virtual void Execute( aiScene* pScene );
private:
void applyScaling( aiNode *currentNode );
private:
ai_real mScale;
};
} // Namespace Assimp

View File

@ -933,6 +933,14 @@ enum aiComponent
#define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT"
/**
* @brief Specifies a gobal key factor for scale, float value
*/
#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR"
#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT)
# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f
#endif // !! AI_DEBONE_THRESHOLD
// ---------- All the Build/Compile-time defines ------------