Merge pull request #3167 from assimp/iisue_3165

Iisue 3165
pull/3168/head
Kim Kulling 2020-04-26 19:38:31 +02:00 committed by GitHub
commit 2273160f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 286 additions and 1476 deletions

View File

@ -994,8 +994,7 @@ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
} else {
*_dest = new aiScene();
}
::memcpy(*_dest,src,sizeof(aiScene));
CopyScene(_dest, src, false);
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -53,62 +51,51 @@ using namespace Assimp;
#define CHAR_BIT 8
#endif
#ifdef _WIN32
# pragma warning(disable : 4127)
#endif // _WIN32
const aiVector3D PlaneInit(0.8523f, 0.34321f, 0.5736f);
// ------------------------------------------------------------------------------------------------
// Constructs a spatially sorted representation from the given position array.
SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset)
// define the reference plane. We choose some arbitrary vector away from all basic axises
// in the hope that no model spreads all its vertices along this plane.
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
SpatialSort::SpatialSort(const aiVector3D *pPositions, unsigned int pNumPositions, unsigned int pElementOffset) :
mPlaneNormal(PlaneInit) {
mPlaneNormal.Normalize();
Fill(pPositions, pNumPositions, pElementOffset);
}
// ------------------------------------------------------------------------------------------------
SpatialSort :: SpatialSort()
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
SpatialSort::SpatialSort() :
mPlaneNormal(PlaneInit) {
mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SpatialSort::~SpatialSort()
{
// nothing to do here, everything destructs automatically
SpatialSort::~SpatialSort() {
// empty
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */)
{
bool pFinalize /*= true */) {
mPositions.clear();
Append(pPositions, pNumPositions, pElementOffset, pFinalize);
}
// ------------------------------------------------------------------------------------------------
void SpatialSort :: Finalize()
{
void SpatialSort::Finalize() {
std::sort(mPositions.begin(), mPositions.end());
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Append(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */)
{
bool pFinalize /*= true */) {
// store references to all given positions along with their distance to the reference plane
const size_t initial = mPositions.size();
mPositions.reserve(initial + (pFinalize ? pNumPositions : pNumPositions * 2));
for( unsigned int a = 0; a < pNumPositions; a++)
{
for (unsigned int a = 0; a < pNumPositions; a++) {
const char *tempPointer = reinterpret_cast<const char *>(pPositions);
const aiVector3D *vec = reinterpret_cast<const aiVector3D *>(tempPointer + a * pElementOffset);
@ -126,8 +113,7 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
// ------------------------------------------------------------------------------------------------
// Returns an iterator for all positions close to the given position.
void SpatialSort::FindPositions(const aiVector3D &pPosition,
ai_real pRadius, std::vector<unsigned int>& poResults) const
{
ai_real pRadius, std::vector<unsigned int> &poResults) const {
const ai_real dist = pPosition * mPlaneNormal;
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
@ -145,8 +131,7 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
// do a binary search for the minimal distance to start the iteration there
unsigned int index = (unsigned int)mPositions.size() / 2;
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
while( binaryStepSize > 1)
{
while (binaryStepSize > 1) {
if (mPositions[index].mDistance < minDist)
index += binaryStepSize;
else
@ -166,8 +151,7 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
// Add all positions inside the distance range within the given radius to the result aray
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
const ai_real pSquared = pRadius * pRadius;
while( it->mDistance < maxDist)
{
while (it->mDistance < maxDist) {
if ((it->mPosition - pPosition).SquareLength() < pSquared)
poResults.push_back(it->mIndex);
++it;
@ -207,6 +191,8 @@ namespace {
// This works best on Visual C++, but other compilers have their problems with it.
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
//::memcpy(&binValue, &pValue, sizeof(pValue));
//return binValue;
#else
// On many compilers, reinterpreting a float address as an integer causes aliasing
// problems. This is an ugly but more or less safe way of doing it.
@ -224,13 +210,17 @@ namespace {
// See http://en.wikipedia.org/wiki/Signed_number_representations.
// Two's complement?
if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000));
bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000));
bool SignedMagnitude = ((-42 == (42 | (-0))) && (binValue & 0x80000000));
if (DefaultValue)
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
// One's complement?
else if ( (-42 == ~42) && (binValue & 0x80000000))
else if (OneComplement)
return BinFloat(-0) - binValue;
// Sign-magnitude?
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
else if (SignedMagnitude) // -0 = 1000... binary
return binValue;
else
return binValue;
@ -241,9 +231,7 @@ namespace {
// ------------------------------------------------------------------------------------------------
// Fills an array with indices of all positions identical to the given position. In opposite to
// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
std::vector<unsigned int>& poResults) const
{
void SpatialSort::FindIdenticalPositions(const aiVector3D &pPosition, std::vector<unsigned int> &poResults) const {
// Epsilons have a huge disadvantage: they are of constant precision, while floating-point
// values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
// if you apply it to 0.001, it is enormous.
@ -279,8 +267,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// do a binary search for the minimal distance to start the iteration there
unsigned int index = (unsigned int)mPositions.size() / 2;
unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
while( binaryStepSize > 1)
{
while (binaryStepSize > 1) {
// Ugly, but conditional jumps are faster with integers than with floats
if (minDistBinary > ToBinary(mPositions[index].mDistance))
index += binaryStepSize;
@ -300,8 +287,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
// Now start iterating from there until the first position lays outside of the distance range.
// Add all positions inside the distance range within the tolerance to the result array
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
while( ToBinary(it->mDistance) < maxDistBinary)
{
while (ToBinary(it->mDistance) < maxDistBinary) {
if (distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
poResults.push_back(it->mIndex);
++it;
@ -313,8 +299,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
}
// ------------------------------------------------------------------------------------------------
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
{
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int> &fill, ai_real pRadius) const {
fill.resize(mPositions.size(), UINT_MAX);
ai_real dist, maxDist;
@ -326,9 +311,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,
fill[mPositions[i].mIndex] = t;
const aiVector3D &oldpos = mPositions[i].mPosition;
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
&& (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
{
for (++i; i < fill.size() && mPositions[i].mDistance < maxDist && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i) {
fill[mPositions[i].mIndex] = t;
}
++t;

View File

@ -49,8 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma GCC system_header
#endif
#include <vector>
#include <assimp/types.h>
#include <vector>
namespace Assimp {
@ -62,10 +62,8 @@ namespace Assimp {
* time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen
* so that it avoids common planes in usual data sets. */
// ------------------------------------------------------------------------------------------------
class ASSIMP_API SpatialSort
{
class ASSIMP_API SpatialSort {
public:
SpatialSort();
// ------------------------------------------------------------------------------------
@ -82,8 +80,6 @@ public:
/** Destructor */
~SpatialSort();
public:
// ------------------------------------------------------------------------------------
/** Sets the input data for the SpatialSort. This replaces existing data, if any.
* The new data receives new indices in ascending order.
@ -101,14 +97,12 @@ public:
unsigned int pElementOffset,
bool pFinalize = true);
// ------------------------------------------------------------------------------------
/** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
void Append(const aiVector3D *pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize = true);
// ------------------------------------------------------------------------------------
/** Finalize the spatial hash data structure. This can be useful after
* multiple calls to #Append() with the pFinalize parameter set to false.
@ -159,11 +153,13 @@ protected:
ai_real mDistance; ///< Distance of this vertex to the sorting plane
Entry() AI_NO_EXCEPT
: mIndex( 999999999 ), mPosition(), mDistance( 99999. ) {
: mIndex(999999999),
mPosition(),
mDistance(99999.) {
// empty
}
Entry( unsigned int pIndex, const aiVector3D& pPosition, ai_real pDistance)
: mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) {
Entry(unsigned int pIndex, const aiVector3D &pPosition, ai_real pDistance) :
mIndex(pIndex), mPosition(pPosition), mDistance(pDistance) {
// empty
}

View File

@ -86,6 +86,7 @@ SET( COMMON
unit/utStringUtils.cpp
unit/Common/uiScene.cpp
unit/Common/utLineSplitter.cpp
unit/Common/utSpatialSort.cpp
)
SET( IMPORTERS

View File

@ -0,0 +1,84 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
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 "UnitTestPCH.h"
#include <assimp/SpatialSort.h>
using namespace Assimp;
class utSpatialSort : public ::testing::Test {
public
:
aiVector3D *vecs;
protected:
void SetUp() override {
::srand(static_cast<unsigned>(time(0)));
vecs = new aiVector3D[100];
for (size_t i = 0; i < 100; ++i) {
vecs[i].x = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
vecs[i].y = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
vecs[i].z = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
}
}
void TearDown() override {
delete[] vecs;
}
};
TEST_F( utSpatialSort, findIdenticalsTest ) {
SpatialSort sSort;
sSort.Fill(vecs, 100, sizeof(aiVector3D));
std::vector<unsigned int> indices;
sSort.FindIdenticalPositions(vecs[0], indices);
EXPECT_EQ(1u, indices.size());
}
TEST_F(utSpatialSort, findPositionsTest) {
SpatialSort sSort;
sSort.Fill(vecs, 100, sizeof(aiVector3D));
std::vector<unsigned int> indices;
sSort.FindPositions(vecs[0], 0.01f, indices);
EXPECT_EQ(1u, indices.size());
}

File diff suppressed because it is too large Load Diff

View File

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