Add GLOB_MEASURE_TIME configuration option to profile the runtime of the postprocessing steps.

Start new documentation page for Performance/Profiling questions.
Migrate existing notes on multithreading to a new doc page, add more details.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@772 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2010-07-08 22:44:44 +00:00
parent 7f2f5e7555
commit aae8637666
10 changed files with 403 additions and 44 deletions

View File

@ -0,0 +1,72 @@
// boost timer.hpp header file ---------------------------------------------//
// Copyright Beman Dawes 1994-99. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/timer for documentation.
// Revision History
// 01 Apr 01 Modified to use new <boost/limits.hpp> header. (JMaddock)
// 12 Jan 01 Change to inline implementation to allow use without library
// builds. See docs for more rationale. (Beman Dawes)
// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock)
// 16 Jul 99 Second beta
// 6 Jul 99 Initial boost version
#ifndef BOOST_TIMER_HPP
#define BOOST_TIMER_HPP
//#include <boost/config.hpp>
#include <ctime>
//#include <boost/limits.hpp>
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::clock_t; using ::clock; }
# endif
namespace boost {
// timer -------------------------------------------------------------------//
// A timer object measures elapsed time.
// It is recommended that implementations measure wall clock rather than CPU
// time since the intended use is performance measurement on systems where
// total elapsed time is more important than just process or CPU time.
// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours
// due to implementation limitations. The accuracy of timings depends on the
// accuracy of timing information provided by the underlying platform, and
// this varies a great deal from platform to platform.
class timer
{
public:
timer() { _start_time = std::clock(); } // postcondition: elapsed()==0
// timer( const timer& src ); // post: elapsed()==src.elapsed()
// ~timer(){}
// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed()
void restart() { _start_time = std::clock(); } // post: elapsed()==0
double elapsed() const // return elapsed time in seconds
{ return double(std::clock() - _start_time) / CLOCKS_PER_SEC; }
double elapsed_max() const // return estimated maximum value for elapsed()
// Portability warning: elapsed_max() may return too high a value on systems
// where std::clock_t overflows or resets at surprising values.
{
return (double((std::numeric_limits<std::clock_t>::max)())
- double(_start_time)) / double(CLOCKS_PER_SEC);
}
double elapsed_min() const // return minimum value for elapsed()
{ return double(1)/double(CLOCKS_PER_SEC); }
private:
std::clock_t _start_time;
}; // timer
} // namespace boost
#endif // BOOST_TIMER_HPP

View File

@ -141,6 +141,7 @@ SOURCE_GROUP( Common FILES
Vertex.h Vertex.h
LineSplitter.h LineSplitter.h
TinyFormatter.h TinyFormatter.h
Profiler.h
) )
SOURCE_GROUP( 3DS FILES SOURCE_GROUP( 3DS FILES
@ -720,6 +721,7 @@ ADD_LIBRARY( assimp SHARED
BlenderIntermediate.h BlenderIntermediate.h
BlenderModifier.h BlenderModifier.h
BlenderModifier.cpp BlenderModifier.cpp
Profiler.h
# Necessary to show the headers in the project when using the VC++ generator: # Necessary to show the headers in the project when using the VC++ generator:
BoostWorkaround/boost/math/common_factor_rt.hpp BoostWorkaround/boost/math/common_factor_rt.hpp

View File

@ -67,6 +67,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ProcessHelper.h" #include "ProcessHelper.h"
#include "ScenePreprocessor.h" #include "ScenePreprocessor.h"
#include "MemoryIOWrapper.h" #include "MemoryIOWrapper.h"
#include "Profiler.h"
using namespace Assimp::Profiling;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importers // Importers
@ -837,20 +840,25 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
{ {
// Check whether this Importer instance has already loaded // Check whether this Importer instance has already loaded
// a scene. In this case we need to delete the old one // a scene. In this case we need to delete the old one
if (pimpl->mScene) if (pimpl->mScene) {
{
DefaultLogger::get()->debug("Deleting previous scene"); DefaultLogger::get()->debug("(Deleting previous scene)");
FreeScene(); FreeScene();
} }
// First check if the file is accessable at all // First check if the file is accessable at all
if( !pimpl->mIOHandler->Exists( pFile)) if( !pimpl->mIOHandler->Exists( pFile)) {
{
pimpl->mErrorString = "Unable to open file \"" + pFile + "\"."; pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
DefaultLogger::get()->error(pimpl->mErrorString); DefaultLogger::get()->error(pimpl->mErrorString);
return NULL; return NULL;
} }
boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
if (profiler) {
profiler->BeginRegion("total");
}
// Find an worker class which can handle the file // Find an worker class which can handle the file
BaseImporter* imp = NULL; BaseImporter* imp = NULL;
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
@ -861,10 +869,9 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
} }
} }
if (!imp) if (!imp) {
{
// not so bad yet ... try format auto detection. // not so bad yet ... try format auto detection.
std::string::size_type s = pFile.find_last_of('.'); const std::string::size_type s = pFile.find_last_of('.');
if (s != std::string::npos) { if (s != std::string::npos) {
DefaultLogger::get()->info("File extension now known, trying signature-based detection"); DefaultLogger::get()->info("File extension now known, trying signature-based detection");
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
@ -885,9 +892,18 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// Dispatch the reading to the worker class for this format // Dispatch the reading to the worker class for this format
DefaultLogger::get()->info("Found a matching importer for this file format"); DefaultLogger::get()->info("Found a matching importer for this file format");
if (profiler) {
profiler->BeginRegion("import");
}
imp->SetupProperties( this ); imp->SetupProperties( this );
pimpl->mScene = imp->ReadFile( pFile, pimpl->mIOHandler); pimpl->mScene = imp->ReadFile( pFile, pimpl->mIOHandler);
if (profiler) {
profiler->EndRegion("import");
}
// If successful, apply all active post processing steps to the imported data // If successful, apply all active post processing steps to the imported data
if( pimpl->mScene) { if( pimpl->mScene) {
@ -904,9 +920,17 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
#endif // no validation #endif // no validation
// Preprocess the scene and prepare it for post-processing // Preprocess the scene and prepare it for post-processing
if (profiler) {
profiler->BeginRegion("preprocess");
}
ScenePreprocessor pre(pimpl->mScene); ScenePreprocessor pre(pimpl->mScene);
pre.ProcessScene(); pre.ProcessScene();
if (profiler) {
profiler->EndRegion("preprocess");
}
// Ensure that the validation process won't be called twice // Ensure that the validation process won't be called twice
ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure)); ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
} }
@ -917,6 +941,10 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// clear any data allocated by post-process steps // clear any data allocated by post-process steps
pimpl->mPPShared->Clean(); pimpl->mPPShared->Clean();
if (profiler) {
profiler->EndRegion("total");
}
} }
#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
catch (std::exception &e) catch (std::exception &e)
@ -979,16 +1007,27 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
pFlags |= aiProcess_ValidateDataStructure; pFlags |= aiProcess_ValidateDataStructure;
} }
#else #else
if (pimpl->bExtraVerbose) if (pimpl->bExtraVerbose) {
DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting"); DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
}
#endif // ! DEBUG #endif // ! DEBUG
boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* process = pimpl->mPostProcessingSteps[a]; BaseProcess* process = pimpl->mPostProcessingSteps[a];
if( process->IsActive( pFlags)) { if( process->IsActive( pFlags)) {
if (profiler) {
profiler->BeginRegion("postprocess");
}
process->SetupProperties( this ); process->SetupProperties( this );
process->ExecuteOnScene ( this ); process->ExecuteOnScene ( this );
if (profiler) {
profiler->EndRegion("postprocess");
}
} }
if( !pimpl->mScene) { if( !pimpl->mScene) {
break; break;

97
code/Profiler.h 100644
View File

@ -0,0 +1,97 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Profiler.h
* @brief Utility to measure the respective runtime of each import step
*/
#ifndef INCLUDED_PROFILER_H
#define INCLUDED_PROFILER_H
#include "boost/timer.hpp"
#include "../include/DefaultLogger.h"
#include "TinyFormatter.h"
namespace Assimp {
namespace Profiling {
using namespace Formatter;
// ------------------------------------------------------------------------------------------------
/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically
* dumped to the log file.
*/
class Profiler
{
public:
Profiler() {}
public:
/** Start a named timer */
void BeginRegion(const std::string& region) {
regions[region] = boost::timer();
DefaultLogger::get()->debug((format("START `"),region,"`"));
}
/** End a specific named timer and write its end time to the log */
void EndRegion(const std::string& region) {
RegionMap::const_iterator it = regions.find(region);
if (it == regions.end()) {
return;
}
DefaultLogger::get()->debug((format("END `"),region,"`, dt= ",(*it).second.elapsed()," s"));
}
private:
typedef std::map<std::string,boost::timer> RegionMap;
RegionMap regions;
};
}
}
#endif

Binary file not shown.

150
doc/dox.h
View File

@ -461,23 +461,6 @@ surely enough for almost any purpose. The process is simple:
<li> .. and pass it as last parameter to #aiImportFileEx <li> .. and pass it as last parameter to #aiImportFileEx
</ul> </ul>
@section threadsafety Thread-safety and internal multi-threading
The ASSIMP library can be accessed by multiple threads simultaneously, as long as the
following prerequisites are fulfilled:
<ul>
<li> When using the C++-API make sure you create a new Importer instance for each thread.
Constructing instances of Importer is expensive, so it might be a good idea to
let every thread maintain its own thread-local instance (use it to
load as many models as you want).</li>
<li> The C-API is threadsafe as long as AI_C_THREADSAFE is defined. That's the default. </li>
<li> When supplying custom IO logic, make sure your underyling implementation is thead-safe.</li>
<li> Custom log streams or logger replacements have to be thread-safe, too.</li>
</ul>
See the @ref assimp_st section @endlink to learn how to build a lightweight variant
of ASSIMP which is not thread-safe and does not utilize multiple threads for loading.
@section logging Logging @section logging Logging
The ASSIMP library provides an easy mechanism to log messages. For instance if you want to check the state of your The ASSIMP library provides an easy mechanism to log messages. For instance if you want to check the state of your
@ -1264,7 +1247,7 @@ mat->Get(AI_MATKEY_COLOR_DIFFUSE,color);
@endcode @endcode
<b>Note:</b> Get() is actually a template with explicit specializations for aiColor3D, aiColor4D, aiString, float, int and some others. <b>Note:</b> Get() is actually a template with explicit specializations for aiColor3D, aiColor4D, aiString, float, int and some others.
Make sure that the type of the second parameter is matching the expected data type of the material property (no compile-time check yet!). Make sure that the type of the second parameter matches the expected data type of the material property (no compile-time check yet!).
Don't follow this advice if you wish to encounter very strange results. Don't follow this advice if you wish to encounter very strange results.
@section C C-API @section C C-API
@ -1466,16 +1449,139 @@ Build: alles von CustomBuild + DirectX + MFC?
*/ */
/**
@page perf Performance
@section perf_overview Overview
This page discusses Assimps general performance and some ways to finetune and profile it. You will see that an
intelligent choice of postprocessing steps is essential for quick loading.
@section perf_profile Profiling
Assimp has builtin support for basic profiling and reporting. To turn it on, set the <tt>GLOB_MEASURE_TIME</tt>
configuration switch to <tt>true</tt> (nonzero). Results are dumped to the logfile, so you need to setup
an appropriate logger implementation with at least one output stream first. See the @link logging Logging Page @endlink
for the details.
A sample report looks like this (some unrelated log messages omitted, grouped entries for clarity):
@verbatim
Debug, T5488: START `total`
Info, T5488: Found a matching importer for this file format
Debug, T5488: START `import`
Info, T5488: BlendModifier: Applied the `Subdivision` modifier to `OBMonkey`
Debug, T5488: END `import`, dt= 3.516 s
Debug, T5488: START `preprocess`
Debug, T5488: END `preprocess`, dt= 0.001 s
Info, T5488: Entering post processing pipeline
Debug, T5488: START `postprocess`
Debug, T5488: RemoveRedundantMatsProcess begin
Debug, T5488: RemoveRedundantMatsProcess finished
Debug, T5488: END `postprocess`, dt= 0.001 s
Debug, T5488: START `postprocess`
Debug, T5488: TriangulateProcess begin
Info, T5488: TriangulateProcess finished. All polygons have been triangulated.
Debug, T5488: END `postprocess`, dt= 3.415 s
Debug, T5488: START `postprocess`
Debug, T5488: SortByPTypeProcess begin
Info, T5488: Points: 0, Lines: 0, Triangles: 1, Polygons: 0 (Meshes, X = removed)
Debug, T5488: SortByPTypeProcess finished
Debug, T5488: START `postprocess`
Debug, T5488: JoinVerticesProcess begin
Debug, T5488: Mesh 0 (unnamed) | Verts in: 503808 out: 126345 | ~74.922
Info, T5488: JoinVerticesProcess finished | Verts in: 503808 out: 126345 | ~74.9
Debug, T5488: END `postprocess`, dt= 2.052 s
Debug, T5488: START `postprocess`
Debug, T5488: FlipWindingOrderProcess begin
Debug, T5488: FlipWindingOrderProcess finished
Debug, T5488: END `postprocess`, dt= 0.006 s
Debug, T5488: START `postprocess`
Debug, T5488: LimitBoneWeightsProcess begin
Debug, T5488: LimitBoneWeightsProcess end
Debug, T5488: END `postprocess`, dt= 0.001 s
Debug, T5488: START `postprocess`
Debug, T5488: ImproveCacheLocalityProcess begin
Debug, T5488: Mesh 0 | ACMR in: 0.851622 out: 0.718139 | ~15.7
Info, T5488: Cache relevant are 1 meshes (251904 faces). Average output ACMR is 0.718139
Debug, T5488: ImproveCacheLocalityProcess finished.
Debug, T5488: END `postprocess`, dt= 1.903 s
Info, T5488: Leaving post processing pipeline
Debug, T5488: END `total`, dt= 11.269 s
@endverbatim
So, only one fourth of the total import time was used for the actual model import, while the rest of the
time was consumed by the #aiProcess_Triangulate, #aiProcess_JoinIdenticalVertices and #aiProcess_ImproveCacheLocality
postprocessing steps. It is therefore not a good idea to specify *all* postprocessing flags just because they
sound so nice.
*/
/**
@page threading Threading
@section overview Overview
This page discusses both Assimps scalability in threaded environments, the precautions to be taken in order to
use it from multiple threads concurrently and finally its own ability to parallelize certain tasks internally.
@section threadsafety Thread-safety / Using Assimp concurrently from several threads
The library can be accessed by multiple threads simultaneously, as long as the
following prerequisites are fulfilled:
<ul>
<li> When using the C++-API make sure you create a new Importer instance for each thread.
Constructing instances of Importer is expensive, so it might be a good idea to
let every thread maintain its own thread-local instance (use it to
load as many models as you want).</li>
<li> The C-API is threadsafe as long as AI_C_THREADSAFE is defined. That's the default. </li>
<li> When supplying custom IO logic, make sure your underyling implementation is thead-safe.</li>
<li> Custom log streams or logger replacements have to be thread-safe, too.</li>
</ul>
Multiple concurrent imports may or may not be beneficial, however. For certain file formats in conjunction with
little postprocessing IO times tend to be the performance bottleneck, using multiple threads does therefore not
help. Intense postprocessing (especially the O(nlogn) steps #aiProcess_JoinIdenticalVertices,
#aiProcess_GenSmoothNormals and #aiProcess_CalcTangentSpace) together with file formats like X or Collada,
which are slow to parse, might scale well with multiple concurrent imports.
@section automt Internal threading
Automatic multi-threading is not currently implemented.
*/
/** /**
@page importer_notes Importer Notes @page importer_notes Importer Notes
@section blender Blender
@subsection bl_overview Overview
Assimp provides a self-contained reimplementation of Blender's so called SDNA system (http://www.blender.org/development/architecture/notes-on-sdna/).
SDNA allows Blender to be fully backward AND forward compatible and to exchange
files created on any of the various platforms blender runs on with any other. Quick processing is another design goal -
BLEND is a fully-fledged binary monster and Assimp tries to read the most of it. Naturally, if Blender is the only modelling tool
in your asset work flow, consider writing a custom exporter from Blender if Assimp's format coverage does not meet your requirements.
@subsection bl_status Current status
@subsection bl_notes Notes
@section ogre Ogre @section ogre Ogre
@subsection overview Overview @subsection overview Overview
Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that i use. Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that i use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922
You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922
@subsection what What will be loaded? @subsection what What will be loaded?

View File

@ -59,6 +59,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_CONFIG_H #define INCLUDED_AI_CONFIG_H
// ###########################################################################
// LIBRARY SETTINGS
// General, global settings
// ###########################################################################
// ---------------------------------------------------------------------------
/** @brief Enables time measurements.
*
* If enabled, measures the time needed for each part of the loading
* process (i.e. IO time, importing, postprocessing, ..) and dumps
* these timings to the DefaultLogger. See the @link perf Performance
* Page@endlink for more information on this topic.
*
* Property type: bool. Default value: false.
*/
#define AI_CONFIG_GLOB_MEASURE_TIME \
"GLOB_MEASURE_TIME"
# if 0 // not implemented yet
// ---------------------------------------------------------------------------
/** @brief Set Assimp's multithreading policy.
*
* This setting is ignored if Assimp was built without boost.thread
* support (ASSIMP_BUILD_NO_THREADING, which is implied by ASSIMP_BUILD_BOOST_WORKAROUND).
* Possible values are: -1 to let Assimp decide what to do, 0 to disable
* multithreading entirely and any number larger than 0 to force a specific
* number of threads. Assimp is always free to ignore this settings, which is
* merely a hint. Usually, the default value (-1) will be fine. However, if
* Assimp is used concurrently from multiple user threads, it might be useful
* to limit each Importer instance to a specific number of cores.
*
* For more information, see the @link threading Threading page@endlink.
* Property type: int, default value: -1.
*/
#define AI_CONFIG_GLOB_MULTITHREADING \
"GLOB_MULTITHREADING"
#endif
// ########################################################################### // ###########################################################################
// POST PROCESSING SETTINGS // POST PROCESSING SETTINGS
// Various stuff to fine-tune the behavior of a specific post processing step. // Various stuff to fine-tune the behavior of a specific post processing step.
@ -136,7 +174,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* important additional information which you intend to parse. * important additional information which you intend to parse.
* For rendering, you can still render all meshes in the scene without * For rendering, you can still render all meshes in the scene without
* any transformations. * any transformations.
* Property type: integer (0: false; !0: true). Default value: false. * Property type: bool. Default value: false.
*/ */
#define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \ #define AI_CONFIG_PP_PTV_KEEP_HIERARCHY \
"PP_PTV_KEEP_HIERARCHY" "PP_PTV_KEEP_HIERARCHY"
@ -159,7 +197,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* degenerated lines to points. See the documentation to the * degenerated lines to points. See the documentation to the
* #aiProcess_FindDegenerates step for a detailed example of the various ways * #aiProcess_FindDegenerates step for a detailed example of the various ways
* to get rid of these lines and points if you don't want them. * to get rid of these lines and points if you don't want them.
* Property type: integer (0: false; !0: true). Default value: false. * Property type: bool. Default value: false.
*/ */
#define AI_CONFIG_PP_FD_REMOVE \ #define AI_CONFIG_PP_FD_REMOVE \
"PP_FD_REMOVE" "PP_FD_REMOVE"
@ -402,7 +440,7 @@ enum aiComponent
// ########################################################################### // ###########################################################################
// IMPORTER SETTINGS // IMPORTER SETTINGS
// Various stuff to fine-tune the behaviour of a specific importer plugin. // Various stuff to fine-tune the behaviour of specific importer plugins.
// ########################################################################### // ###########################################################################
@ -433,7 +471,7 @@ enum aiComponent
/** @brief Configures the AC loader to collect all surfaces which have the /** @brief Configures the AC loader to collect all surfaces which have the
* "Backface cull" flag set in separate meshes. * "Backface cull" flag set in separate meshes.
* *
* Property type: integer (0: false; !0: true). Default value: true. * Property type: bool. Default value: true.
*/ */
#define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \ #define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
"IMPORT_AC_SEPARATE_BFCULL" "IMPORT_AC_SEPARATE_BFCULL"
@ -444,7 +482,7 @@ enum aiComponent
* default, Assimp performs the subdivision using the standard * default, Assimp performs the subdivision using the standard
* Catmull-Clark algorithm * Catmull-Clark algorithm
* *
* Property type: integer (0: false; !0: true). Default value: true. * * Property type: bool. Default value: true.
*/ */
#define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \ #define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
"IMPORT_AC_EVAL_SUBDIVISION" "IMPORT_AC_EVAL_SUBDIVISION"
@ -453,7 +491,7 @@ enum aiComponent
/** @brief Configures the UNREAL 3D loader to separate faces with different /** @brief Configures the UNREAL 3D loader to separate faces with different
* surface flags (e.g. two-sided vs. single-sided). * surface flags (e.g. two-sided vs. single-sided).
* *
* Property type: integer (0: false; !0: true). Default value: true. * * Property type: bool. Default value: true.
*/ */
#define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \ #define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
"UNREAL_HANDLE_FLAGS" "UNREAL_HANDLE_FLAGS"
@ -466,7 +504,7 @@ enum aiComponent
* want to compute them on your own, if you need them. This option is intended * want to compute them on your own, if you need them. This option is intended
* for model viewers which want to offer an easy way to apply textures to * for model viewers which want to offer an easy way to apply textures to
* terrains. * terrains.
* Property type: integer (0: false; !0: true). Default value: false. * * Property type: bool. Default value: false.
*/ */
#define AI_CONFIG_IMPORT_TER_MAKE_UVS \ #define AI_CONFIG_IMPORT_TER_MAKE_UVS \
"IMPORT_TER_MAKE_UVS" "IMPORT_TER_MAKE_UVS"
@ -475,19 +513,20 @@ enum aiComponent
/** @brief Configures the ASE loader to always reconstruct normal vectors /** @brief Configures the ASE loader to always reconstruct normal vectors
* basing on the smoothing groups loaded from the file. * basing on the smoothing groups loaded from the file.
* *
* Many ASE files have invalid normals (they're not orthonormal). * Some ASE files have carry invalid normals, other don't.
* Property type: integer (0: false; !0: true). Default value: true. * * Property type: bool. Default value: true.
*/ */
#define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \ #define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
"IMPORT_ASE_RECONSTRUCT_NORMALS" "IMPORT_ASE_RECONSTRUCT_NORMALS"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Configures the M3D loader to process multi-part player models. /** @brief Configures the M3D loader to detect and process multi-part
* Quake player models.
* *
* These models usually consist of 3 files, lower.md3, upper.md3 and * These models usually consist of 3 files, lower.md3, upper.md3 and
* head.md3. If this property is set to true, Assimp will try to load and * head.md3. If this property is set to true, Assimp will try to load and
* combine all three files if one of them is loaded. * combine all three files if one of them is loaded.
* Property type: integer (0: false; !0: true). Default value: true. * Property type: bool. Default value: true.
*/ */
#define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \ #define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
"IMPORT_MD3_HANDLE_MULTIPART" "IMPORT_MD3_HANDLE_MULTIPART"
@ -545,7 +584,7 @@ enum aiComponent
* and combined with the MD5MESH file. This configuration option can be * and combined with the MD5MESH file. This configuration option can be
* used to disable this behaviour. * used to disable this behaviour.
* *
* Property type: integer (0: false; !0: true). Default value: false. * * Property type: bool. Default value: false.
*/ */
#define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \ #define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
"IMPORT_MD5_NO_ANIM_AUTOLOAD" "IMPORT_MD5_NO_ANIM_AUTOLOAD"

Binary file not shown.

View File

@ -151,7 +151,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
aiSetImportPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,g_smoothAngle); aiSetImportPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,g_smoothAngle);
aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,nopointslines ? aiPrimitiveType_LINE | aiPrimitiveType_POINT : 0 ); aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,nopointslines ? aiPrimitiveType_LINE | aiPrimitiveType_POINT : 0 );
//aiSetImportPropertyInteger(AI_CONFIG_PP_FD_REMOVE,1); aiSetImportPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,1);
//aiSetImportPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,1); //aiSetImportPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,1);
// Call ASSIMPs C-API to load the file // Call ASSIMPs C-API to load the file

View File

@ -2425,6 +2425,10 @@
RelativePath="..\..\code\ParsingUtils.h" RelativePath="..\..\code\ParsingUtils.h"
> >
</File> </File>
<File
RelativePath="..\..\code\Profiler.h"
>
</File>
<File <File
RelativePath="..\..\code\qnan.h" RelativePath="..\..\code\qnan.h"
> >