Fix references in cmake file.

This commit is contained in:
Kim Kulling
2019-06-09 18:43:56 +02:00
parent 57c46db042
commit 2d985b92c9
17 changed files with 365 additions and 361 deletions

View File

@@ -1,251 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
---------------------------------------------------------------------------
*/
/** @file ImporterRegistry.cpp
Central registry for all postprocessing steps available. Do not edit this file
directly (unless you are adding new steps), instead use the
corresponding preprocessor flag to selectively disable steps.
*/
#include "ProcessHelper.h"
#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
# include "CalcTangentsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
# include "JoinVerticesProcess.h"
#endif
#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
# include "ConvertToLHProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
# include "TriangulateProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_DROPFACENORMALS_PROCESS
# include "DropFaceNormalsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS
# include "GenFaceNormalsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS
# include "GenVertexNormalsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS
# include "RemoveVCProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS
# include "SplitLargeMeshes.h"
#endif
#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
# include "PretransformVertices.h"
#endif
#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
# include "LimitBoneWeightsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
# include "ValidateDataStructure.h"
#endif
#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS
# include "ImproveCacheLocality.h"
#endif
#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS
# include "FixNormalsStep.h"
#endif
#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS
# include "RemoveRedundantMaterials.h"
#endif
#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
# include "EmbedTexturesProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
# include "FindInvalidDataProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
# include "FindDegenerates.h"
#endif
#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS
# include "SortByPTypeProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
# include "ComputeUVMappingProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
# include "TextureTransform.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS
# include "FindInstancesProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
# include "OptimizeMeshes.h"
#endif
#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
# include "OptimizeGraph.h"
#endif
#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
# include "SplitByBoneCountProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
# include "DeboneProcess.h"
#endif
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
# include "ScaleProcess.h"
#endif
namespace Assimp {
// ------------------------------------------------------------------------------------------------
void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
{
// ----------------------------------------------------------------------------
// Add an instance of each post processing step here in the order
// of sequence it is executed. Steps that are added here are not
// validated - as RegisterPPStep() does - all dependencies must be given.
// ----------------------------------------------------------------------------
out.reserve(31);
#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
out.push_back( new MakeLeftHandedProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS)
out.push_back( new FlipUVsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
out.push_back( new FlipWindingOrderProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS)
out.push_back( new RemoveVCProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
out.push_back( new RemoveRedundantMatsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
out.push_back( new EmbedTexturesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS)
out.push_back( new FindInstancesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
out.push_back( new OptimizeGraphProcess());
#endif
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
out.push_back( new ComputeUVMappingProcess());
#endif
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
out.push_back( new TextureTransformStep());
#endif
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
out.push_back( new ScaleProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
out.push_back( new PretransformVertices());
#endif
#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
out.push_back( new TriangulateProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
//find degenerates should run after triangulation (to sort out small
//generated triangles) but before sort by p types (in case there are lines
//and points generated and inserted into a mesh)
out.push_back( new FindDegeneratesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
out.push_back( new SortByPTypeProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS)
out.push_back( new FindInvalidDataProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS)
out.push_back( new OptimizeMeshesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
out.push_back( new FixInfacingNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS)
out.push_back( new SplitByBoneCountProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
out.push_back( new SplitLargeMeshesProcess_Triangle());
#endif
#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
out.push_back( new DropFaceNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
out.push_back( new GenFaceNormalsProcess());
#endif
// .........................................................................
// DON'T change the order of these five ..
// XXX this is actually a design weakness that dates back to the time
// when Importer would maintain the postprocessing step list exclusively.
// Now that others access it too, we need a better solution.
out.push_back( new ComputeSpatialSortProcess());
// .........................................................................
#if (!defined ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS)
out.push_back( new GenVertexNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS)
out.push_back( new CalcTangentsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS)
out.push_back( new JoinVerticesProcess());
#endif
// .........................................................................
out.push_back( new DestroySpatialSortProcess());
// .........................................................................
#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
out.push_back( new SplitLargeMeshesProcess_Vertex());
#endif
#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
out.push_back( new DeboneProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
out.push_back( new LimitBoneWeightsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
out.push_back( new ImproveCacheLocalityProcess());
#endif
}
}

View File

@@ -1,113 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------
*/
/** @file RemoveComments.cpp
* @brief Defines the CommentRemover utility class
*/
#include <assimp/RemoveComments.h>
#include <assimp/ParsingUtils.h>
namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Remove line comments from a file
void CommentRemover::RemoveLineComments(const char* szComment,
char* szBuffer, char chReplacement /* = ' ' */)
{
// validate parameters
ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
const size_t len = strlen(szComment);
while (*szBuffer) {
// skip over quotes
if (*szBuffer == '\"' || *szBuffer == '\'')
while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
if (!strncmp(szBuffer,szComment,len)) {
while (!IsLineEnd(*szBuffer))
*szBuffer++ = chReplacement;
if (!*szBuffer) {
break;
}
}
++szBuffer;
}
}
// ------------------------------------------------------------------------------------------------
// Remove multi-line comments from a file
void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
const char* szCommentEnd,char* szBuffer,
char chReplacement)
{
// validate parameters
ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
NULL != szBuffer && *szCommentStart && *szCommentEnd);
const size_t len = strlen(szCommentEnd);
const size_t len2 = strlen(szCommentStart);
while (*szBuffer) {
// skip over quotes
if (*szBuffer == '\"' || *szBuffer == '\'')
while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
if (!strncmp(szBuffer,szCommentStart,len2)) {
while (*szBuffer) {
if (!::strncmp(szBuffer,szCommentEnd,len)) {
for (unsigned int i = 0; i < len;++i)
*szBuffer++ = chReplacement;
break;
}
*szBuffer++ = chReplacement;
}
continue;
}
++szBuffer;
}
}
} // !! Assimp

View File

@@ -1,168 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
---------------------------------------------------------------------------
*/
/** @file Implementation of the helper class to quickly find
vertices close to a given position. Special implementation for
the 3ds loader handling smooth groups correctly */
#include <assimp/SGSpatialSort.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
SGSpatialSort::SGSpatialSort()
{
// 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.Set( 0.8523f, 0.34321f, 0.5736f);
mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SGSpatialSort::~SGSpatialSort()
{
// nothing to do here, everything destructs automatically
}
// ------------------------------------------------------------------------------------------------
void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index,
unsigned int smoothingGroup)
{
// store position by index and distance
float distance = vPosition * mPlaneNormal;
mPositions.push_back( Entry( index, vPosition,
distance, smoothingGroup));
}
// ------------------------------------------------------------------------------------------------
void SGSpatialSort::Prepare()
{
// now sort the array ascending by distance.
std::sort( this->mPositions.begin(), this->mPositions.end());
}
// ------------------------------------------------------------------------------------------------
// Returns an iterator for all positions close to the given position.
void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
uint32_t pSG,
float pRadius,
std::vector<unsigned int>& poResults,
bool exactMatch /*= false*/) const
{
float dist = pPosition * mPlaneNormal;
float minDist = dist - pRadius, maxDist = dist + pRadius;
// clear the array
poResults.clear();
// quick check for positions outside the range
if( mPositions.empty() )
return;
if( maxDist < mPositions.front().mDistance)
return;
if( minDist > mPositions.back().mDistance)
return;
// 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)
{
if( mPositions[index].mDistance < minDist)
index += binaryStepSize;
else
index -= binaryStepSize;
binaryStepSize /= 2;
}
// depending on the direction of the last step we need to single step a bit back or forth
// to find the actual beginning element of the range
while( index > 0 && mPositions[index].mDistance > minDist)
index--;
while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
index++;
// Mow start iterating from there until the first position lays outside of the distance range.
// Add all positions inside the distance range within the given radius to the result aray
float squareEpsilon = pRadius * pRadius;
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
std::vector<Entry>::const_iterator end = mPositions.end();
if (exactMatch)
{
while( it->mDistance < maxDist)
{
if((it->mPosition - pPosition).SquareLength() < squareEpsilon && it->mSmoothGroups == pSG)
{
poResults.push_back( it->mIndex);
}
++it;
if( end == it )break;
}
}
else
{
// if the given smoothing group is 0, we'll return all surrounding vertices
if (!pSG)
{
while( it->mDistance < maxDist)
{
if((it->mPosition - pPosition).SquareLength() < squareEpsilon)
poResults.push_back( it->mIndex);
++it;
if( end == it)break;
}
}
else while( it->mDistance < maxDist)
{
if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
(it->mSmoothGroups & pSG || !it->mSmoothGroups))
{
poResults.push_back( it->mIndex);
}
++it;
if( end == it)break;
}
}
}

View File

@@ -1,261 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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 "ScenePreprocessor.h"
#include <assimp/ai_assert.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
// ---------------------------------------------------------------------------------------------
void ScenePreprocessor::ProcessScene ()
{
ai_assert(scene != NULL);
// Process all meshes
for (unsigned int i = 0; i < scene->mNumMeshes;++i)
ProcessMesh(scene->mMeshes[i]);
// - nothing to do for nodes for the moment
// - nothing to do for textures for the moment
// - nothing to do for lights for the moment
// - nothing to do for cameras for the moment
// Process all animations
for (unsigned int i = 0; i < scene->mNumAnimations;++i)
ProcessAnimation(scene->mAnimations[i]);
// Generate a default material if none was specified
if (!scene->mNumMaterials && scene->mNumMeshes) {
scene->mMaterials = new aiMaterial*[2];
aiMaterial* helper;
aiString name;
scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
aiColor3D clr(0.6f,0.6f,0.6f);
helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
// setup the default name to make this material identifiable
name.Set(AI_DEFAULT_MATERIAL_NAME);
helper->AddProperty(&name,AI_MATKEY_NAME);
ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
}
scene->mNumMaterials++;
}
}
// ---------------------------------------------------------------------------------------------
void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
{
// If aiMesh::mNumUVComponents is *not* set assign the default value of 2
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!mesh->mTextureCoords[i]) {
mesh->mNumUVComponents[i] = 0;
} else {
if (!mesh->mNumUVComponents[i])
mesh->mNumUVComponents[i] = 2;
aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
// Ensure unused components are zeroed. This will make 1D texture channels work
// as if they were 2D channels .. just in case an application doesn't handle
// this case
if (2 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p)
p->z = 0.f;
}
else if (1 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p)
p->z = p->y = 0.f;
}
else if (3 == mesh->mNumUVComponents[i]) {
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
for (; p != end; ++p) {
if (p->z != 0)
break;
}
if (p == end) {
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
mesh->mNumUVComponents[i] = 2;
}
}
}
}
// If the information which primitive types are there in the
// mesh is currently not available, compute it.
if (!mesh->mPrimitiveTypes) {
for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
aiFace& face = mesh->mFaces[a];
switch (face.mNumIndices)
{
case 3u:
mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
case 2u:
mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case 1u:
mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
default:
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
break;
}
}
}
// If tangents and normals are given but no bitangents compute them
if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) {
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
for (unsigned int i = 0; i < mesh->mNumVertices;++i) {
mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
}
}
}
// ---------------------------------------------------------------------------------------------
void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
{
double first = 10e10, last = -10e10;
for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* channel = anim->mChannels[i];
/* If the exact duration of the animation is not given
* compute it now.
*/
if (anim->mDuration == -1.) {
// Position keys
for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) {
aiVectorKey& key = channel->mPositionKeys[j];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Scaling keys
for (unsigned int j = 0; j < channel->mNumScalingKeys;++j ) {
aiVectorKey& key = channel->mScalingKeys[j];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
// Rotation keys
for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) {
aiQuatKey& key = channel->mRotationKeys[ j ];
first = std::min (first, key.mTime);
last = std::max (last, key.mTime);
}
}
/* Check whether the animation channel has no rotation
* or position tracks. In this case we generate a dummy
* track from the information we have in the transformation
* matrix of the corresponding node.
*/
if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) {
// Find the node that belongs to this animation
aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
if (node) // ValidateDS will complain later if 'node' is NULL
{
// Decompose the transformation matrix of the node
aiVector3D scaling, position;
aiQuaternion rotation;
node->mTransformation.Decompose(scaling, rotation,position);
// No rotation keys? Generate a dummy track
if (!channel->mNumRotationKeys) {
channel->mNumRotationKeys = 1;
channel->mRotationKeys = new aiQuatKey[1];
aiQuatKey& q = channel->mRotationKeys[0];
q.mTime = 0.;
q.mValue = rotation;
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
}
// No scaling keys? Generate a dummy track
if (!channel->mNumScalingKeys) {
channel->mNumScalingKeys = 1;
channel->mScalingKeys = new aiVectorKey[1];
aiVectorKey& q = channel->mScalingKeys[0];
q.mTime = 0.;
q.mValue = scaling;
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
}
// No position keys? Generate a dummy track
if (!channel->mNumPositionKeys) {
channel->mNumPositionKeys = 1;
channel->mPositionKeys = new aiVectorKey[1];
aiVectorKey& q = channel->mPositionKeys[0];
q.mTime = 0.;
q.mValue = position;
ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated");
}
}
}
}
if (anim->mDuration == -1.) {
ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration");
anim->mDuration = last - std::min( first, 0. );
}
}

View File

@@ -1,125 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------
*/
/** @file Defines a post processing step to search all meshes for
degenerated faces */
#ifndef AI_SCENE_PREPROCESSOR_H_INC
#define AI_SCENE_PREPROCESSOR_H_INC
#include <assimp/defs.h>
#include <stddef.h>
struct aiScene;
struct aiAnimation;
struct aiMesh;
class ScenePreprocessorTest;
namespace Assimp {
// ----------------------------------------------------------------------------------
/** ScenePreprocessor: Preprocess a scene before any post-processing
* steps are executed.
*
* The step computes data that needn't necessarily be provided by the
* importer, such as aiMesh::mPrimitiveTypes.
*/
// ----------------------------------------------------------------------------------
class ASSIMP_API ScenePreprocessor
{
// Make ourselves a friend of the corresponding test unit.
friend class ::ScenePreprocessorTest;
public:
// ----------------------------------------------------------------
/** Default c'tpr. Use SetScene() to assign a scene to the object.
*/
ScenePreprocessor()
: scene (NULL)
{}
/** Constructs the object and assigns a specific scene to it
*/
ScenePreprocessor(aiScene* _scene)
: scene (_scene)
{}
// ----------------------------------------------------------------
/** Assign a (new) scene to the object.
*
* One 'SceneProcessor' can be used for multiple scenes.
* Call ProcessScene to have the scene preprocessed.
* @param sc Scene to be processed.
*/
void SetScene (aiScene* sc) {
scene = sc;
}
// ----------------------------------------------------------------
/** Preprocess the current scene
*/
void ProcessScene ();
protected:
// ----------------------------------------------------------------
/** Preprocess an animation in the scene
* @param anim Anim to be preprocessed.
*/
void ProcessAnimation (aiAnimation* anim);
// ----------------------------------------------------------------
/** Preprocess a mesh in the scene
* @param mesh Mesh to be preprocessed.
*/
void ProcessMesh (aiMesh* mesh);
protected:
//! Scene we're currently working on
aiScene* scene;
};
} // ! end namespace Assimp
#endif // include guard

View File

@@ -1,342 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
---------------------------------------------------------------------------
*/
/** @file Implementation of the helper class to quickly find vertices close to a given position */
#include <assimp/SpatialSort.h>
#include <assimp/ai_assert.h>
using namespace Assimp;
// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
// ------------------------------------------------------------------------------------------------
// 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)
{
mPlaneNormal.Normalize();
Fill(pPositions,pNumPositions,pElementOffset);
}
// ------------------------------------------------------------------------------------------------
SpatialSort :: SpatialSort()
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SpatialSort::~SpatialSort()
{
// nothing to do here, everything destructs automatically
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
bool pFinalize /*= true */)
{
mPositions.clear();
Append(pPositions,pNumPositions,pElementOffset,pFinalize);
}
// ------------------------------------------------------------------------------------------------
void SpatialSort :: Finalize()
{
std::sort( mPositions.begin(), mPositions.end());
}
// ------------------------------------------------------------------------------------------------
void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
unsigned int pElementOffset,
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++)
{
const char* tempPointer = reinterpret_cast<const char*> (pPositions);
const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
// store position by index and distance
ai_real distance = *vec * mPlaneNormal;
mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
}
if (pFinalize) {
// now sort the array ascending by distance.
Finalize();
}
}
// ------------------------------------------------------------------------------------------------
// 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
{
const ai_real dist = pPosition * mPlaneNormal;
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
// clear the array
poResults.clear();
// quick check for positions outside the range
if( mPositions.size() == 0)
return;
if( maxDist < mPositions.front().mDistance)
return;
if( minDist > mPositions.back().mDistance)
return;
// 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)
{
if( mPositions[index].mDistance < minDist)
index += binaryStepSize;
else
index -= binaryStepSize;
binaryStepSize /= 2;
}
// depending on the direction of the last step we need to single step a bit back or forth
// to find the actual beginning element of the range
while( index > 0 && mPositions[index].mDistance > minDist)
index--;
while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
index++;
// Mow start iterating from there until the first position lays outside of the distance range.
// 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)
{
if( (it->mPosition - pPosition).SquareLength() < pSquared)
poResults.push_back( it->mIndex);
++it;
if( it == mPositions.end())
break;
}
// that's it
}
namespace {
// Binary, signed-integer representation of a single-precision floating-point value.
// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
// ordered the same way when their bits are reinterpreted as sign-magnitude integers."
// This allows us to convert all floating-point numbers to signed integers of arbitrary size
// and then use them to work with ULPs (Units in the Last Place, for high-precision
// computations) or to compare them (integer comparisons are faster than floating-point
// comparisons on many platforms).
typedef ai_int BinFloat;
// --------------------------------------------------------------------------------------------
// Converts the bit pattern of a floating-point number to its signed integer representation.
BinFloat ToBinary( const ai_real & pValue) {
// If this assertion fails, signed int is not big enough to store a float on your platform.
// Please correct the declaration of BinFloat a few lines above - but do it in a portable,
// #ifdef'd manner!
static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
#if defined( _MSC_VER)
// If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
// code has just become legacy code! Find out the current value of _MSC_VER and modify
// the #if above so it evaluates false on the current and all upcoming VC versions (or
// on the current platform, if LP64 or LLP64 are still used on other platforms).
static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
// This works best on Visual C++, but other compilers have their problems with it.
const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
#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.
union {
ai_real asFloat;
BinFloat asBin;
} conversion;
conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
conversion.asFloat = pValue;
const BinFloat binValue = conversion.asBin;
#endif
// floating-point numbers are of sign-magnitude format, so find out what signed number
// representation we must convert negative values to.
// See http://en.wikipedia.org/wiki/Signed_number_representations.
// Two's complement?
if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
// One's complement?
else if ( (-42 == ~42) && (binValue & 0x80000000))
return BinFloat(-0) - binValue;
// Sign-magnitude?
else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
return binValue;
else
return binValue;
}
} // 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
{
// 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.
// The best way to overcome this is the unit in the last place (ULP). A precision of 2 ULPs
// tells us that a float does not differ more than 2 bits from the "real" value. ULPs are of
// logarithmic precision - around 1, they are 1*(2^24) and around 10000, they are 0.00125.
// For standard C math, we can assume a precision of 0.5 ULPs according to IEEE 754. The
// incoming vertex positions might have already been transformed, probably using rather
// inaccurate SSE instructions, so we assume a tolerance of 4 ULPs to safely identify
// identical vertex positions.
static const int toleranceInULPs = 4;
// An interesting point is that the inaccuracy grows linear with the number of operations:
// multiplying to numbers, each inaccurate to four ULPs, results in an inaccuracy of four ULPs
// plus 0.5 ULPs for the multiplication.
// To compute the distance to the plane, a dot product is needed - that is a multiplication and
// an addition on each number.
static const int distanceToleranceInULPs = toleranceInULPs + 1;
// The squared distance between two 3D vectors is computed the same way, but with an additional
// subtraction.
static const int distance3DToleranceInULPs = distanceToleranceInULPs + 1;
// Convert the plane distance to its signed integer representation so the ULPs tolerance can be
// applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
// clear the array in this strange fashion because a simple clear() would also deallocate
// the array which we want to avoid
poResults.resize( 0 );
// 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)
{
// Ugly, but conditional jumps are faster with integers than with floats
if( minDistBinary > ToBinary(mPositions[index].mDistance))
index += binaryStepSize;
else
index -= binaryStepSize;
binaryStepSize /= 2;
}
// depending on the direction of the last step we need to single step a bit back or forth
// to find the actual beginning element of the range
while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
index--;
while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
index++;
// 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)
{
if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
poResults.push_back(it->mIndex);
++it;
if( it == mPositions.end())
break;
}
// that's it
}
// ------------------------------------------------------------------------------------------------
unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
{
fill.resize(mPositions.size(),UINT_MAX);
ai_real dist, maxDist;
unsigned int t=0;
const ai_real pSquared = pRadius*pRadius;
for (size_t i = 0; i < mPositions.size();) {
dist = mPositions[i].mPosition * mPlaneNormal;
maxDist = dist + pRadius;
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)
{
fill[mPositions[i].mIndex] = t;
}
++t;
}
#ifdef ASSIMP_BUILD_DEBUG
// debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
for (size_t i = 0; i < fill.size(); ++i) {
ai_assert(fill[i]<mPositions.size());
}
#endif
return t;
}

View File

@@ -1,407 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------
*/
/// @file SplitByBoneCountProcess.cpp
/// Implementation of the SplitByBoneCount postprocessing step
// internal headers of the post-processing framework
#include "SplitByBoneCountProcess.h"
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
#include <limits>
#include <assimp/TinyFormatter.h>
using namespace Assimp;
using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Constructor
SplitByBoneCountProcess::SplitByBoneCountProcess()
{
// set default, might be overridden by importer config
mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
}
// ------------------------------------------------------------------------------------------------
// Destructor
SplitByBoneCountProcess::~SplitByBoneCountProcess()
{
// nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag.
bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const
{
return !!(pFlags & aiProcess_SplitByBoneCount);
}
// ------------------------------------------------------------------------------------------------
// Updates internal properties
void SplitByBoneCountProcess::SetupProperties(const Importer* pImp)
{
mMaxBoneCount = pImp->GetPropertyInteger(AI_CONFIG_PP_SBBC_MAX_BONES,AI_SBBC_DEFAULT_MAX_BONES);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitByBoneCountProcess::Execute( aiScene* pScene)
{
ASSIMP_LOG_DEBUG("SplitByBoneCountProcess begin");
// early out
bool isNecessary = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
isNecessary = true;
if( !isNecessary )
{
ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." );
return;
}
// we need to do something. Let's go.
mSubMeshIndices.clear();
mSubMeshIndices.resize( pScene->mNumMeshes);
// build a new array of meshes for the scene
std::vector<aiMesh*> meshes;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
{
aiMesh* srcMesh = pScene->mMeshes[a];
std::vector<aiMesh*> newMeshes;
SplitMesh( pScene->mMeshes[a], newMeshes);
// mesh was split
if( !newMeshes.empty() )
{
// store new meshes and indices of the new meshes
for( unsigned int b = 0; b < newMeshes.size(); ++b)
{
mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
meshes.push_back( newMeshes[b]);
}
// and destroy the source mesh. It should be completely contained inside the new submeshes
delete srcMesh;
}
else
{
// Mesh is kept unchanged - store it's new place in the mesh array
mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
meshes.push_back( srcMesh);
}
}
// rebuild the scene's mesh array
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
delete [] pScene->mMeshes;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
// recurse through all nodes and translate the node's mesh indices to fit the new mesh array
UpdateNode( pScene->mRootNode);
ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." );
}
// ------------------------------------------------------------------------------------------------
// Splits the given mesh by bone count.
void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const
{
// skip if not necessary
if( pMesh->mNumBones <= mMaxBoneCount )
return;
// necessary optimisation: build a list of all affecting bones for each vertex
// TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
typedef std::pair<unsigned int, float> BoneWeight;
std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
for( unsigned int a = 0; a < pMesh->mNumBones; ++a)
{
const aiBone* bone = pMesh->mBones[a];
for( unsigned int b = 0; b < bone->mNumWeights; ++b)
vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
}
unsigned int numFacesHandled = 0;
std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
while( numFacesHandled < pMesh->mNumFaces )
{
// which bones are used in the current submesh
unsigned int numBones = 0;
std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
// indices of the faces which are going to go into this submesh
std::vector<unsigned int> subMeshFaces;
subMeshFaces.reserve( pMesh->mNumFaces);
// accumulated vertex count of all the faces in this submesh
unsigned int numSubMeshVertices = 0;
// a small local array of new bones for the current face. State of all used bones for that face
// can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
std::vector<unsigned int> newBonesAtCurrentFace;
// add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
{
// skip if the face is already stored in a submesh
if( isFaceHandled[a] )
continue;
const aiFace& face = pMesh->mFaces[a];
// check every vertex if its bones would still fit into the current submesh
for( unsigned int b = 0; b < face.mNumIndices; ++b )
{
const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
for( unsigned int c = 0; c < vb.size(); ++c)
{
unsigned int boneIndex = vb[c].first;
// if the bone is already used in this submesh, it's ok
if( isBoneUsed[boneIndex] )
continue;
// if it's not used, yet, we would need to add it. Store its bone index
if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
newBonesAtCurrentFace.push_back( boneIndex);
}
}
// leave out the face if the new bones required for this face don't fit the bone count limit anymore
if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
continue;
// mark all new bones as necessary
while( !newBonesAtCurrentFace.empty() )
{
unsigned int newIndex = newBonesAtCurrentFace.back();
newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
if( isBoneUsed[newIndex] )
continue;
isBoneUsed[newIndex] = true;
numBones++;
}
// store the face index and the vertex count
subMeshFaces.push_back( a);
numSubMeshVertices += face.mNumIndices;
// remember that this face is handled
isFaceHandled[a] = true;
numFacesHandled++;
}
// create a new mesh to hold this subset of the source mesh
aiMesh* newMesh = new aiMesh;
if( pMesh->mName.length > 0 )
newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
newMesh->mMaterialIndex = pMesh->mMaterialIndex;
newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
poNewMeshes.push_back( newMesh);
// create all the arrays for this mesh if the old mesh contained them
newMesh->mNumVertices = numSubMeshVertices;
newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
if( pMesh->HasNormals() )
newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
if( pMesh->HasTangentsAndBitangents() )
{
newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
newMesh->mBitangents = new aiVector3D[newMesh->mNumVertices];
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
{
if( pMesh->HasTextureCoords( a) )
newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
{
if( pMesh->HasVertexColors( a) )
newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
}
// and copy over the data, generating faces with linear indices along the way
newMesh->mFaces = new aiFace[subMeshFaces.size()];
unsigned int nvi = 0; // next vertex index
std::vector<unsigned int> previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
for( unsigned int a = 0; a < subMeshFaces.size(); ++a )
{
const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
aiFace& dstFace = newMesh->mFaces[a];
dstFace.mNumIndices = srcFace.mNumIndices;
dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
// accumulate linearly all the vertices of the source face
for( unsigned int b = 0; b < dstFace.mNumIndices; ++b )
{
unsigned int srcIndex = srcFace.mIndices[b];
dstFace.mIndices[b] = nvi;
previousVertexIndices[nvi] = srcIndex;
newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
if( pMesh->HasNormals() )
newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
if( pMesh->HasTangentsAndBitangents() )
{
newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
newMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
}
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
{
if( pMesh->HasTextureCoords( c) )
newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
}
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
{
if( pMesh->HasVertexColors( c) )
newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
}
nvi++;
}
}
ai_assert( nvi == numSubMeshVertices );
// Create the bones for the new submesh: first create the bone array
newMesh->mNumBones = 0;
newMesh->mBones = new aiBone*[numBones];
std::vector<unsigned int> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<unsigned int>::max());
for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
{
if( !isBoneUsed[a] )
continue;
// create the new bone
const aiBone* srcBone = pMesh->mBones[a];
aiBone* dstBone = new aiBone;
mappedBoneIndex[a] = newMesh->mNumBones;
newMesh->mBones[newMesh->mNumBones++] = dstBone;
dstBone->mName = srcBone->mName;
dstBone->mOffsetMatrix = srcBone->mOffsetMatrix;
dstBone->mNumWeights = 0;
}
ai_assert( newMesh->mNumBones == numBones );
// iterate over all new vertices and count which bones affected its old vertex in the source mesh
for( unsigned int a = 0; a < numSubMeshVertices; ++a )
{
unsigned int oldIndex = previousVertexIndices[a];
const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b )
{
unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
newMesh->mBones[newBoneIndex]->mNumWeights++;
}
}
// allocate all bone weight arrays accordingly
for( unsigned int a = 0; a < newMesh->mNumBones; ++a )
{
aiBone* bone = newMesh->mBones[a];
ai_assert( bone->mNumWeights > 0 );
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
bone->mNumWeights = 0; // for counting up in the next step
}
// now copy all the bone vertex weights for all the vertices which made it into the new submesh
for( unsigned int a = 0; a < numSubMeshVertices; ++a)
{
// find the source vertex for it in the source mesh
unsigned int previousIndex = previousVertexIndices[a];
// these bones were affecting it
const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[previousIndex];
// all of the bones affecting it should be present in the new submesh, or else
// the face it comprises shouldn't be present
for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b)
{
unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
ai_assert( newBoneIndex != std::numeric_limits<unsigned int>::max() );
aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
newMesh->mBones[newBoneIndex]->mNumWeights++;
dstWeight->mVertexId = a;
dstWeight->mWeight = bonesOnThisVertex[b].second;
}
}
// I have the strange feeling that this will break apart at some point in time...
}
}
// ------------------------------------------------------------------------------------------------
// Recursively updates the node's mesh list to account for the changed mesh list
void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
{
// rebuild the node's mesh index list
if( pNode->mNumMeshes > 0 )
{
std::vector<unsigned int> newMeshList;
for( unsigned int a = 0; a < pNode->mNumMeshes; ++a)
{
unsigned int srcIndex = pNode->mMeshes[a];
const std::vector<unsigned int>& replaceMeshes = mSubMeshIndices[srcIndex];
newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
}
delete [] pNode->mMeshes;
pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
}
// do that also recursively for all children
for( unsigned int a = 0; a < pNode->mNumChildren; ++a )
{
UpdateNode( pNode->mChildren[a]);
}
}

View File

@@ -1,111 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------
*/
/// @file SplitByBoneCountProcess.h
/// Defines a post processing step to split meshes with many bones into submeshes
#ifndef AI_SPLITBYBONECOUNTPROCESS_H_INC
#define AI_SPLITBYBONECOUNTPROCESS_H_INC
#include <vector>
#include "BaseProcess.h"
#include <assimp/mesh.h>
#include <assimp/scene.h>
namespace Assimp
{
/** Postprocessing filter to split meshes with many bones into submeshes
* so that each submesh has a certain max bone count.
*
* Applied BEFORE the JoinVertices-Step occurs.
* Returns NON-UNIQUE vertices, splits by bone count.
*/
class SplitByBoneCountProcess : public BaseProcess
{
public:
SplitByBoneCountProcess();
~SplitByBoneCountProcess();
public:
/** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. A
* bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields,
* false if not.
*/
bool IsActive( unsigned int pFlags) const;
/** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
*/
virtual void SetupProperties(const Importer* pImp);
protected:
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
/// Splits the given mesh by bone count.
/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
void SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const;
/// Recursively updates the node's mesh list to account for the changed mesh list
void UpdateNode( aiNode* pNode) const;
public:
/// Max bone count. Splitting occurs if a mesh has more than that number of bones.
size_t mMaxBoneCount;
/// Per mesh index: Array of indices of the new submeshes.
std::vector< std::vector<unsigned int> > mSubMeshIndices;
};
} // end of namespace Assimp
#endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC

View File

@@ -1,134 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
---------------------------------------------------------------------------
*/
/** @file Implementation of the VertexTriangleAdjacency helper class
*/
// internal headers
#include "VertexTriangleAdjacency.h"
#include <assimp/mesh.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
unsigned int iNumFaces,
unsigned int iNumVertices /*= 0*/,
bool bComputeNumTriangles /*= false*/)
{
// compute the number of referenced vertices if it wasn't specified by the caller
const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
if (!iNumVertices) {
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
ai_assert( nullptr != pcFace );
ai_assert(3 == pcFace->mNumIndices);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
}
}
mNumVertices = iNumVertices;
unsigned int* pi;
// allocate storage
if (bComputeNumTriangles) {
pi = mLiveTriangles = new unsigned int[iNumVertices+1];
::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
mOffsetTable = new unsigned int[iNumVertices+2]+1;
} else {
pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
mLiveTriangles = NULL; // important, otherwise the d'tor would crash
}
// get a pointer to the end of the buffer
unsigned int* piEnd = pi+iNumVertices;
*piEnd++ = 0u;
// first pass: compute the number of faces referencing each vertex
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
{
unsigned nind = pcFace->mNumIndices;
unsigned * ind = pcFace->mIndices;
if (nind > 0) pi[ind[0]]++;
if (nind > 1) pi[ind[1]]++;
if (nind > 2) pi[ind[2]]++;
}
// second pass: compute the final offset table
unsigned int iSum = 0;
unsigned int* piCurOut = this->mOffsetTable;
for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) {
unsigned int iLastSum = iSum;
iSum += *piCur;
*piCurOut = iLastSum;
}
pi = this->mOffsetTable;
// third pass: compute the final table
this->mAdjacencyTable = new unsigned int[iSum];
iSum = 0;
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) {
unsigned nind = pcFace->mNumIndices;
unsigned * ind = pcFace->mIndices;
if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum;
if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum;
if (nind > 2) mAdjacencyTable[pi[ind[2]]++] = iSum;
}
// fourth pass: undo the offset computations made during the third pass
// We could do this in a separate buffer, but this would be TIMES slower.
--mOffsetTable;
*mOffsetTable = 0u;
}
// ------------------------------------------------------------------------------------------------
VertexTriangleAdjacency::~VertexTriangleAdjacency()
{
// delete allocated storage
delete[] mOffsetTable;
delete[] mAdjacencyTable;
delete[] mLiveTriangles;
}

View File

@@ -1,117 +0,0 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------
*/
/** @file Defines a helper class to compute a vertex-triangle adjacency map */
#ifndef AI_VTADJACENCY_H_INC
#define AI_VTADJACENCY_H_INC
#include "BaseProcess.h"
#include <assimp/types.h>
#include <assimp/ai_assert.h>
struct aiMesh;
struct aiFace;
namespace Assimp {
// --------------------------------------------------------------------------------------------
/** @brief The VertexTriangleAdjacency class computes a vertex-triangle
* adjacency map from a given index buffer.
*
* @note Although it is called #VertexTriangleAdjacency, the current version does also
* support arbitrary polygons. */
// --------------------------------------------------------------------------------------------
class ASSIMP_API VertexTriangleAdjacency {
public:
// ----------------------------------------------------------------------------
/** @brief Construction from an existing index buffer
* @param pcFaces Index buffer
* @param iNumFaces Number of faces in the buffer
* @param iNumVertices Number of referenced vertices. This value
* is computed automatically if 0 is specified.
* @param bComputeNumTriangles If you want the class to compute
* a list containing the number of referenced triangles per vertex
* per vertex - pass true. */
VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces,
unsigned int iNumVertices = 0,
bool bComputeNumTriangles = true);
// ----------------------------------------------------------------------------
/** @brief Destructor */
~VertexTriangleAdjacency();
// ----------------------------------------------------------------------------
/** @brief Get all triangles adjacent to a vertex
* @param iVertIndex Index of the vertex
* @return A pointer to the adjacency list. */
unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const {
ai_assert(iVertIndex < mNumVertices);
return &mAdjacencyTable[ mOffsetTable[iVertIndex]];
}
// ----------------------------------------------------------------------------
/** @brief Get the number of triangles that are referenced by
* a vertex. This function returns a reference that can be modified
* @param iVertIndex Index of the vertex
* @return Number of referenced triangles */
unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) {
ai_assert( iVertIndex < mNumVertices );
ai_assert( nullptr != mLiveTriangles );
return mLiveTriangles[iVertIndex];
}
//! Offset table
unsigned int* mOffsetTable;
//! Adjacency table
unsigned int* mAdjacencyTable;
//! Table containing the number of referenced triangles per vertex
unsigned int* mLiveTriangles;
//! Debug: Number of referenced vertices
unsigned int mNumVertices;
};
} //! ns Assimp
#endif // !! AI_VTADJACENCY_H_INC