Merge branch 'master' into make_tools

pull/1954/head
Kim Kulling 2018-06-04 09:12:11 +02:00 committed by GitHub
commit a2a7877939
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 1698 additions and 807 deletions

3
.gitignore vendored
View File

@ -12,6 +12,8 @@ build
bin/
lib/
# QtCreator
CMakeLists.txt.user
# Generated
assimp.pc
@ -38,6 +40,7 @@ tools/assimp_cmd/Makefile
# Tests
test/results
test/readlinetest*
# Python
__pycache__

258
CHANGES
View File

@ -1,6 +1,264 @@
----------------------------------------------------------------------
CHANGELOG
----------------------------------------------------------------------
4.1.0 (2017-12):
- FEATURES:
- Export 3MF ( experimental )
- Import / Export glTF 2
- Introduce new zib-lib to eb able to export zip-archives
- FIXES/HOUSEKEEPING:
- Added missing include to stdlib.h and remove load library call
- Fix install for builds with MSVC compiler and NMake.
- Update list of supported file formats.
- Add TriLib to the official list of supported ports.
- Re-enabling PACK_STRUCT for MDL files.
- Use std.::unique_ptr
- Update D3MFExporter.h
- Update MD3Loader.cpp, using index
- Fix all warnings on MSVC14
- Copy assimp dll to unit folder on windows
- Update jvm port supported formats
- Add support for building Mac OS X Framework bundles
- Check for nullptr dereferencing before copying scene data
- Update ValidateDataStructure.h, typo
- Enable data structure validation in cases where it doesn't cause failures
- Remove some dead assignments
- fast_atof: Silence some uninitialized variable warnings
- Check for area test if the face is a triangle.
- Set mNumUVComponents to 0 when deleting texture coordinate sets
- Only scale the root node because this will rescale all children nodes as well.
- Issue 1514: Fix frame pointer arithmetic
- Prevent failing stringstream to crash the export process
- powf -> pow
- add Defines.h to include folder for install.
- Android:
- Fix android build
- Fix assimp for cross compile for android
- Use define for D_FILE_OFFSET_BITS only for not-android systems.
- FBX:
- Fix handling with embedded textures
- FBX 7500 Binary reading
- Remove dead assignment
- Fix export of deleted meshes; Add LazyDict::Remove method
- Log an error instead of letting the fbx-importer crash. ( issue 213 )
- Replace bad pointer casting with memcpy
- Remove useless const qualifier from return value
- Add explicit instantiation of log_prefix so other FBX source files can see it
- add missing inversion of postrotation matrix for fbx.
- FIReader: Silence uninitialized variable warning
- Update version check in FBX reader to check for version >= 7500
- Use actual min/max of anim keys when start/stop time is missing
- GLTF1:
- Fix output of glTF 1 version string
- Fix delete / delete[] mismatch in glTFAsset
- Don’t ignore rgba(1,1,1,1) color properties
- glTF2 primitives fixes
- Don’t ignore rgba(1,1,1,1) color properties
- Fix delete / delete[] mismatch in glTFAsset
- Remove KHR_binary_glTF code
- glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh
- version in glb header is stored as uint32_t
- GLTF2:
- node name conflict fix
- Fix transform matrices multiplication order
- Preserve node names when importing
- Add support for tangents in import
- Fix typo on gltf2 camera parameters
- Moved byteStride from accessor to bufferView
- Implemented reading binary glTF2 (glb) files
- Fix signed/unsigned warning
- Add postprocess step for scaling
- Fix shininess to roughness conversion
- Prefer “BLEND” over “MASK” as an alphaMode default
- Approximate specularity / glossiness in metallicRoughness materials
- Diffuse color and diffuse texture import and export improvements
- Addressed some mismatched news/deletes caused by the new glTF2 sources.
- Fix delete / delete[] mismatches in glTF2 importer
- use correct name of exporter to gltf2
- Fix possible infinite loop when exporting to gltf2
- Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars
- Fix glTF2 alphaMode storage and reading
- Fix glTF 2.0 multi-primitive support
- Load gltf .bin files from correct directory
- Add support for importing both glTF and glTF2 files
- ampler improvements; Add new LazyDict method
- Changes to GLTF2 materials
- Remove Light, Technique references
- Start removing materials common, and adding pbrSpecularGlossiness
- Use !ObjectEmpty() vs. MemberCount() > 0
- Working read, import, export, and write of gltf2 (pbr) material
- Check in gltf2 models to test directory
- Remove un-needed test models
- Start managing and importing gltf2 pbr materials
- Update glTF2 Asset to use indexes
- Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List
- glTF2: Fix animation export
- use opacity for diffuse alpha + alphaMode
- STL:
- Restore import of multi mesh binary STLs
- Blender:
- Silence warning about uninitialized member
- MDLImporter:
- Don't take address of packed struct member
- assimp_cmd:
- Fix strict-aliasing warnings
- Open3DGC:
- Fix strict-aliasing warnings
- Add assertions to silence static analyzer warnings
- Remove redundant const qualifiers from return types
- Fix some uninitialized variable warnings
- Remove OPEN3DGC and compression references
- unzip:
- Remove dead assignment
- Bail on bad compression method
- Fix possibly uninitialized variables
- clipper:
- Add assertion to silence a static analyzer warning
- OpenDDLExport:
- Reduce scope of a variable
- Remove dead variable
- Remove dead assignment
- Fix another potential memory leak
- X3DImporter:
- Add assertions to silence static analyzer warnings
- Add missing unittest
- Workaround for buggy Android NDK (issue #1361)
- TerragenLoader:
- Remove unused variable
- SIBImporter:
- Add assertions to silence static analyzer warnings
- IFC:
- Remove dead code
- Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it
- PLY:
- Remove dead assignment and reduce scope of a variable
- fix vertex attribute lookup.
- OpenGEX:
- Add assertion to silence a static analyzer warning
- Fix for TextureFile with number in file name
- Return early when element is TextureFile
- NFF:
- Add assertions to silence static analyzer warnings
- Split up some complicated assignments
- Raw: Fix misleading indentation warning
- Reduce scope of a variable
- LWO
- Reduce scope of a variable
- IRRLoader:
- Fix confusing boolean casting
- AssbinExporter:
- Add assertion to silence a static analyzer warning
- ASE:
- Add assertion to silence a static analyzer warning
- AMFImporter:
- Add assertion to silence a static analyzer warning
- Add a block
- OptimizeGraph:
- Fix possible null pointer dereference
- RemoveRedundantMaterials:
- Add assertion to silence a static analyzer warning
- ImproveCacheLocality:
- Add assertion to silence a static analyzer warning
- RemoveRedundantMaterials:
- Set pointer to nullptr after deleting it
- Travis:
- Disable unit tests in scan-build config
- Move slower builds earlier to improve parallelization
- Add static analysis to build
- Remove unused branch rule for travis.
- Add Clang UBSan build configuration
- Treat warnings as errors, without typos this time
- Unittests:
- Add VS-based source groups for the unittests.
- Collada:
- export <library_animations> tag
- Update ColladaExporter.cpp
- Silence uninitialized variable warning
- Add support for line strip primitives
- Obj Wavefront:
- check in exporting against out-of-bounds-access .
- Issue 1351: use correct name for obj-meshname export for groups.
- fix mem-lead: face will be not released in case of an error.
- Anatoscope obj exporter nomtl
- Raise exception when obj file contains invalid face indices
- Added alternative displacement texture token in OBJ MTL material.
- Obj: rename attribute from exporter.
- Fix OBJ discarding all material names if the material library is missing
- Step:
- use correct lookup for utf32
- MD2:
- Fix MD2 frames containing garbage
- STL
- add missing const.
- Fix memory-alignment bug.
- Fix issue 104: deal with more solids in one STL file.
- CMake
- Fix issue 213: use correct include folder for assimp
- Doxygen
- Fix issue 1513: put irrXML onto exclucde list for doxygen run
- PyAssimp:
- Search for libassimp.so in LD_LIBRARY_PATH if available.
- Fix operator precedence issue in header check
- Split setup.py into multiple lines
- Detect if Anaconda and fixed 3d_viewer for Python 3
- created a python3 version of the 3dviewer and fixed the / = float in py3
- Blender:
- Fix invalid access to mesh array when the array is empty.
- Fix short overflow.
- Silence warning about inline function which is declared but not defined
- JAssimp
- Changed license header for IHMC contributions from Apache 2.0 to BSD
- Add Node metadata to the Jassmip Java API
- Added supported for custom IO Systems in Java. Implemented ClassLoader IO System
- Added a link to pure jvm assimp port
- Clang sanitizer:
- Undefined Behavior sanitizer
- Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug
- B3DImporter:
- Replace bad pointer casting with memcpy
- AppVeyor:
- Cleanup and Addition of VS 2017 and running Tests
- Fixed File Size reported as 0 in tests that use temporary files
- x86 isn't a valid VS platform. Win32 it is, then.
- Replaced the worker image name, which doesn't work as generator name, with a manually created generator name.
- Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests.
- Treat warnings as errors on Appveyor
- Disable warning 4351 on MSVC 2013
- OpenGEXImporter:
- Copy materials to scene
- Store RefInfo in unique_ptr so they get automatically cleaned up
- Fix IOStream leak
- Store ChildInfo in unique_ptr so they get automatically cleaned up
- improve logging to be able to detect error-prone situations.
- AMFImporter:
- Fix memory leak
- UnrealLoader:
- Fix IOStream leak
- Upgrade RapidJSON to get rid of a clang warning
- zlib:
- Update zlib contribution
- Removed unnecessary files from zlib contribution
- Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table
- MakeVerboseFormat:
- Fix delete / delete[] mismatches in MakeVerboseFormat
- MaterialSystem:
- Fix out-of-bounds read in MaterialSystem unit test
- SIB:
- Added support for SIB models from Silo 2.5
- AssbinExporter:
- Fix strict aliasing violation
- Add Write specialization for aiColor3D
- DefaultLogger:
- Whitespace cleanup to fix GCC misleading indentation warning
- MDP:
- Fix encoding issues.
- PreTransformVertices:
- fix name lost in mesh and nodes when load with flag
- C4D:
- Fixes for C4D importer
- Unzip:
- Latest greatest.
4.0.1 (2017-07-28)
- FIXES/HOUSEKEEPING:
- fix version test.

View File

@ -412,32 +412,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
# Check dependencies for assimp_qt_viewer.
# Why here? Maybe user do not want Qt viewer and have no Qt.
# Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
# Because viewer can be build independently of Assimp.
FIND_PACKAGE(Qt5Widgets QUIET)
FIND_PACKAGE(DevIL QUIET)
FIND_PACKAGE(OpenGL QUIET)
IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
ELSE()
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
IF (NOT Qt5_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
ENDIF (NOT Qt5_FOUND)
IF (NOT IL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
ENDIF (NOT IL_FOUND)
IF (NOT OPENGL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
ENDIF (NOT OPENGL_FOUND)
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( ASSIMP_BUILD_SAMPLES)

11
CONTRIBUTING.md 100644
View File

@ -0,0 +1,11 @@
#How to contribute
If you want to contribute you can follow these setps:
- Fist create your own clone of assimp
- When you want to fix a bug or add a new feature create a branch on your own fork ( just follow https://help.github.com/articles/creating-a-pull-request-from-a-fork/ )
- Push it to the repo and open a pull request
- A pull request will start our CI-service, which checks if the build works for linux and windows.
It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fails: fix it and the tests will be reastarted automatically
- At the end we will perform a code review and merge your branch to the master branch.

View File

@ -140,8 +140,6 @@ Open Asset Import Library is implemented in C++. The directory structure is:
/tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible
use cases for Assimp
/workspaces Build environments for vc,xcode,... (deprecated,
CMake has superseeded all legacy build options!)
### Where to get help ###

View File

@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup the texture mapping mode
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
int mapMode = static_cast<int>(texture.mMapMode);
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
// Mirroring - double the scaling values
// FIXME: this is not really correct ...
@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
case D3DS::Discreet3DS::Blinn :
eShading = aiShadingMode_Blinn; break;
}
mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
int eShading_ = static_cast<int>(eShading);
mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
// DIFFUSE texture
if( oldMat.sTexDiffuse.mMapName.length() > 0)

View File

@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
0,
0,
0,
"3ds prj 3DS PRJ"
"3ds prj"
};
@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() {
// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) {
if(extension == "3ds" || extension == "prj") {
return true;
}

View File

@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
@ -84,7 +84,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
@ -130,7 +130,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
} while(false)
/// \def MACRO_NODECHECK_READCOMP_F
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float".
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
@ -147,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
/// \def MACRO_NODECHECK_READCOMP_U32
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.

View File

@ -99,7 +99,7 @@ CAMFImporter_NodeElement* ne;
ParseHelper_Node_Exit();
// check that all components was defined
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
// check if <a> is absent. Then manualy add "a == 1".
// check if <a> is absent. Then manually add "a == 1".
if(!read_flag[3]) als.Color.a = 1;
}// if(!mReader->isEmptyElement())

View File

@ -770,7 +770,7 @@ std::list<aiNode*> ch_node;
// find referenced object
if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
// create node for apllying transformation
// create node for applying transformation
t_node = new aiNode;
t_node->mParent = con_node;
// apply transformation

View File

@ -427,7 +427,7 @@ public:
// -------------------------------------------------------------------
//! Construct a parser from a given input file which is
//! guaranted to be terminated with zero.
//! guaranteed to be terminated with zero.
//! @param szFile Input file
//! @param fileFormatDefault Assumed file format version. If the
//! file format is specified in the file the new value replaces

View File

@ -227,7 +227,7 @@ void DNAParser::Parse ()
// ------------------------------------------------------------------------------------------------
void DNA :: DumpToFile()
{
// we dont't bother using the VFS here for this is only for debugging.
// we don't bother using the VFS here for this is only for debugging.
// (and all your bases are belong to us).
std::ofstream f("dna.txt");

View File

@ -663,7 +663,7 @@ public:
/** Check whether a specific item is in the cache.
* @param s Data type of the item
* @param out Output pointer. Unchanged if the
* cache doens't know the item yet.
* cache doesn't know the item yet.
* @param ptr Item address to look for. */
template <typename T> void get (
const Structure& s,

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_BLEND_TESSELLATOR_H
// Use these to toggle between GLU Tessellate or poly2tri
// Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
// Note (acg) keep GLU Tessellate disabled by default - if it is turned on,
// assimp needs to be linked against GLU, which is currently not yet
// made configurable in CMake and potentially not wanted by most users
// as it requires a Gl environment.

View File

@ -208,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_
# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
# this way selective loaders can be compiled (reduces filesize + compile time)
MACRO(ADD_ASSIMP_IMPORTER name)
OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
IF(ASSIMP_BUILD_${name}_IMPORTER)
IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT)
set(ASSIMP_IMPORTER_ENABLED TRUE)
IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER)
set(ASSIMP_IMPORTER_ENABLED FALSE)
ENDIF ()
ELSE ()
set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER})
ENDIF ()
IF (ASSIMP_IMPORTER_ENABLED)
LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
SET(${name}_SRCS ${ARGN})

View File

@ -189,7 +189,7 @@ protected:
{}
};
// summarize a material in an convinient way.
// summarize a material in an convenient way.
struct Material
{
std::string name;

View File

@ -956,7 +956,7 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
// Stores all animations
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
{
// recursivly collect all animations from the collada scene
// recursively collect all animations from the collada scene
StoreAnimations( pScene, pParser, &pParser.mAnims, "");
// catch special case: many animations with the same length, each affecting only a single node.
@ -1784,7 +1784,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// In FBX files textures are now stored internally by Assimp with their filename included
// Now Assimp can lookup thru the loaded textures after all data is processed
// Now Assimp can lookup through the loaded textures after all data is processed
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
// This may occur on this case too, it has to be studied
// setup texture reference string
@ -1819,9 +1819,12 @@ void ColladaLoader::ConvertPath (aiString& ss)
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
// I need to filter it without destroying linux paths starting with "/somewhere"
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
{
ss.length--;
#if defined( _MSC_VER )
if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) {
#else
if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') {
#endif
--ss.length;
::memmove( ss.data, ss.data+1, ss.length);
ss.data[ss.length] = 0;
}

View File

@ -222,7 +222,7 @@ void D3MFExporter::writeMetaData() {
return;
}
const aiString *key;
const aiString *key = nullptr;
const aiMetadataEntry *entry(nullptr);
for ( size_t i = 0; i < numMetaEntries; ++i ) {
mScene->mMetaData->Get( i, key, entry );

View File

@ -115,10 +115,10 @@ public:
// import the metadata
if ( !mMetaData.empty() ) {
const size_t numMeta( mMetaData.size() );
scene->mMetaData = aiMetadata::Alloc( numMeta );
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>( numMeta ) );
for ( size_t i = 0; i < numMeta; ++i ) {
aiString val( mMetaData[ i ].value );
scene->mMetaData->Set( i, mMetaData[ i ].name, val );
scene->mMetaData->Set(static_cast<unsigned int>( i ), mMetaData[ i ].name, val );
}
}

View File

@ -127,7 +127,7 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
if ( extension.empty() || checkSig ) {
static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4 );
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 );
}
return false;

View File

@ -76,11 +76,11 @@ bool DefaultIOSystem::Exists( const char* pFile) const
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL);
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
struct _stat64 filestat;
struct __stat64 filestat;
if (0 != _wstat64(fileName16, &filestat)) {
return false;
}
@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
FILE* file;
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL );
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
std::string mode8(strMode);
@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
{
ai_assert(in && _out);
#if defined( _MSC_VER ) || defined( __MINGW32__ )
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL);
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
if (isUnicode) {
wchar_t out16[PATHLIMIT];
wchar_t in16[PATHLIMIT];

View File

@ -154,9 +154,9 @@ Exporter::ExportFormatEntry gExporters[] =
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
#endif

View File

@ -448,8 +448,8 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
/*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t version = ReadWord(input, cursor, input + length);
const bool is64bits = version >= 7500;
while (cursor < input + length)
{
const char *end = input + length;
while (cursor < end ) {
if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
break;
}

View File

@ -1526,6 +1526,46 @@ unsigned int Converter::ConvertVideo( const Video& video )
return static_cast<unsigned int>( textures.size() - 1 );
}
aiString Converter::GetTexturePath(const Texture* tex)
{
aiString path;
path.Set(tex->RelativeFilename());
const Video* media = tex->Media();
if (media != nullptr) {
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
unsigned int index;
VideoMap::const_iterator it = textures_converted.find(media);
if (it != textures_converted.end()) {
index = (*it).second;
textureReady = true;
}
else {
if (media->ContentLength() > 0) {
index = ConvertVideo(*media);
textures_converted[media] = index;
textureReady = true;
}
}
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
if (textureReady) {
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// In FBX files textures are now stored internally by Assimp with their filename included
// Now Assimp can lookup through the loaded textures after all data is processed
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
// This may occur on this case too, it has to be studied
path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
}
}
}
return path;
}
void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName,
aiTextureType target, const MeshGeometry* const mesh )
@ -1538,41 +1578,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
const Texture* const tex = ( *it ).second;
if ( tex != 0 )
{
aiString path;
path.Set( tex->RelativeFilename() );
const Video* media = tex->Media();
if (media != 0) {
bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
unsigned int index;
VideoMap::const_iterator it = textures_converted.find(media);
if (it != textures_converted.end()) {
index = (*it).second;
textureReady = true;
}
else {
if (media->ContentLength() > 0) {
index = ConvertVideo(*media);
textures_converted[media] = index;
textureReady = true;
}
}
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
if (doc.Settings().useLegacyEmbeddedTextureNaming) {
if (textureReady) {
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// In FBX files textures are now stored internally by Assimp with their filename included
// Now Assimp can lookup thru the loaded textures after all data is processed
// We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
// This may occur on this case too, it has to be studied
path.data[0] = '*';
path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
}
}
}
aiString path = GetTexturePath(tex);
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
aiUVTransform uvTrafo;
@ -1696,9 +1702,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
const Texture* const tex = ( *it ).second->getTexture(texIndex);
aiString path;
path.Set( tex->RelativeFilename() );
aiString path = GetTexturePath(tex);
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
aiUVTransform uvTrafo;

View File

@ -228,6 +228,10 @@ private:
// Video -> aiTexture
unsigned int ConvertVideo(const Video& video);
// ------------------------------------------------------------------------------------------------
// convert embedded texture if necessary and return actual texture path
aiString GetTexturePath(const Texture* tex);
// ------------------------------------------------------------------------------------------------
void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName,

View File

@ -575,11 +575,11 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
ai_assert( count != 0 );
ai_assert( count <= MAX_CLASSNAMES);
size_t lenghts[MAX_CLASSNAMES];
size_t lengths[MAX_CLASSNAMES];
const size_t c = count;
for (size_t i = 0; i < c; ++i) {
lenghts[ i ] = strlen(classnames[i]);
lengths[ i ] = strlen(classnames[i]);
}
std::vector<const Connection*> temp;
@ -597,7 +597,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
for (size_t i = 0; i < c; ++i) {
ai_assert(classnames[i]);
if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
obtype = NULL;
break;
}

View File

@ -450,7 +450,7 @@ void FBXExporter::WriteDocuments ()
p.AddP70string("ActiveAnimStackName", ""); // should do this properly?
doc.AddChild(p);
// UID for root node in scene heirarchy.
// UID for root node in scene hierarchy.
// always set to 0 in the case of a single document.
// not sure what happens if more than one document exists,
// but that won't matter to us as we're exporting a single scene.
@ -650,7 +650,7 @@ void FBXExporter::WriteDefinitions ()
}
// Model / FbxNode
// <~~ node heirarchy
// <~~ node hierarchy
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
if (count) {
n = FBX::Node("ObjectType", "Model");
@ -1223,7 +1223,7 @@ void FBXExporter::WriteObjects ()
// it's all about this material
aiMaterial* m = mScene->mMaterials[i];
// these are used to recieve material data
// these are used to receive material data
float f; aiColor3D c;
// start the node record
@ -1311,7 +1311,7 @@ void FBXExporter::WriteObjects ()
// Now the legacy system.
// For safety let's include it.
// thrse values don't exist in the property template,
// and usualy are completely ignored when loading.
// and usually are completely ignored when loading.
// One notable exception is the "Opacity" property,
// which Blender uses as (1.0 - alpha).
c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
@ -1532,7 +1532,7 @@ void FBXExporter::WriteObjects ()
// bones.
//
// output structure:
// subset of node heirarchy that are "skeleton",
// subset of node hierarchy that are "skeleton",
// i.e. do not have meshes but only bones.
// but.. i'm not sure how anyone could guarantee that...
//
@ -1544,7 +1544,7 @@ void FBXExporter::WriteObjects ()
//
// well. we can assume a sane input, i suppose.
//
// so input is the bone node heirarchy,
// so input is the bone node hierarchy,
// with an extra thing for the transformation of the MESH in BONE space.
//
// output is a set of bone nodes,
@ -1556,7 +1556,7 @@ void FBXExporter::WriteObjects ()
// and represents the influence of that bone on the grandparent mesh.
// the subdeformer has a list of indices, and weights,
// with indices specifying vertex indices,
// and weights specifying the correspoding influence of this bone.
// and weights specifying the corresponding influence of this bone.
// it also has Transform and TransformLink elements,
// specifying the transform of the MESH in BONE space,
// and the transformation of the BONE in WORLD space,
@ -1806,7 +1806,7 @@ void FBXExporter::WriteObjects ()
// and a correct skeleton would still be output.
// transformlink should be the position of the bone in world space.
// if the bone is in the bind pose (or nonexistant),
// if the bone is in the bind pose (or nonexistent),
// we can just use the matrix we already calculated
if (bone_xform_okay) {
sdnode.AddChild("TransformLink", bone_xform);
@ -1945,7 +1945,7 @@ void FBXExporter::WriteObjects ()
// TODO: cameras, lights
// write nodes (i.e. model heirarchy)
// write nodes (i.e. model hierarchy)
// start at root node
WriteModelNodes(
outstream, mScene->mRootNode, 0, limbnodes
@ -2203,8 +2203,8 @@ void FBXExporter::WriteModelNode(
} else {
// apply the transformation chain.
// these transformation elements are created when importing FBX,
// which has a complex transformation heirarchy for each node.
// as such we can bake the heirarchy back into the node on export.
// which has a complex transformation hierarchy for each node.
// as such we can bake the hierarchy back into the node on export.
for (auto &item : transform_chain) {
auto elem = transform_types.find(item.first);
if (elem == transform_types.end()) {

View File

@ -90,7 +90,7 @@ namespace Assimp
const ExportProperties* mProperties; // currently unused
std::shared_ptr<IOStream> outfile; // file to write to
std::vector<FBX::Node> connections; // conection storage
std::vector<FBX::Node> connections; // connection storage
std::vector<int64_t> mesh_uids;
std::vector<int64_t> material_uids;

View File

@ -302,7 +302,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
}
if(Content) {
//this field is ommited when the embedded texture is already loaded, let's ignore if it's not found
//this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
try {
const Token& token = GetRequiredToken(*Content, 0);
const char* data = token.begin();

View File

@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
//remove mesh at position 'index' from the scene
static void removeMesh(aiScene* pScene, unsigned const index);
//correct node indices to meshes and remove references to deleted mesh
static void updateSceneGraph(aiNode* pNode, unsigned const index);
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindDegeneratesProcess::FindDegeneratesProcess()
@ -87,11 +92,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
void FindDegeneratesProcess::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
ExecuteOnMesh( pScene->mMeshes[ i ] );
if (ExecuteOnMesh(pScene->mMeshes[i])) {
removeMesh(pScene, i);
--i; //the current i is removed, do not skip the next one
}
}
ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
}
static void removeMesh(aiScene* pScene, unsigned const index) {
//we start at index and copy the pointers one position forward
//save the mesh pointer to delete it later
auto delete_me = pScene->mMeshes[index];
for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) {
pScene->mMeshes[i] = pScene->mMeshes[i+1];
}
pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr;
--(pScene->mNumMeshes);
delete delete_me;
//removing a mesh also requires updating all references to it in the scene graph
updateSceneGraph(pScene->mRootNode, index);
}
static void updateSceneGraph(aiNode* pNode, unsigned const index) {
for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
if (pNode->mMeshes[i] > index) {
--(pNode->mMeshes[i]);
continue;
}
if (pNode->mMeshes[i] == index) {
for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) {
pNode->mMeshes[j] = pNode->mMeshes[j+1];
}
--(pNode->mNumMeshes);
--i;
continue;
}
}
//recurse to all children
for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
updateSceneGraph(pNode->mChildren[i], index);
}
}
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
ai_real s = (a + b + c) / 2;
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 );
@ -125,7 +169,7 @@ static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
mesh->mPrimitiveTypes = 0;
std::vector<bool> remove_me;
@ -161,7 +205,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
// NOTE: we set the removed vertex index to an unique value
// to make sure the developer gets notified when his
// application attemps to access this data.
// application attempts to access this data.
face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
if(first) {
@ -227,30 +271,28 @@ evil_jump_outside:
if (&face_src != &face_dest) {
// clear source
face_src.mNumIndices = 0;
face_src.mIndices = NULL;
face_src.mIndices = nullptr;
}
}
else {
// Otherwise delete it if we don't need this face
delete[] face_src.mIndices;
face_src.mIndices = NULL;
face_src.mIndices = nullptr;
face_src.mNumIndices = 0;
}
}
// Just leave the rest of the array unreferenced, we don't care for now
mesh->mNumFaces = n;
if (!mesh->mNumFaces) {
// WTF!?
// OK ... for completeness and because I'm not yet tired,
// let's write code that will hopefully never be called
// (famous last words)
// OK ... bad idea.
throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
//The whole mesh consists of degenerated faces
//signal upward, that this mesh should be deleted.
ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
return true;
}
}
if (deg && !DefaultLogger::isNullLogger()) {
ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
}
return false;
}

View File

@ -74,7 +74,8 @@ public:
// -------------------------------------------------------------------
// Execute step on a given mesh
void ExecuteOnMesh( aiMesh* mesh);
///@returns true if the current mesh should be deleted, false otherwise
bool ExecuteOnMesh( aiMesh* mesh);
// -------------------------------------------------------------------
/// @brief Enable the instant removal of degenerated primitives

View File

@ -146,7 +146,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0;i < face.mNumIndices;++i) {
pMesh->mNormals[face.mIndices[i]] = vNor;
@ -214,17 +214,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
aiVector3D vr = pMesh->mNormals[i];
ai_real vrlen = vr.Length();
aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
aiVector3D v = pMesh->mNormals[verticesFound[a]];
// check whether the angle between the two normals is not too large
// HACK: if v.x is qnan the dot product will become qnan, too
// therefore the comparison against fLimit should be false
// in every case.
if (v * vr >= fLimit * vrlen * v.Length())
// Check whether the angle between the two normals is not too large.
// Skip the angle check on our own normal to avoid false negatives
// (v*v is not guaranteed to be 1.0 for all unit vectors v)
if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
pcNor += v;
}
pcNew[i] = pcNor.NormalizeSafe();

View File

@ -91,7 +91,7 @@ protected:
// -------------------------------------------------------------------
/** Read a property of the specified type from the current XML element.
* @param out Recives output data
* @param out Receives output data
*/
void ReadHexProperty (HexProperty& out);
void ReadStringProperty (StringProperty& out);

View File

@ -970,15 +970,18 @@ void Importer::GetExtensionList(aiString& szOut) const
(*i)->GetExtensionList(str);
}
for (std::set<std::string>::const_iterator it = str.begin();; ) {
szOut.Append("*.");
szOut.Append((*it).c_str());
// List can be empty
if( !str.empty() ) {
for (std::set<std::string>::const_iterator it = str.begin();; ) {
szOut.Append("*.");
szOut.Append((*it).c_str());
if (++it == str.end()) {
break;
}
szOut.Append(";");
}
if (++it == str.end()) {
break;
}
szOut.Append(";");
}
}
ASSIMP_END_EXCEPTION_REGION(void);
}
@ -997,33 +1000,33 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue)
// Set a configuration property
bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
{
bool exising;
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
exising = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
ASSIMP_END_EXCEPTION_REGION(bool);
return exising;
return existing;
}
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyString(const char* szName, const std::string& value)
{
bool exising;
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
exising = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
ASSIMP_END_EXCEPTION_REGION(bool);
return exising;
return existing;
}
// ------------------------------------------------------------------------------------------------
// Set a configuration property
bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
{
bool exising;
bool existing;
ASSIMP_BEGIN_EXCEPTION_REGION();
exising = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
ASSIMP_END_EXCEPTION_REGION(bool);
return exising;
return existing;
}
// ------------------------------------------------------------------------------------------------

View File

@ -317,7 +317,7 @@ void TempMesh::FixupFaceOrientation()
IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0))
/ IfcFloat(mVertcnt[farthestIndex]);
// We accapt a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
// We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
// the file.
if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
{

View File

@ -108,6 +108,125 @@ void JoinVerticesProcess::Execute( aiScene* pScene)
pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
}
namespace {
bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex)
{
// A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f;
// Squared because we check against squared length of the vector difference
static const float squareEpsilon = epsilon * epsilon;
// Square compare is useful for animeshes vertices compare
if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) {
return false;
}
// We just test the other attributes even if they're not present in the mesh.
// In this case they're initialized to 0 so the comparison succeeds.
// By this method the non-present attributes are effectively ignored in the comparison.
if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
return false;
}
if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) {
return false;
}
// Usually we won't have vertex colors or multiple UVs, so we can skip from here
// Actually this increases runtime performance slightly, at least if branch
// prediction is on our side.
if (complex) {
for (int i = 0; i < 8; i++) {
if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
return false;
}
if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
return false;
}
}
}
return true;
}
template<class XMesh>
void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
// replace vertex data with the unique data sets
pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position, if present (check made for aiAnimMesh)
if (pMesh->mVertices)
{
delete [] pMesh->mVertices;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mVertices[a] = uniqueVertices[a].position;
}
}
// Normals, if present
if (pMesh->mNormals)
{
delete [] pMesh->mNormals;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mNormals[a] = uniqueVertices[a].normal;
}
}
// Tangents, if present
if (pMesh->mTangents)
{
delete [] pMesh->mTangents;
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = uniqueVertices[a].tangent;
}
}
// Bitangents as well
if (pMesh->mBitangents)
{
delete [] pMesh->mBitangents;
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
}
}
// Vertex colors
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
{
delete [] pMesh->mColors[a];
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
}
}
// Texture coords
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
{
delete [] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
@ -132,9 +251,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff");
std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
// A little helper to find locally close vertices faster.
// Try to reuse the lookup table from the last step.
const static float epsilon = 1e-5f;
// float posEpsilonSqr;
SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder;
@ -156,9 +272,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// posEpsilonSqr = ComputePositionEpsilon(pMesh);
}
// Squared because we check against squared length of the vector difference
static const float squareEpsilon = epsilon * epsilon;
// Again, better waste some bytes than a realloc ...
std::vector<unsigned int> verticesFound;
verticesFound.reserve(10);
@ -166,6 +279,16 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// Run an optimized code path if we don't have multiple UVs or vertex colors.
// This should yield false in more than 99% of all imports ...
const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
// We'll never have more vertices afterwards.
std::vector<std::vector<Vertex>> uniqueAnimatedVertices;
if (hasAnimMeshes) {
uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes);
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
}
}
// Now check each vertex if it brings something new to the table
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
@ -178,74 +301,32 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// check all unique vertices close to the position if this vertex is already present among them
for( unsigned int b = 0; b < verticesFound.size(); b++) {
const unsigned int vidx = verticesFound[b];
const unsigned int uidx = replaceIndex[ vidx];
if( uidx & 0x80000000)
continue;
const Vertex& uv = uniqueVertices[ uidx];
// Position mismatch is impossible - the vertex finder already discarded all non-matching positions
// We just test the other attributes even if they're not present in the mesh.
// In this case they're initialized to 0 so the comparison succeeds.
// By this method the non-present attributes are effectively ignored in the comparison.
if( (uv.normal - v.normal).SquareLength() > squareEpsilon)
continue;
if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon)
continue;
if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon)
continue;
if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon)
if (!areVerticesEqual(v, uv, complex)) {
continue;
}
// Usually we won't have vertex colors or multiple UVs, so we can skip from here
// Actually this increases runtime performance slightly, at least if branch
// prediction is on our side.
if (complex){
// manually unrolled because continue wouldn't work as desired in an inner loop,
// also because some compilers seem to fail the task. Colors and UV coords
// are interleaved since the higher entries are most likely to be
// zero and thus useless. By interleaving the arrays, vertices are,
// on average, rejected earlier.
if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon)
continue;
if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon)
continue;
if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon)
continue;
if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon)
continue;
if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon)
continue;
if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon)
continue;
if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon)
continue;
if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon)
if (hasAnimMeshes) {
// If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology)
// NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces)
bool breaksAnimMesh = false;
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx];
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) {
breaksAnimMesh = true;
break;
}
}
if (breaksAnimMesh) {
continue;
}
}
// we're still here -> this vertex perfectly matches our given vertex
@ -264,6 +345,12 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
// no unique vertex matches it up to now -> so add it
replaceIndex[a] = (unsigned int)uniqueVertices.size();
uniqueVertices.push_back( v);
if (hasAnimMeshes) {
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a);
uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex);
}
}
}
}
@ -281,64 +368,10 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
);
}
// replace vertex data with the unique data sets
pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position
delete [] pMesh->mVertices;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mVertices[a] = uniqueVertices[a].position;
// Normals, if present
if( pMesh->mNormals)
{
delete [] pMesh->mNormals;
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mNormals[a] = uniqueVertices[a].normal;
}
}
// Tangents, if present
if( pMesh->mTangents)
{
delete [] pMesh->mTangents;
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = uniqueVertices[a].tangent;
}
}
// Bitangents as well
if( pMesh->mBitangents)
{
delete [] pMesh->mBitangents;
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
}
}
// Vertex colors
for( unsigned int a = 0; pMesh->HasVertexColors(a); a++)
{
delete [] pMesh->mColors[a];
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
}
}
// Texture coords
for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
{
delete [] pMesh->mTextureCoords[a];
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
updateXMeshVertices(pMesh, uniqueVertices);
if (hasAnimMeshes) {
for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]);
}
}

View File

@ -253,7 +253,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
// setup the mapping mode
pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
int mapping_ = static_cast<int>(mapping);
pcMat->AddProperty<int>(&mapping_, 1, AI_MATKEY_MAPPING(type, cur));
// add the u-wrapping
temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
@ -365,7 +366,8 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
}
if (surf.mMaximumSmoothAngle <= 0.0)
m = aiShadingMode_Flat;
pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
int m_ = static_cast<int>(m);
pcMat->AddProperty(&m_, 1, AI_MATKEY_SHADING_MODEL);
// (the diffuse value is just a scaling factor)
// If a diffuse texture is set, we set this value to 1.0

View File

@ -410,7 +410,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// name to attach light to node -> unique due to LWs indexing system
lit->mName = nd->mName;
// detemine light type and setup additional members
// determine light type and setup additional members
if (src.lightType == 2) { /* spot light */
lit->mType = aiLightSource_SPOT;

View File

@ -141,7 +141,7 @@ void MDLImporter::SetupProperties(const Importer* pImp)
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
}
// AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
// AI_CONFIG_IMPORT_MDL_COLORMAP - palette file
configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
}
@ -1496,7 +1496,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
// check whether the triangle data structure is large enough
// to contain a second UV coodinate set
// to contain a second UV coordinate set
if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
groupData.bNeed2UV = true;

View File

@ -217,7 +217,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
pMesh->mNumFaces = indexCount / 3;
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
const int numIndices = 3; // trianglular face
const int numIndices = 3; // triangular face
for (unsigned int index = 0; index < pMesh->mNumFaces; index++) {
pMesh->mFaces[index].mNumIndices = numIndices;
unsigned int *indices = new unsigned int[numIndices];

View File

@ -354,8 +354,9 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
return AI_FAILURE;
}
// Determine mapping type
aiTextureMapping mapping = aiTextureMapping_UV;
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
int mapping_ = static_cast<int>(aiTextureMapping_UV);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
if (_mapping)
*_mapping = mapping;

View File

@ -271,7 +271,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
ShadingInfo s; // current material info
// degree of tesselation
// degree of tessellation
unsigned int iTesselation = 4;
// some temporary variables we need to parse the file
@ -988,7 +988,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
::ai_snprintf(currentMesh.name,128,"cone_%i",cone++);
else ::ai_snprintf(currentMesh.name,128,"cylinder_%i",cylinder++);
}
// 'tess' - tesselation
// 'tess' - tessellation
else if (TokenMatch(sz,"tess",4))
{
SkipSpaces(&sz);

View File

@ -691,7 +691,7 @@ void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *
void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
m_currentMesh = new aiMesh;
const size_t meshidx( m_meshCache.size() );
// ownership is transfered but a reference remains in m_currentMesh
// ownership is transferred but a reference remains in m_currentMesh
m_meshCache.emplace_back( m_currentMesh );
Property *prop = node->getProperties();

View File

@ -102,7 +102,7 @@ public:
}
// -------------------------------------------------------------------
/** @brief Rmeove a node from the list of locked nodes.
/** @brief Remove a node from the list of locked nodes.
* @param name Name to be unlocked
*/
inline void RemoveLockedNode(std::string& name)

View File

@ -212,7 +212,7 @@ template <> struct MinMaxChooser<aiVertexWeight> {
// -------------------------------------------------------------------------------
/** @brief Find the min/max values of an array of Ts
* @param in Input array
* @param size Numebr of elements to process
* @param size Number of elements to process
* @param[out] min minimum value
* @param[out] max maximum value
*/

View File

@ -352,7 +352,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
if (positionBuffer.empty()) {
pMesh->mNumFaces = 0;
throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded");
ASSIMP_LOG_WARN("STL: mesh is empty or invalid; no data loaded");
}
if (positionBuffer.size() % 3 != 0) {
pMesh->mNumFaces = 0;
@ -365,10 +365,10 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
memcpy(pMesh->mVertices, positionBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D));
positionBuffer.clear();
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
memcpy(pMesh->mNormals, normalBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D));
normalBuffer.clear();
// now copy faces

View File

@ -104,7 +104,7 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
// Ensure unsued components are zeroed. This will make 1D texture channels work
// 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]) {

View File

@ -377,7 +377,7 @@ void StandardShapes::MakeSphere(unsigned int tess,
MakeIcosahedron(positions);
// ... and subdivide it until the requested output
// tesselation is reached
// tessellation is reached
for (unsigned int i = 0; i<tess;++i)
Subdivide(positions);
}

View File

@ -162,7 +162,7 @@ void StepExporter::WriteFile()
// see http://shodhganga.inflibnet.ac.in:8080/jspui/bitstream/10603/14116/11/11_chapter%203.pdf
// note, that all realnumber values must be comma separated in x files
mOutput.setf(std::ios::fixed);
// precission for double
// precision for double
// see http://stackoverflow.com/questions/554063/how-do-i-print-a-double-value-with-full-precision-using-cout
mOutput.precision(16);

View File

@ -88,7 +88,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
{
/* This function tries to simplify the input UV transformation.
* That's very important as it allows us to reduce the number
* of output UV channels. The oder in which the transformations
* of output UV channels. The order in which the transformations
* are applied is - as always - scaling, rotation, translation.
*/

View File

@ -369,7 +369,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// positions must always be there ...
if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
ReportError("The mesh contains no vertices");
ReportError("The mesh %s contains no vertices", pMesh->mName.C_Str());
}
if (pMesh->mNumVertices > AI_MAX_VERTICES) {
@ -386,7 +386,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// faces, too
if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
ReportError("Mesh contains no faces");
ReportError("Mesh %s contains no faces", pMesh->mName.C_Str());
}
// now check whether the face indexing layout is correct:

View File

@ -50,7 +50,7 @@ static const unsigned int MajorVersion = 4;
static const unsigned int MinorVersion = 1;
// --------------------------------------------------------------------------------
// Legal information string - dont't remove this.
// Legal information string - don't remove this.
static const char* LEGAL_INFORMATION =
"Open Asset Import Library (Assimp).\n"

View File

@ -26,7 +26,7 @@ namespace Assimp
/// Limitations.
///
/// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format.
/// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tesselation:
/// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tessellation:
/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all.
///
/// Supported nodes:

View File

@ -522,7 +522,7 @@ private:
/// \param [in] pStartAngle - angle in radians of start of the arc.
/// \param [in] pEndAngle - angle in radians of end of the arc.
/// \param [in] pRadius - radius of the arc.
/// \param [out] pNumSegments - number of segments in arc. In other words - tesselation factor.
/// \param [out] pNumSegments - number of segments in arc. In other words - tessellation factor.
/// \param [out] pVertices - generated vertices.
void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices);

View File

@ -136,7 +136,7 @@ void X3DImporter::ParseNode_Geometry3D_Cone()
}
else
{
const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tvec;// temp array for vertices.
@ -209,7 +209,7 @@ void X3DImporter::ParseNode_Geometry3D_Cylinder()
}
else
{
const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property
const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tside;// temp array for vertices of side.
std::vector<aiVector3D> tcir;// temp array for vertices of circle.
@ -480,7 +480,7 @@ static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx
tvec = pSpine[1] - pSpine[0];
}
else
{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about droping tail) spine[n - 1] is
{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
// the spine[0].
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
}
@ -967,7 +967,7 @@ void X3DImporter::ParseNode_Geometry3D_Sphere()
}
else
{
const unsigned int tess = 3;///TODO: IME tesselation factor through ai_property
const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property
std::vector<aiVector3D> tlist;

View File

@ -76,7 +76,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
@ -89,7 +89,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.

View File

@ -79,7 +79,7 @@ namespace Assimp
if(!mReader->isEmptyElement()) \
ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \
else \
NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manualy */ \
NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manually */ \
\
NodeElement_List.push_back(pNE);/* add new element to elements list. */ \
}/* if(!pUSE_Var.empty()) else */ \

View File

@ -132,7 +132,7 @@ void XFileExporter::WriteFile()
{
// note, that all realnumber values must be comma separated in x files
mOutput.setf(std::ios::fixed);
mOutput.precision(16); // precission for double
mOutput.precision(16); // precision for double
// entry of writing the file
WriteHeader();

View File

@ -498,7 +498,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
right = forward ^ up;
if (std::fabs(up * forward) > 1e-4) {
// this is definitely wrong - a degenerate coordinate space ruins everything
// so subtitute identity transform.
// so substitute identity transform.
LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
return m;
}

View File

@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* glTF Extensions Support:
* KHR_materials_pbrSpecularGlossiness full
* KHR_materials_unlit full
*/
#ifndef GLTF2ASSET_H_INC
#define GLTF2ASSET_H_INC
@ -386,7 +387,7 @@ namespace glTF2
};
//! Base classe for all glTF top-level objects
//! Base class for all glTF top-level objects
struct Object
{
int index; //!< The index of this object within its property container
@ -741,6 +742,9 @@ namespace glTF2
//extension: KHR_materials_pbrSpecularGlossiness
Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
//extension: KHR_materials_unlit
bool unlit;
Material() { SetDefaults(); }
void Read(Value& obj, Asset& r);
void SetDefaults();
@ -1037,6 +1041,7 @@ namespace glTF2
struct Extensions
{
bool KHR_materials_pbrSpecularGlossiness;
bool KHR_materials_unlit;
} extensionsUsed;

View File

@ -860,6 +860,8 @@ inline void Material::Read(Value& material, Asset& r)
this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
}
}
unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit");
}
}
@ -882,6 +884,7 @@ inline void Material::SetDefaults()
alphaMode = "OPAQUE";
alphaCutoff = 0.5;
doubleSided = false;
unlit = false;
}
inline void PbrSpecularGlossiness::SetDefaults()
@ -1213,12 +1216,15 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
// Read the "scene" property, which specifies which scene to load
// and recursively load everything referenced by it
unsigned int sceneIndex = 0;
if (Value* scene = FindUInt(doc, "scene")) {
unsigned int sceneIndex = scene->GetUint();
sceneIndex = scene->GetUint();
}
Ref<Scene> s = scenes.Retrieve(sceneIndex);
this->scene = s;
if (Value* scenesArray = FindArray(doc, "scenes")) {
if (sceneIndex < scenesArray->Size()) {
this->scene = scenes.Retrieve(sceneIndex);
}
}
// Clean up
@ -1253,6 +1259,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
CHECK_EXT(KHR_materials_unlit);
#undef CHECK_EXT
}

View File

@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* glTF Extensions Support:
* KHR_materials_pbrSpecularGlossiness: full
* KHR_materials_unlit: full
*/
#ifndef GLTF2ASSETWRITER_H_INC
#define GLTF2ASSETWRITER_H_INC

View File

@ -343,6 +343,12 @@ namespace glTF2 {
}
}
if (m.unlit) {
Value unlit;
unlit.SetObject();
exts.AddMember("KHR_materials_unlit", unlit, w.mAl);
}
if (!exts.ObjectEmpty()) {
obj.AddMember("extensions", exts, w.mAl);
}
@ -683,6 +689,10 @@ namespace glTF2 {
if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
}
if (this->mAsset.extensionsUsed.KHR_materials_unlit) {
exts.PushBack(StringRef("KHR_materials_unlit"), mAl);
}
}
if (!exts.Empty())

View File

@ -138,28 +138,29 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
}
}
glTF2Exporter::~glTF2Exporter() {
// empty
}
/*
* Copy a 4x4 matrix from struct aiMatrix to typedef mat4.
* Also converts from row-major to column-major storage.
*/
static void CopyValue(const aiMatrix4x4& v, mat4& o)
{
static void CopyValue(const aiMatrix4x4& v, mat4& o) {
o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1;
o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2;
o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3;
o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4;
}
static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
{
static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) {
o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
}
static void IdentityMatrix4(mat4& o)
{
static void IdentityMatrix4(mat4& o) {
o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0;
o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0;
o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0;
@ -169,7 +170,9 @@ static void IdentityMatrix4(mat4& o)
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
{
if (!count || !data) return Ref<Accessor>();
if (!count || !data) {
return Ref<Accessor>();
}
unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
unsigned int numCompsOut = AttribType::GetNumComponents(typeOut);
@ -511,9 +514,9 @@ void glTF2Exporter::ExportMaterials()
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR);
if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
float shininess;
float shininess;
if (mat->Get(AI_MATKEY_SHININESS, shininess)) {
if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
pbrSG.glossinessFactor = shininess / 1000;
}
}
@ -523,6 +526,12 @@ void glTF2Exporter::ExportMaterials()
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
}
bool unlit;
if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) {
mAsset->extensionsUsed.KHR_materials_unlit = true;
m->unlit = true;
}
}
}
@ -638,11 +647,11 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
Mesh::Primitive& p = meshRef->primitives.back();
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if ( vertexJointAccessor ) {
unsigned int offset = vertexJointAccessor->bufferView->byteOffset;
unsigned int bytesLen = vertexJointAccessor->bufferView->byteLength;
size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
unsigned int s_bytesPerComp= ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType);
unsigned int s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
uint8_t* arrys = new uint8_t[s_bytesLen];
unsigned int i = 0;
@ -728,8 +737,10 @@ void glTF2Exporter::ExportMeshes()
/******************** Normals ********************/
// Normalize all normals as the validator can emit a warning otherwise
for (auto i = 0u; i < aim->mNumVertices; ++i) {
aim->mNormals[i].Normalize();
if ( nullptr != aim->mNormals) {
for ( auto i = 0u; i < aim->mNumVertices; ++i ) {
aim->mNormals[ i ].Normalize();
}
}
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);

View File

@ -87,28 +87,15 @@ namespace Assimp
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to an glTF file. */
// ------------------------------------------------------------------------------------------------
class glTF2Exporter
{
class glTF2Exporter {
public:
/// Constructor for a specific scene to export
glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
const ExportProperties* pProperties, bool binary);
~glTF2Exporter();
private:
const char* mFilename;
IOSystem* mIOSystem;
const aiScene* mScene;
const ExportProperties* mProperties;
std::map<std::string, unsigned int> mTexturesByPath;
std::shared_ptr<glTF2::Asset> mAsset;
std::vector<unsigned char> mBodyData;
protected:
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
@ -126,6 +113,15 @@ namespace Assimp
unsigned int ExportNode(const aiNode* node, glTF2::Ref<glTF2::Node>& parent);
void ExportScene();
void ExportAnimations();
private:
const char* mFilename;
IOSystem* mIOSystem;
const aiScene* mScene;
const ExportProperties* mProperties;
std::map<std::string, unsigned int> mTexturesByPath;
std::shared_ptr<glTF2::Asset> mAsset;
std::vector<unsigned char> mBodyData;
};
}

View File

@ -121,6 +121,21 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
return false;
}
static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
{
switch (gltfWrapMode) {
case SamplerWrap::Mirrored_Repeat:
return aiTextureMapMode_Mirror;
case SamplerWrap::Clamp_To_Edge:
return aiTextureMapMode_Clamp;
case SamplerWrap::UNSET:
case SamplerWrap::Repeat:
default:
return aiTextureMapMode_Wrap;
}
}
//static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
//{
@ -198,8 +213,10 @@ inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset&
mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS);
aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT);
mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
if (sampler->magFilter != SamplerMagFilter::UNSET) {
mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
@ -281,6 +298,9 @@ static aiMaterial* ImportMaterial(std::vector<int>& embeddedTexIdxs, Asset& r, M
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
}
if (mat.unlit) {
aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT);
}
return aimat;
}

View File

@ -381,7 +381,7 @@ namespace glTF
};
//! Base classe for all glTF top-level objects
//! Base class for all glTF top-level objects
struct Object
{
std::string id; //!< The globally unique ID used to reference this object

View File

@ -703,7 +703,7 @@ void glTFExporter::ExportMeshes()
// Coordinates indices
comp_o3dgc_ifs.SetNCoordIndex(aim->mNumFaces);
comp_o3dgc_ifs.SetCoordIndex((IndicesType* const)&b->GetPointer()[idx_srcdata_ind]);
// Prepare to enconding
// Prepare to encoding
comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes());
if(mProperties->GetPropertyBool("extensions.Open3DGC.binary", true))
comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY);

View File

@ -164,7 +164,7 @@ If done correctly you should now be able to compile, link, run and use the appli
@section install_own Building the library from scratch
First you need to install cmake. Now just get the code from github or download the latest version from the webside.
to buil the library just open a command-prompt / bash, navigate into the repo-folder and run cmake via:
to build the library just open a command-prompt / bash, navigate into the repo-folder and run cmake via:
@code
cmake CMakeLists.txt
@ -653,7 +653,7 @@ To apply such an animation you need to identify the animation tracks that refer
in your mesh. Then for every track: <br>
a) Find the keys that lay right before the current anim time. <br>
b) Optional: interpolate between these and the following keys. <br>
c) Combine the calculated position, rotation and scaling to a tranformation matrix <br>
c) Combine the calculated position, rotation and scaling to a transformation matrix <br>
d) Set the affected node's transformation to the calculated matrix. <br>
If you need hints on how to convert to or from quaternions, have a look at the
@ -669,7 +669,7 @@ Such textures are loaded into an aiTexture structure.
In previous versions, the path from the query for `AI_MATKEY_TEXTURE(textureType, index)` would be
`*<index>` where `<index>` is the index of the texture in aiScene::mTextures. Now this call will
return a file path for embedded textures in FBX files. To test if it is an embdedded texture use
return a file path for embedded textures in FBX files. To test if it is an embedded texture use
aiScene::GetEmbeddedTexture. If the returned pointer is not null, it is embedded und can be loaded
from the data structure. If it is null, search for a separate file. Other file types still use the
old behaviour.<br>
@ -794,7 +794,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor
<td><tt>COLOR_REFLECTIVE</tt></td>
<td>aiColor3D</td>
<td>black (0,0,0)</td>
<td>Defines the reflective color of the material. This is typically scaled by the amount of incoming light from the direction of mirror reflection. Usually combined with an enviroment lightmap of some kind for real-time applications.</td>
<td>Defines the reflective color of the material. This is typically scaled by the amount of incoming light from the direction of mirror reflection. Usually combined with an environment lightmap of some kind for real-time applications.</td>
<td>---</td>
</tr>
@ -819,7 +819,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor
<td>int</td>
<td>false</td>
<td>Specifies whether meshes using this material must be rendered without backface culling. 0 for false, !0 for true. </td>
<td>Some importers set this property if they don't know whether the output face oder is right. As long as it is not set, you may safely enable backface culling.</tt></td>
<td>Some importers set this property if they don't know whether the output face order is right. As long as it is not set, you may safely enable backface culling.</tt></td>
</tr>
<tr>

View File

@ -134,6 +134,30 @@ public:
}
}
// ----------------------------------------------------------------------------
/** Extract a particular vertex from a anim mesh and interleave all components */
explicit Vertex(const aiAnimMesh* msh, unsigned int idx) {
ai_assert(idx < msh->mNumVertices);
position = msh->mVertices[idx];
if (msh->HasNormals()) {
normal = msh->mNormals[idx];
}
if (msh->HasTangentsAndBitangents()) {
tangent = msh->mTangents[idx];
bitangent = msh->mBitangents[idx];
}
for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
texcoords[i] = msh->mTextureCoords[i][idx];
}
for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
colors[i] = msh->mColors[i][idx];
}
}
public:
Vertex& operator += (const Vertex& v) {

View File

@ -149,7 +149,8 @@ struct aiMetadata {
mValues[ i ].mType = rhs.mValues[ i ].mType;
switch ( rhs.mValues[ i ].mType ) {
case AI_BOOL:
mValues[ i ].mData = new bool( rhs.mValues[i].mData );
mValues[ i ].mData = new bool;
::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) );
break;
case AI_INT32: {
int32_t v;

View File

@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0
#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
#define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"

View File

@ -98,8 +98,10 @@ AI_FORCE_INLINE bool is_qnan(float in)
// compare <register-with-different-width> against <in>
// FIXME: Use <float> stuff instead? I think fpclassify needs C99
return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 &&
reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac);
_IEEESingle temp;
memcpy(&temp, &in, sizeof(float));
return (temp.IEEE.Exp == (1u << 8)-1 &&
temp.IEEE.Frac);
}
// ---------------------------------------------------------------------------
@ -114,8 +116,10 @@ AI_FORCE_INLINE bool is_qnan(double in)
// compare <register-with-different-width> against <in>
// FIXME: Use <float> stuff instead? I think fpclassify needs C99
return (reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1 &&
reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Frac);
_IEEEDouble temp;
memcpy(&temp, &in, sizeof(in));
return (temp.IEEE.Exp == (1u << 11)-1 &&
temp.IEEE.Frac);
}
// ---------------------------------------------------------------------------
@ -125,7 +129,9 @@ AI_FORCE_INLINE bool is_qnan(double in)
* @param in Input value */
AI_FORCE_INLINE bool is_special_float(float in)
{
return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1);
_IEEESingle temp;
memcpy(&temp, &in, sizeof(float));
return (temp.IEEE.Exp == (1u << 8)-1);
}
// ---------------------------------------------------------------------------
@ -135,7 +141,9 @@ AI_FORCE_INLINE bool is_special_float(float in)
* @param in Input value */
AI_FORCE_INLINE bool is_special_float(double in)
{
return (reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1);
_IEEESingle temp;
memcpy(&temp, &in, sizeof(float));
return (temp.IEEE.Exp == (1u << 11)-1);
}
// ---------------------------------------------------------------------------

View File

@ -1 +1 @@
See https://code.google.com/p/assimp-net/ and https://github.com/assimp/assimp-net for a Github mirror.
Please check the following github-repo for the source: https://github.com/kebby/assimp-net

View File

@ -1,94 +0,0 @@
PyAssimp Readme
===============
A simple Python wrapper for Assimp using `ctypes` to access the library.
Requires Python >= 2.6.
Python 3 support is mostly here, but not well tested.
Note that pyassimp is not complete. Many ASSIMP features are missing.
USAGE
-----
### Complete example: 3D viewer
`pyassimp` comes with a simple 3D viewer that shows how to load and display a 3D
model using a shader-based OpenGL pipeline.
![Screenshot](3d_viewer_screenshot.png)
To use it, from within `/port/PyAssimp`:
```
$ cd scripts
$ python ./3D-viewer <path to your model>
```
You can use this code as starting point in your applications.
### Writing your own code
To get started with `pyassimp`, examine the simpler `sample.py` script in `scripts/`,
which illustrates the basic usage. All Assimp data structures are wrapped using
`ctypes`. All the data+length fields in Assimp's data structures (such as
`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python
lists, so you can call `len()` on them to get their respective size and access
members using `[]`.
For example, to load a file named `hello.3ds` and print the first
vertex of the first mesh, you would do (proper error handling
substituted by assertions ...):
```python
from pyassimp import *
scene = load('hello.3ds')
assert len(scene.meshes)
mesh = scene.meshes[0]
assert len(mesh.vertices)
print(mesh.vertices[0])
# don't forget this one, or you will leak!
release(scene)
```
Another example to list the 'top nodes' in a
scene:
```python
from pyassimp import *
scene = load('hello.3ds')
for c in scene.rootnode.children:
print(str(c))
release(scene)
```
INSTALL
-------
Install `pyassimp` by running:
```
$ python setup.py install
```
PyAssimp requires a assimp dynamic library (`DLL` on windows,
`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories
are:
- the current directory
- on linux additionally: `/usr/lib`, `/usr/local/lib`,
`/usr/lib/x86_64-linux-gnu`
To build that library, refer to the Assimp master `INSTALL`
instructions. To look in more places, edit `./pyassimp/helper.py`.
There's an `additional_dirs` list waiting for your entries.

View File

@ -0,0 +1,96 @@
PyAssimp: Python bindings for libassimp
=======================================
A simple Python wrapper for Assimp using ``ctypes`` to access the
library. Requires Python >= 2.6.
Python 3 support is mostly here, but not well tested.
Note that pyassimp is not complete. Many ASSIMP features are missing.
USAGE
-----
Complete example: 3D viewer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
``pyassimp`` comes with a simple 3D viewer that shows how to load and
display a 3D model using a shader-based OpenGL pipeline.
.. figure:: 3d_viewer_screenshot.png
:alt: Screenshot
Screenshot
To use it, from within ``/port/PyAssimp``:
::
$ cd scripts
$ python ./3D-viewer <path to your model>
You can use this code as starting point in your applications.
Writing your own code
~~~~~~~~~~~~~~~~~~~~~
To get started with ``pyassimp``, examine the simpler ``sample.py``
script in ``scripts/``, which illustrates the basic usage. All Assimp
data structures are wrapped using ``ctypes``. All the data+length fields
in Assimp's data structures (such as ``aiMesh::mNumVertices``,
``aiMesh::mVertices``) are replaced by simple python lists, so you can
call ``len()`` on them to get their respective size and access members
using ``[]``.
For example, to load a file named ``hello.3ds`` and print the first
vertex of the first mesh, you would do (proper error handling
substituted by assertions ...):
.. code:: python
from pyassimp import *
scene = load('hello.3ds')
assert len(scene.meshes)
mesh = scene.meshes[0]
assert len(mesh.vertices)
print(mesh.vertices[0])
# don't forget this one, or you will leak!
release(scene)
Another example to list the 'top nodes' in a scene:
.. code:: python
from pyassimp import *
scene = load('hello.3ds')
for c in scene.rootnode.children:
print(str(c))
release(scene)
INSTALL
-------
Install ``pyassimp`` by running:
::
$ python setup.py install
PyAssimp requires a assimp dynamic library (``DLL`` on windows, ``.so``
on linux, ``.dynlib`` on macOS) in order to work. The default search
directories are:
- the current directory
- on linux additionally: ``/usr/lib``, ``/usr/local/lib``,
``/usr/lib/x86_64-linux-gnu``
To build that library, refer to the Assimp master ``INSTALL``
instructions. To look in more places, edit ``./pyassimp/helper.py``.
There's an ``additional_dirs`` list waiting for your entries.

View File

@ -312,7 +312,7 @@ def load(filename,
file_type)
else:
# a filename string has been passed
model = _assimp_lib.load(filename.encode("ascii"), processing)
model = _assimp_lib.load(filename.encode(sys.getfilesystemencoding()), processing)
if not model:
raise AssimpError('Could not import file!')
@ -342,7 +342,7 @@ def export(scene,
'''
from ctypes import pointer
exportStatus = _assimp_lib.export(pointer(scene), file_type.encode("ascii"), filename.encode("ascii"), processing)
exportStatus = _assimp_lib.export(pointer(scene), file_type.encode("ascii"), filename.encode(sys.getfilesystemencoding()), processing)
if exportStatus != 0:
raise AssimpError('Could not export scene!')

View File

@ -1,15 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from distutils.core import setup
def readme():
with open('README.rst') as f:
return f.read()
setup(name='pyassimp',
version='4.1.0',
version='4.1.3',
license='ISC',
description='Python bindings for the Open Asset Import Library (ASSIMP)',
long_description=readme(),
url='https://github.com/assimp/assimp',
author='ASSIMP developers',
author_email='assimp-discussions@lists.sourceforge.net',
maintainer='SĂ©verin Lemaignan',
maintainer_email='severin@guakamole.org',
packages=['pyassimp'],
data_files=[
('share/pyassimp', ['README.md']),
('share/pyassimp', ['README.rst']),
('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])
],
requires=['numpy']

View File

@ -59,9 +59,9 @@ build_arch()
$XCODE_ROOT_DIR/Developer/usr/bin/make clean
$XCODE_ROOT_DIR/Developer/usr/bin/make assimp -j 8 -l
echo "[!] Moving built library into: $BUILD_DIR/$1/"
echo "[!] Moving built libraries into: $BUILD_DIR/$1/"
mv ./lib/libassimp.a $BUILD_DIR/$1/
mv ./lib/*.a $BUILD_DIR/$1/
}
echo "[!] $0 - assimp iOS build script"
@ -110,14 +110,27 @@ for ARCH_TARGET in $DEPLOY_ARCHS; do
#rm ./lib/libassimp.a
done
if [[ "$DEPLOY_FAT" -eq 1 ]]; then
echo '[+] Creating fat binary ...'
make_fat_binary()
{
LIB_NAME=$1
LIPO_ARGS=''
for ARCH_TARGET in $DEPLOY_ARCHS; do
LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/libassimp.a "
LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.a "
done
LIPO_ARGS="$LIPO_ARGS-create -output $BUILD_DIR/libassimp-fat.a"
LIPO_ARGS="$LIPO_ARGS-create -output $BUILD_DIR/$LIB_NAME-fat.a"
lipo $LIPO_ARGS
echo "[!] Done! The fat binary can be found at $BUILD_DIR"
}
if [[ "$DEPLOY_FAT" -eq 1 ]]; then
echo '[+] Creating fat binaries ...'
make_fat_binary 'libassimp'
make_fat_binary 'libIrrXML'
make_fat_binary 'libzlibstatic'
echo "[!] Done! The fat binaries can be found at $BUILD_DIR"
fi

View File

@ -0,0 +1,11 @@
solid testTriangle
facet normal 0.0 0.0 1.0
outer loop
vertex 1.0 1.0 0.0
vertex -1.0 1.0 0.0
vertex 0.0 -1.0 0.0
endloop
endfacet
endsolid
solid emptySolid
endsolid

View File

@ -146,8 +146,8 @@
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
"wrapS": 33648,
"wrapT": 33071
}
],
"bufferViews": [

View File

@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "UnitTestPCH.h"
#include "AbstractImportExportBase.h"
#include <assimp/postprocess.h>
#include <assimp/Importer.hpp>
@ -52,13 +53,90 @@ class utLWSImportExport : public AbstractImportExportBase {
public:
virtual bool importerTest() {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWS/move_x.lws", 0 );
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWS/move_x.lws", aiProcess_ValidateDataStructure);
return nullptr != scene;
return true;
}
};
TEST_F( utLWSImportExport, importLWSFromFileTest ) {
EXPECT_TRUE( importerTest() );
}
TEST_F(utLWSImportExport, importLWSmove_x_post_linear) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_linear.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_xz_bezier) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_bezier.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_xz_stepped) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_stepped.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_oldformat_56) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_oldformat_56.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_post_offset_repeat) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_offset_repeat.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_xz_hermite) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_hermite.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_y_pre_ofrep_post_osc) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_y_pre_ofrep_post_osc.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_oldformat_6) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_oldformat_6.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_post_repeat) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_repeat.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_xz_linear) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_linear.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_post_constant) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_constant.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_x_post_reset) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_reset.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}
TEST_F(utLWSImportExport, importLWSmove_xz_spline) {
::Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_spline.lws", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
}

View File

@ -210,7 +210,7 @@ TEST_F( utMetadata, copy_test ) {
// int32_t test
{
int32_t v;
int32_t v = 0;
bool ok = copy.Get( "int32", v );
EXPECT_TRUE( ok );
EXPECT_EQ( i32v, v );

View File

@ -73,6 +73,16 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) {
EXPECT_NE( nullptr, scene );
}
TEST_F(utSTLImporterExporter, test_with_empty_solid) {
Assimp::Importer importer;
//STL File with empty mesh. We should still be able to import other meshes in this file. ValidateDataStructure should fail.
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_empty_solid.stl", 0);
EXPECT_NE(nullptr, scene);
const aiScene *scene2 = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_empty_solid.stl", aiProcess_ValidateDataStructure);
EXPECT_EQ(nullptr, scene2);
}
#ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F(utSTLImporterExporter, exporterTest) {

View File

@ -78,7 +78,7 @@ TEST_F(SharedPPDataTest, testPODProperty)
{
int i = 5;
shared->AddProperty("test",i);
int o;
int o = 0;
EXPECT_TRUE(shared->GetProperty("test",o));
EXPECT_EQ(5, o);
EXPECT_FALSE(shared->GetProperty("test2",o));

View File

@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
using namespace Assimp;
@ -54,7 +55,21 @@ public:
virtual bool importerTest() {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure);
return nullptr != scene;
EXPECT_NE( scene, nullptr );
if ( !scene ) return false;
EXPECT_TRUE( scene->HasMaterials() );
if ( !scene->HasMaterials() ) return false;
const aiMaterial *material = scene->mMaterials[0];
aiString path;
aiTextureMapMode modes[2];
EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes) );
EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" );
EXPECT_EQ( modes[0], aiTextureMapMode_Mirror );
EXPECT_EQ( modes[1], aiTextureMapMode_Clamp );
return true;
}
virtual bool binaryImporterTest() {
@ -89,4 +104,5 @@ TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) {
TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) {
EXPECT_TRUE( exporterTest() );
}
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -106,7 +106,8 @@ int Assimp_Export(const char* const* params, unsigned int num)
continue;
}
if (!strncmp( params[i], "-f",2)) {
outf = std::string(params[i]+2);
if ( strncmp( params[ i ], "-fi",3 ))
outf = std::string(params[i]+2);
}
else if ( !strncmp( params[i], "--format=",9)) {
outf = std::string(params[i]+9);

View File

@ -261,7 +261,6 @@ void PrintHorBar()
printf("-----------------------------------------------------------------\n");
}
// ------------------------------------------------------------------------------
// Import a specific file
const aiScene* ImportModel(
@ -390,105 +389,101 @@ int ProcessStandardArguments(
for (unsigned int i = 0; i < num;++i)
{
if (! strcmp(params[i], "-ptv") || ! strcmp(params[i], "--pretransform-vertices")) {
const char *param = params[ i ];
printf( "param = %s\n", param );
if (! strcmp( param, "-ptv") || ! strcmp( param, "--pretransform-vertices")) {
fill.ppFlags |= aiProcess_PreTransformVertices;
}
else if (! strcmp(params[i], "-gsn") || ! strcmp(params[i], "--gen-smooth-normals")) {
else if (! strcmp( param, "-gsn") || ! strcmp( param, "--gen-smooth-normals")) {
fill.ppFlags |= aiProcess_GenSmoothNormals;
}
else if (! strcmp(params[i], "-gn") || ! strcmp(params[i], "--gen-normals")) {
else if (! strcmp( param, "-gn") || ! strcmp( param, "--gen-normals")) {
fill.ppFlags |= aiProcess_GenNormals;
}
else if (! strcmp(params[i], "-jiv") || ! strcmp(params[i], "--join-identical-vertices")) {
else if (! strcmp( param, "-jiv") || ! strcmp( param, "--join-identical-vertices")) {
fill.ppFlags |= aiProcess_JoinIdenticalVertices;
}
else if (! strcmp(params[i], "-rrm") || ! strcmp(params[i], "--remove-redundant-materials")) {
else if (! strcmp( param, "-rrm") || ! strcmp( param, "--remove-redundant-materials")) {
fill.ppFlags |= aiProcess_RemoveRedundantMaterials;
}
else if (! strcmp(params[i], "-fd") || ! strcmp(params[i], "--find-degenerates")) {
else if (! strcmp( param, "-fd") || ! strcmp( param, "--find-degenerates")) {
fill.ppFlags |= aiProcess_FindDegenerates;
}
else if (! strcmp(params[i], "-slm") || ! strcmp(params[i], "--split-large-meshes")) {
else if (! strcmp( param, "-slm") || ! strcmp( param, "--split-large-meshes")) {
fill.ppFlags |= aiProcess_SplitLargeMeshes;
}
else if (! strcmp(params[i], "-lbw") || ! strcmp(params[i], "--limit-bone-weights")) {
else if (! strcmp( param, "-lbw") || ! strcmp( param, "--limit-bone-weights")) {
fill.ppFlags |= aiProcess_LimitBoneWeights;
}
else if (! strcmp(params[i], "-vds") || ! strcmp(params[i], "--validate-data-structure")) {
else if (! strcmp( param, "-vds") || ! strcmp( param, "--validate-data-structure")) {
fill.ppFlags |= aiProcess_ValidateDataStructure;
}
else if (! strcmp(params[i], "-icl") || ! strcmp(params[i], "--improve-cache-locality")) {
else if (! strcmp( param, "-icl") || ! strcmp( param, "--improve-cache-locality")) {
fill.ppFlags |= aiProcess_ImproveCacheLocality;
}
else if (! strcmp(params[i], "-sbpt") || ! strcmp(params[i], "--sort-by-ptype")) {
else if (! strcmp( param, "-sbpt") || ! strcmp( param, "--sort-by-ptype")) {
fill.ppFlags |= aiProcess_SortByPType;
}
else if (! strcmp(params[i], "-lh") || ! strcmp(params[i], "--left-handed")) {
else if (! strcmp( param, "-lh") || ! strcmp( param, "--left-handed")) {
fill.ppFlags |= aiProcess_ConvertToLeftHanded;
}
else if (! strcmp(params[i], "-fuv") || ! strcmp(params[i], "--flip-uv")) {
else if (! strcmp( param, "-fuv") || ! strcmp( param, "--flip-uv")) {
fill.ppFlags |= aiProcess_FlipUVs;
}
else if (! strcmp(params[i], "-fwo") || ! strcmp(params[i], "--flip-winding-order")) {
else if (! strcmp( param, "-fwo") || ! strcmp( param, "--flip-winding-order")) {
fill.ppFlags |= aiProcess_FlipWindingOrder;
}
else if (! strcmp(params[i], "-tuv") || ! strcmp(params[i], "--transform-uv-coords")) {
else if (! strcmp( param, "-tuv") || ! strcmp( param, "--transform-uv-coords")) {
fill.ppFlags |= aiProcess_TransformUVCoords;
}
else if (! strcmp(params[i], "-guv") || ! strcmp(params[i], "--gen-uvcoords")) {
else if (! strcmp( param, "-guv") || ! strcmp( param, "--gen-uvcoords")) {
fill.ppFlags |= aiProcess_GenUVCoords;
}
else if (! strcmp(params[i], "-fid") || ! strcmp(params[i], "--find-invalid-data")) {
else if (! strcmp( param, "-fid") || ! strcmp( param, "--find-invalid-data")) {
fill.ppFlags |= aiProcess_FindInvalidData;
}
else if (! strcmp(params[i], "-fixn") || ! strcmp(params[i], "--fix-normals")) {
else if (! strcmp( param, "-fixn") || ! strcmp( param, "--fix-normals")) {
fill.ppFlags |= aiProcess_FixInfacingNormals;
}
else if (! strcmp(params[i], "-tri") || ! strcmp(params[i], "--triangulate")) {
else if (! strcmp( param, "-tri") || ! strcmp( param, "--triangulate")) {
fill.ppFlags |= aiProcess_Triangulate;
}
else if (! strcmp(params[i], "-cts") || ! strcmp(params[i], "--calc-tangent-space")) {
else if (! strcmp( param, "-cts") || ! strcmp( param, "--calc-tangent-space")) {
fill.ppFlags |= aiProcess_CalcTangentSpace;
}
else if (! strcmp(params[i], "-fi") || ! strcmp(params[i], "--find-instances")) {
else if (! strcmp( param, "-fi") || ! strcmp( param, "--find-instances")) {
fill.ppFlags |= aiProcess_FindInstances;
}
else if (! strcmp(params[i], "-og") || ! strcmp(params[i], "--optimize-graph")) {
else if (! strcmp( param, "-og") || ! strcmp( param, "--optimize-graph")) {
fill.ppFlags |= aiProcess_OptimizeGraph;
}
else if (! strcmp(params[i], "-om") || ! strcmp(params[i], "--optimize-meshes")) {
else if (! strcmp( param, "-om") || ! strcmp( param, "--optimize-meshes")) {
fill.ppFlags |= aiProcess_OptimizeMeshes;
}
else if (! strcmp(params[i], "-db") || ! strcmp(params[i], "--debone")) {
else if (! strcmp( param, "-db") || ! strcmp( param, "--debone")) {
fill.ppFlags |= aiProcess_Debone;
}
else if (! strcmp(params[i], "-sbc") || ! strcmp(params[i], "--split-by-bone-count")) {
else if (! strcmp( param, "-sbc") || ! strcmp( param, "--split-by-bone-count")) {
fill.ppFlags |= aiProcess_SplitByBoneCount;
}
else if (! strncmp(params[i], "-c",2) || ! strncmp(params[i], "--config=",9)) {
else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) {
const unsigned int ofs = (params[i][1] == '-' ? 9 : 2);
// use default configurations
if (! strncmp(params[i]+ofs,"full",4)) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
}
else if (! strncmp(params[i]+ofs,"default",7)) {
if (!strncmp( param + ofs, "full", 4 )) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality;
} else if (!strncmp( param + ofs, "default", 7 )) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_Quality;
}
else if (! strncmp(params[i]+ofs,"fast",4)) {
} else if (! strncmp( param +ofs,"fast",4)) {
fill.ppFlags |= aiProcessPreset_TargetRealtime_Fast;
}
}
else if (! strcmp(params[i], "-l") || ! strcmp(params[i], "--show-log")) {
} else if (! strcmp( param, "-l") || ! strcmp( param, "--show-log")) {
fill.showLog = true;
}
else if (! strcmp(params[i], "-v") || ! strcmp(params[i], "--verbose")) {
else if (! strcmp( param, "-v") || ! strcmp( param, "--verbose")) {
fill.verbose = true;
}
else if (! strncmp(params[i], "--log-out=",10) || ! strncmp(params[i], "-lo",3)) {
else if (! strncmp( param, "--log-out=",10) || ! strncmp( param, "-lo",3)) {
fill.logFile = std::string(params[i]+(params[i][1] == '-' ? 10 : 3));
if (!fill.logFile.length()) {
fill.logFile = "assimp-log.txt";

View File

@ -3,43 +3,103 @@ project(assimp_qt_viewer)
cmake_minimum_required(VERSION 2.6)
find_package(Qt5Widgets REQUIRED)
find_package(DevIL REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(
${Qt5Widgets_INCLUDES}
${Assimp_SOURCE_DIR}/include
${Assimp_SOURCE_DIR}/code
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}
${OPENGL_INCLUDE_DIR}
${IL_INCLUDE_DIR}
OPTION( ASSIMP_QT4_VIEWER
"Set to ON to enable Qt4 against Qt5 for assimp_qt_viewer"
OFF
)
link_directories(${Assimp_BINARY_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall")
FIND_PACKAGE(DevIL QUIET)
FIND_PACKAGE(OpenGL QUIET)
set(assimp_qt_viewer_SRCS main.cpp loggerview.cpp glview.cpp mainwindow.cpp)
qt5_wrap_ui(UISrcs mainwindow.ui)
qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
IF(ASSIMP_QT4_VIEWER)
# Qt4 version
FIND_PACKAGE(Qt4 QUIET)
ELSE(ASSIMP_QT4_VIEWER)
# Qt5 version
FIND_PACKAGE(Qt5 COMPONENTS Gui Widgets OpenGL QUIET)
ENDIF(ASSIMP_QT4_VIEWER)
add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp)
SET(VIEWER_BUILD:BOOL FALSE)
qt5_use_modules(${PROJECT_NAME} Widgets OpenGL)
if(WIN32) # Check if we are on Windows
if(MSVC) # Check if we are using the Visual Studio compiler
#set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
elseif(CMAKE_COMPILER_IS_GNUCXX)
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested
else()
message(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)")
endif()
elseif(UNIX)
# Nothing special required
else()
message(SEND_ERROR "You are on an unsupported platform! (Not Win32 or Unix)")
endif()
IF((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND)
SET(VIEWER_BUILD TRUE)
set_property(TARGET ${PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
ELSE((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
IF(ASSIMP_QT4_VIEWER)
IF (NOT Qt4_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt4")
ENDIF (NOT Qt4_FOUND)
ELSE(ASSIMP_QT4_VIEWER)
IF (NOT Qt5_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
ENDIF (NOT Qt5_FOUND)
ENDIF(ASSIMP_QT4_VIEWER)
IF (NOT IL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
ENDIF (NOT IL_FOUND)
IF (NOT OPENGL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
ENDIF (NOT OPENGL_FOUND)
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
ENDIF((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND)
IF(VIEWER_BUILD)
INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/include
${Assimp_SOURCE_DIR}/code
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}
${OPENGL_INCLUDE_DIR}
${IL_INCLUDE_DIR}
)
LINK_DIRECTORIES(${Assimp_BINARY_DIR})
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall")
SET(assimp_qt_viewer_SRCS main.cpp loggerview.cpp glview.cpp mainwindow.cpp)
IF(ASSIMP_QT4_VIEWER)
MESSAGE("assimp_qt_viewer use Qt4")
ADD_DEFINITIONS( -DASSIMP_QT4_VIEWER )
INCLUDE_DIRECTORIES(${QT_INCLUDES})
qt4_wrap_ui(UISrcs mainwindow.ui)
qt4_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
ELSE()
MESSAGE("assimp_qt_viewer use Qt5")
INCLUDE_DIRECTORIES(${Qt5Widgets_INCLUDES})
qt5_wrap_ui(UISrcs mainwindow.ui)
qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
ENDIF()
add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs})
IF(ASSIMP_QT4_VIEWER)
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp)
ELSE()
target_link_libraries(${PROJECT_NAME} Qt5::Gui Qt5::Widgets Qt5::OpenGL ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp)
ENDIF()
IF(WIN32) # Check if we are on Windows
IF(MSVC) # Check if we are using the Visual Studio compiler
#set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
ELSEIF(CMAKE_COMPILER_IS_GNUCXX)
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested
ELSE()
MESSAGE(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)")
ENDIF()
ELSEIF(UNIX)
# Nothing special required
ELSE()
MESSAGE(SEND_ERROR "You are on an unsupported platform! (Not Win32 or Unix)")
ENDIF()
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS assimp_qt_viewer DESTINATION "${ASSIMP_BIN_INSTALL_DIR}")
ENDIF(VIEWER_BUILD)

View File

@ -5,6 +5,9 @@
#include "glview.hpp"
// Header files, Qt.
#include <QTime>
// Header files, OpenGL.
#if defined(__APPLE__)
# include <OpenGL/glu.h>
@ -58,6 +61,33 @@ void CGLView::SHelper_Camera::SetDefault()
/************ CGLView *************/
/**********************************/
#if !ASSIMP_QT4_VIEWER
# define ConditionalContextControl_Begin \
bool ContextEnabledHere; \
\
if(mGLContext_Current) \
{ \
ContextEnabledHere = false; \
} \
else \
{ \
makeCurrent(); \
mGLContext_Current = true; \
ContextEnabledHere = true; \
} \
\
do {} while(false)
# define ConditionalContextControl_End \
if(ContextEnabledHere) \
{ \
doneCurrent(); \
mGLContext_Current = false; \
} \
\
do {} while(false)
#endif // ASSIMP_QT4_VIEWER
void CGLView::Material_Apply(const aiMaterial* pMaterial)
{
GLfloat tcol[4];
@ -105,7 +135,7 @@ void CGLView::Material_Apply(const aiMaterial* pMaterial)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, tcol);
// Shininess
float shininess, strength;
ai_real shininess, strength;
max = 1;
ret1 = aiGetMaterialFloatArray(pMaterial, AI_MATKEY_SHININESS, &shininess, &max);
@ -406,9 +436,9 @@ void CGLView::BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVe
for(size_t idx_vert = 1; idx_vert < pVerticesQuantity; idx_vert++)
{
const GLfloat x = pVertices[idx_vert].x;
const GLfloat y = pVertices[idx_vert].y;
const GLfloat z = pVertices[idx_vert].z;
const ai_real x = pVertices[idx_vert].x;
const ai_real y = pVertices[idx_vert].y;
const ai_real z = pVertices[idx_vert].z;
// search minimal...
AssignIfLesser(&pBBox.Minimum.x, x);
@ -446,7 +476,12 @@ void CGLView::Draw_Node(const aiNode* pNode)
// Apply node transformation matrix.
mat_node.Transpose();
glPushMatrix();
#if ASSIMP_DOUBLE_PRECISION
glMultMatrixd((GLdouble*)mat_node[0]);
#else
glMultMatrixf((GLfloat*)&mat_node);
#endif // ASSIMP_DOUBLE_PRECISION
// Draw all meshes assigned to this node
for(size_t idx_mesh_arr = 0; idx_mesh_arr < pNode->mNumMeshes; idx_mesh_arr++) Draw_Mesh(pNode->mMeshes[idx_mesh_arr]);
@ -473,13 +508,21 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index)
// Vertices array
//
glEnableClientState(GL_VERTEX_ARRAY);
#if ASSIMP_DOUBLE_PRECISION
glVertexPointer(3, GL_DOUBLE, 0, mesh_cur.mVertices);
#else
glVertexPointer(3, GL_FLOAT, 0, mesh_cur.mVertices);
#endif // ASSIMP_DOUBLE_PRECISION
if(mesh_cur.HasVertexColors(0))
{
glEnable(GL_COLOR_MATERIAL);///TODO: cache
glEnableClientState(GL_COLOR_ARRAY);
#if ASSIMP_DOUBLE_PRECISION
glColorPointer(4, GL_DOUBLE, 0, mesh_cur.mColors[0]);
#else
glColorPointer(4, GL_FLOAT, 0, mesh_cur.mColors[0]);
#endif // ASSIMP_DOUBLE_PRECISION
}
//
@ -488,7 +531,11 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index)
if(mesh_cur.HasTextureCoords(0))
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if ASSIMP_DOUBLE_PRECISION
glTexCoordPointer(2, GL_DOUBLE, sizeof(aiVector3D), mesh_cur.mTextureCoords[0]);
#else
glTexCoordPointer(2, GL_FLOAT, sizeof(aiVector3D), mesh_cur.mTextureCoords[0]);
#endif // ASSIMP_DOUBLE_PRECISION
}
//
@ -497,7 +544,11 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index)
if(mesh_cur.HasNormals())
{
glEnableClientState(GL_NORMAL_ARRAY);
#if ASSIMP_DOUBLE_PRECISION
glNormalPointer(GL_DOUBLE, 0, mesh_cur.mNormals);
#else
glNormalPointer(GL_FLOAT, 0, mesh_cur.mNormals);
#endif // ASSIMP_DOUBLE_PRECISION
}
//
@ -530,22 +581,46 @@ void CGLView::Draw_BBox(const SBBox& pBBox)
glBindTexture(GL_TEXTURE_1D, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_3D, 0);
#if ASSIMP_QT4_VIEWER
qglColor(QColor(Qt::white));
#else
const QColor c_w(Qt::white);
glColor3f(c_w.redF(), c_w.greenF(), c_w.blueF());
#endif // ASSIMP_QT4_VIEWER
glBegin(GL_LINE_STRIP);
# if ASSIMP_DOUBLE_PRECISION
glVertex3dv(&vertex[0][0]), glVertex3dv(&vertex[1][0]), glVertex3dv(&vertex[2][0]), glVertex3dv(&vertex[3][0]), glVertex3dv(&vertex[0][0]);// "Minimum" side.
glVertex3dv(&vertex[4][0]), glVertex3dv(&vertex[5][0]), glVertex3dv(&vertex[6][0]), glVertex3dv(&vertex[7][0]), glVertex3dv(&vertex[4][0]);// Edge and "maximum" side.
# else
glVertex3fv(&vertex[0][0]), glVertex3fv(&vertex[1][0]), glVertex3fv(&vertex[2][0]), glVertex3fv(&vertex[3][0]), glVertex3fv(&vertex[0][0]);// "Minimum" side.
glVertex3fv(&vertex[4][0]), glVertex3fv(&vertex[5][0]), glVertex3fv(&vertex[6][0]), glVertex3fv(&vertex[7][0]), glVertex3fv(&vertex[4][0]);// Edge and "maximum" side.
# endif // ASSIMP_DOUBLE_PRECISION
glEnd();
glBegin(GL_LINES);
# if ASSIMP_DOUBLE_PRECISION
glVertex3dv(&vertex[1][0]), glVertex3dv(&vertex[5][0]);
glVertex3dv(&vertex[2][0]), glVertex3dv(&vertex[6][0]);
glVertex3dv(&vertex[3][0]), glVertex3dv(&vertex[7][0]);
# else
glVertex3fv(&vertex[1][0]), glVertex3fv(&vertex[5][0]);
glVertex3fv(&vertex[2][0]), glVertex3fv(&vertex[6][0]);
glVertex3fv(&vertex[3][0]), glVertex3fv(&vertex[7][0]);
# endif // ASSIMP_DOUBLE_PRECISION
glEnd();
glDisable(GL_COLOR_MATERIAL);
if(mLightingEnabled) glEnable(GL_LIGHTING);
}
void CGLView::Enable_Textures(const bool pEnable)
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
if(pEnable)
{
glEnable(GL_TEXTURE_1D);
@ -558,30 +633,10 @@ void CGLView::Enable_Textures(const bool pEnable)
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
}
}
void CGLView::Enable_Axes(const bool pEnable){
if(pEnable)
{
this->mAxesEnabled = true;
}
else
{
this->mAxesEnabled = false;
}
}
void CGLView::Enable_Reload_Textures(const bool pEnable)
{
if(pEnable)
{
this->mReloadTexturesEnabled = true;
// this->mScene->ImportTextures(this->mScene->pScenePath);
}
else
{
this->mReloadTexturesEnabled = false;
}
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
/********************************************************************/
@ -590,7 +645,13 @@ void CGLView::Enable_Reload_Textures(const bool pEnable)
void CGLView::initializeGL()
{
#if ASSIMP_QT4_VIEWER
qglClearColor(Qt::gray);
#else
mGLContext_Current = true;
initializeOpenGLFunctions();
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
#endif // ASSIMP_QT4_VIEWER
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
@ -607,24 +668,39 @@ void CGLView::initializeGL()
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
#if !ASSIMP_QT4_VIEWER
mGLContext_Current = false;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::resizeGL(int pWidth, int pHeight)
{
#if !ASSIMP_QT4_VIEWER
mGLContext_Current = true;
#endif // ASSIMP_QT4_VIEWER
mCamera_Viewport_AspectRatio = (GLdouble)pWidth / pHeight;
glViewport(0, 0, pWidth, pHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(mCamera_FOVY, mCamera_Viewport_AspectRatio, 1.0, 100000.0);///TODO: znear/zfar depend on scene size.
#if !ASSIMP_QT4_VIEWER
mGLContext_Current = false;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::drawCoordSystem() {
glBindTexture(GL_TEXTURE_1D, 0);
// Disable lighting. Colors must be bright and colorful)
if ( mLightingEnabled ) glDisable( GL_LIGHTING );///TODO: display list
// For same reason - disable textures.
glBindTexture(GL_TEXTURE_1D, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_3D, 0);
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_LINES);
// X, -X
#if ASSIMP_QT4_VIEWER
// X, -X
qglColor(QColor(Qt::red)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(100000.0, 0.0, 0.0);
qglColor(QColor(Qt::cyan)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(-100000.0, 0.0, 0.0);
// Y, -Y
@ -634,12 +710,31 @@ void CGLView::drawCoordSystem() {
qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0);
qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0);
qglColor(QColor(Qt::white));
glEnd();
#else
// X, -X
glColor3f(1.0f, 0.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(100000.0, 0.0, 0.0);
glColor3f(0.5f, 0.5f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(-100000.0, 0.0, 0.0);
// Y, -Y
glColor3f(0.0f, 1.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 100000.0, 0.0);
glColor3f(1.0f, 0.0f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, -100000.0, 0.0);
// Z, -Z
glColor3f(0.0f, 0.0f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0);
glColor3f(1.0f, 1.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0);
glColor3f(1.0f, 1.0f, 1.0f);
#endif // ASSIMP_QT4_VIEWER
glEnd();
// Restore previous state of lighting.
if(mLightingEnabled) glEnable(GL_LIGHTING);
}
void CGLView::paintGL()
{
QTime time_paintbegin;
#if !ASSIMP_QT4_VIEWER
mGLContext_Current = true;
#endif // ASSIMP_QT4_VIEWER
QTime time_paintbegin;
time_paintbegin = QTime::currentTime();
@ -647,30 +742,36 @@ void CGLView::paintGL()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Apply current camera transformations.
#if ASSIMP_DOUBLE_PRECISION
glMultMatrixd((GLdouble*)&mHelper_Camera.Rotation_AroundCamera);
glTranslated(-mHelper_Camera.Translation_ToScene.x, -mHelper_Camera.Translation_ToScene.y, -mHelper_Camera.Translation_ToScene.z);
glMultMatrixd((GLdouble*)&mHelper_Camera.Rotation_Scene);
#else
glMultMatrixf((GLfloat*)&mHelper_Camera.Rotation_AroundCamera);
glTranslatef(-mHelper_Camera.Translation_ToScene.x, -mHelper_Camera.Translation_ToScene.y, -mHelper_Camera.Translation_ToScene.z);
glMultMatrixf((GLfloat*)&mHelper_Camera.Rotation_Scene);
#endif // ASSIMP_DOUBLE_PRECISION
// Coordinate system
if ( mLightingEnabled ) {
glDisable( GL_LIGHTING );///TODO: display list
}
if (this->mAxesEnabled == true)
if (mScene_AxesEnabled == true)
{
drawCoordSystem();
}
glDisable(GL_COLOR_MATERIAL);
if(mLightingEnabled) glEnable(GL_LIGHTING);
// Scene
if(mScene != nullptr)
{
Draw_Node(mScene->mRootNode);
// Scene BBox
if(mScene_DrawBBox) Draw_BBox(mScene_BBox);
}
emit Paint_Finished((size_t)time_paintbegin.msecsTo(QTime::currentTime()), mHelper_Camera.Translation_ToScene.Length());
#if !ASSIMP_QT4_VIEWER
mGLContext_Current = false;
#endif // ASSIMP_QT4_VIEWER
}
/********************************************************************/
@ -678,10 +779,12 @@ void CGLView::paintGL()
/********************************************************************/
CGLView::CGLView(QWidget *pParent)
#if ASSIMP_QT4_VIEWER
: QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer), pParent)
#else
: QOpenGLWidget(pParent), mGLContext_Current(false)
#endif // ASSIMP_QT4_VIEWER
{
static_assert(sizeof(GLfloat) == sizeof(ai_real), "ai_real in Assimp must be equal to GLfloat/float.");///TODO: may be templates can be used.
// set initial view
mHelper_CameraDefault.SetDefault();
Camera_Set(0);
@ -698,6 +801,10 @@ CGLView::~CGLView()
void CGLView::FreeScene()
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
// Set scene to null and after that \ref paintGL will not try to render it.
mScene = nullptr;
// Clean helper objects.
@ -727,10 +834,18 @@ void CGLView::FreeScene()
mTexture_IDMap.clear();
delete [] id_tex;
}
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath)
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
FreeScene();// Clear old data
// Why checking here, not at begin of function. Because old scene may not exist at know. So, need cleanup.
if(pScene == nullptr) return;
@ -957,6 +1072,10 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath)
emit SceneObject_Camera(mScene->mCameras[idx_cam]->mName.C_Str());
}
}// if(!mScene->HasCameras()) else
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
/********************************************************************/
@ -965,39 +1084,65 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath)
void CGLView::Lighting_Enable()
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
mLightingEnabled = true;
glEnable(GL_LIGHTING);
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::Lighting_Disable()
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
glDisable(GL_LIGHTING);
mLightingEnabled = false;
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters)
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
const size_t light_num = GL_LIGHT0 + pLightNumber;
GLfloat farr[4];
if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value;
glLightfv(light_num, GL_AMBIENT, &pLightParameters.Ambient.r);// Ambient color
glLightfv(light_num, GL_DIFFUSE, &pLightParameters.Diffuse.r);// Diffuse color
glLightfv(light_num, GL_SPECULAR, &pLightParameters.Specular.r);// Specular color
// Ambient color
farr[0] = pLightParameters.Ambient.r, farr[1] = pLightParameters.Ambient.g; farr[2] = pLightParameters.Ambient.b; farr[3] = pLightParameters.Ambient.a;
glLightfv(light_num, GL_AMBIENT, farr);
// Diffuse color
farr[0] = pLightParameters.Diffuse.r, farr[1] = pLightParameters.Diffuse.g; farr[2] = pLightParameters.Diffuse.b; farr[3] = pLightParameters.Diffuse.a;
glLightfv(light_num, GL_DIFFUSE, farr);
// Specular color
farr[0] = pLightParameters.Specular.r, farr[1] = pLightParameters.Specular.g; farr[2] = pLightParameters.Specular.b; farr[3] = pLightParameters.Specular.a;
glLightfv(light_num, GL_SPECULAR, farr);
// Other parameters
switch(pLightParameters.Type)
{
case aiLightSource_DIRECTIONAL:
// Direction
farr[0] = pLightParameters.For.Directional.Direction.x, farr[2] = pLightParameters.For.Directional.Direction.y;
farr[0] = pLightParameters.For.Directional.Direction.x, farr[1] = pLightParameters.For.Directional.Direction.y;
farr[2] = pLightParameters.For.Directional.Direction.z; farr[3] = 0;
glLightfv(light_num, GL_POSITION, farr);
break;
case aiLightSource_POINT:
// Position
farr[0] = pLightParameters.For.Point.Position.x, farr[2] = pLightParameters.For.Point.Position.y;
farr[0] = pLightParameters.For.Point.Position.x, farr[1] = pLightParameters.For.Point.Position.y;
farr[2] = pLightParameters.For.Point.Position.z; farr[3] = 1;
glLightfv(light_num, GL_POSITION, farr);
// Attenuation
@ -1008,20 +1153,20 @@ GLfloat farr[4];
break;
case aiLightSource_SPOT:
// Position
farr[0] = pLightParameters.For.Spot.Position.x, farr[2] = pLightParameters.For.Spot.Position.y, farr[2] = pLightParameters.For.Spot.Position.z; farr[3] = 1;
farr[0] = pLightParameters.For.Spot.Position.x, farr[1] = pLightParameters.For.Spot.Position.y, farr[2] = pLightParameters.For.Spot.Position.z; farr[3] = 1;
glLightfv(light_num, GL_POSITION, farr);
// Attenuation
glLightf(light_num, GL_CONSTANT_ATTENUATION, pLightParameters.For.Spot.Attenuation_Constant);
glLightf(light_num, GL_LINEAR_ATTENUATION, pLightParameters.For.Spot.Attenuation_Linear);
glLightf(light_num, GL_QUADRATIC_ATTENUATION, pLightParameters.For.Spot.Attenuation_Quadratic);
// Spot specific
farr[0] = pLightParameters.For.Spot.Direction.x, farr[2] = pLightParameters.For.Spot.Direction.y, farr[2] = pLightParameters.For.Spot.Direction.z; farr[3] = 0;
farr[0] = pLightParameters.For.Spot.Direction.x, farr[1] = pLightParameters.For.Spot.Direction.y, farr[2] = pLightParameters.For.Spot.Direction.z; farr[3] = 0;
glLightfv(light_num, GL_SPOT_DIRECTION, farr);
glLightf(light_num, GL_SPOT_CUTOFF, pLightParameters.For.Spot.CutOff);
break;
default:// For unknown light source types use point source.
// Position
farr[0] = pLightParameters.For.Point.Position.x, farr[2] = pLightParameters.For.Point.Position.y;
farr[0] = pLightParameters.For.Point.Position.x, farr[1] = pLightParameters.For.Point.Position.y;
farr[2] = pLightParameters.For.Point.Position.z; farr[3] = 1;
glLightfv(light_num, GL_POSITION, farr);
// Attenuation
@ -1031,20 +1176,40 @@ GLfloat farr[4];
glLightf(light_num, GL_SPOT_CUTOFF, 180.0);
break;
}// switch(pLightParameters.Type)
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::Lighting_EnableSource(const size_t pLightNumber)
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value;
glEnable(GL_LIGHT0 + pLightNumber);
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
void CGLView::Lighting_DisableSource(const size_t pLightNumber)
{
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_Begin;
#endif // ASSIMP_QT4_VIEWER
if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value;
glDisable(GL_LIGHT0 + pLightNumber);
#if !ASSIMP_QT4_VIEWER
ConditionalContextControl_End;
#endif // ASSIMP_QT4_VIEWER
}
/********************************************************************/
@ -1096,24 +1261,30 @@ void CGLView::Camera_Set(const size_t pCameraNumber)
gluLookAt(hcam.Position.x, hcam.Position.y, hcam.Position.z, hcam.Target.x, hcam.Target.y, hcam.Target.z, up.x, up.y, up.z);
}
void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial)
{
auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; };
aiMatrix4x4 mat_rot;
mat_rot.FromEulerAnglesXYZ(deg2rad(pAngle_X), deg2rad(pAngle_Y), deg2rad(pAngle_Z));
mHelper_Camera.Rotation_Scene *= mat_rot;
if(pMatrix_Rotation_Initial != nullptr)
mHelper_Camera.Rotation_Scene = *pMatrix_Rotation_Initial * mat_rot;
else
mHelper_Camera.Rotation_Scene *= mat_rot;
}
void CGLView::Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
void CGLView::Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial)
{
auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; };
aiMatrix4x4 mat_rot;
mat_rot.FromEulerAnglesXYZ(deg2rad(pAngle_X), deg2rad(pAngle_Y), deg2rad(pAngle_Z));
mHelper_Camera.Rotation_AroundCamera *= mat_rot;
if(pMatrix_Rotation_Initial != nullptr)
mHelper_Camera.Rotation_AroundCamera = *pMatrix_Rotation_Initial * mat_rot;
else
mHelper_Camera.Rotation_AroundCamera *= mat_rot;
}
void CGLView::Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z)
@ -1123,3 +1294,10 @@ aiVector3D vect_tr(pTranslate_X, pTranslate_Y, pTranslate_Z);
vect_tr *= mHelper_Camera.Rotation_AroundCamera;
mHelper_Camera.Translation_ToScene += vect_tr;
}
void CGLView::Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera)
{
pRotation_Camera = mHelper_Camera.Rotation_AroundCamera;
pRotation_Scene = mHelper_Camera.Rotation_Scene;
pTranslation_Camera = mHelper_Camera.Translation_ToScene;
}

View File

@ -6,14 +6,24 @@
#pragma once
// Header files, Qt.
#include <QtOpenGL>
#include <QMap>
#if ASSIMP_QT4_VIEWER
# include <QtOpenGL>
#else
# include <QOpenGLWidget>
# include <QOpenGLFunctions>
#endif // ASSIMP_QT4_VIEWER
// Header files Assimp
#include <assimp/scene.h>
/// \class CGLView
/// Class which hold and render scene.
#if ASSIMP_QT4_VIEWER
class CGLView : public QGLWidget
#else
class CGLView : public QOpenGLWidget, protected QOpenGLFunctions
#endif // ASSIMP_QT4_VIEWER
{
Q_OBJECT
@ -75,9 +85,7 @@ private:
};
public:
bool mAxesEnabled = true;
// Textures
bool mReloadTexturesEnabled = false; // If true then textures will reload when the window is activated.
/// \enum ELightType
/// Type of light source.
enum class ELightType { Directional, Point, Spot };
@ -141,11 +149,16 @@ public:
private:
#if !ASSIMP_QT4_VIEWER
// Qt5 widget has another behavior, so you must to know that you already made context are current. Yes, its a dirty hack. Better decision are welcome.
bool mGLContext_Current;///< Widget's GL-context made current.
#endif // ASSIMP_QT4_VIEWER
// Scene
const aiScene* mScene = nullptr;///< Copy of pointer to scene (\ref aiScene).
SBBox mScene_BBox;///< Bounding box of scene.
aiVector3D mScene_Center;///< Coordinates of center of the scene.
bool mScene_DrawBBox = false;///< Flag which control drawing scene BBox.
bool mScene_AxesEnabled = true;///< Flag which control drawing axes of the coordinate system.
// Meshes
size_t mHelper_Mesh_Quantity = 0;///< Quantity of meshes in scene.
SHelper_Mesh** mHelper_Mesh = nullptr;///< Array of pointers to helper objects for drawing mesh. Sequence of meshes are equivalent to \ref aiScene::mMeshes.
@ -254,7 +267,11 @@ private:
/********************************************************************/
protected:
/// \fn void drawCoordSystem()
/// Draw axes of the coordinate system.
void drawCoordSystem();
/// \fn void initializeGL() override
/// Override function to initialise OpenGL.
void initializeGL() override;
@ -307,11 +324,10 @@ public:
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Textures(const bool pEnable);
void Enable_Axes(const bool pEnable);
/// \fn void Enable_Textures(const bool pEnable)
/// Control textures drawing.
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Reload_Textures(const bool pEnable);
/// \fn void Enable_Axes(const bool pEnable)
/// Control axes drawing.
/// \param [in] pEnable - if true then enable axes, false - disable axes.
void Enable_Axes(const bool pEnable) { this->mScene_AxesEnabled = pEnable; }
/********************************************************************/
/******************** Lighting control functions ********************/
@ -350,19 +366,23 @@ public:
/// \param [in] pCamera_Index - index of the camera (\ref aiScene::mCameras).
void Camera_Set(const size_t pCameraNumber);
/// \fn void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
/// \fn void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial)
/// Rotate scene around axisees.
/// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees.
/// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees.
/// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees.
void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z);
/// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix
/// will be used.
void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr);
/// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
/// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr)
/// Rotate camera around axisees.
/// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees.
/// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees.
/// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees.
void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z);
/// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix
/// will be used.
void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr);
/// \fn void Camera_Translate(const size_t pTranslate_X, const size_t pTranslate_Y, const size_t pTranslate_Z)
/// Translate camera along axises. In local coordinates.
@ -371,6 +391,13 @@ public:
/// \param [in] pTranslate_Z - specifies the Z coordinate of translation vector.
void Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z);
/// \fn void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera)
/// Return data about camera position in world.
/// \param [out] pRotation_Camera - rotation matrix which set rotation angles of the scene around camera.
/// \param [out] pRotation_Scene - rotation matrix which set rotation angles of the scene around own center.
/// \param [out] pTranslation_Camera - translation vector from camera to the scene.
void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera);
signals:
/// \fn void Paint_Finished(const size_t pPaintTime, const GLfloat pDistance)

View File

@ -48,7 +48,7 @@ QTime time_begin = QTime::currentTime();
ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable();
ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true);
ui->cbxReloadTextures->setChecked(true); mGLView->Enable_Reload_Textures(false);
//
// Fill info labels
//
@ -84,7 +84,11 @@ QTime time_begin = QTime::currentTime();
mGLView->Camera_Set(0);
// Scene is loaded, do first rendering.
LogInfo("Scene is ready for rendering.");
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
else
{
@ -128,40 +132,74 @@ void MainWindow::LogError(const QString& pMessage)
void MainWindow::mousePressEvent(QMouseEvent* pEvent)
{
if(pEvent->button() & Qt::LeftButton)
mPosition_Pressed_LMB = pEvent->pos();
else if(pEvent->button() & Qt::RightButton)
mPosition_Pressed_RMB = pEvent->pos();
const QPoint ms_pt = pEvent->pos();
__unused aiVector3D temp_v3;
// Check if GLView is pointed.
if(childAt(ms_pt) == mGLView)
{
if(!mMouse_Transformation.Position_Pressed_Valid)
{
mMouse_Transformation.Position_Pressed_Valid = true;// set flag
// Store current transformation matrices.
mGLView->Camera_Matrix(mMouse_Transformation.Rotation_AroundCamera, mMouse_Transformation.Rotation_Scene, temp_v3);
}
if(pEvent->button() & Qt::LeftButton)
mMouse_Transformation.Position_Pressed_LMB = ms_pt;
else if(pEvent->button() & Qt::RightButton)
mMouse_Transformation.Position_Pressed_RMB = ms_pt;
}
else
{
mMouse_Transformation.Position_Pressed_Valid = false;
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *pEvent)
{
if(pEvent->buttons() == 0) mMouse_Transformation.Position_Pressed_Valid = false;
}
void MainWindow::mouseMoveEvent(QMouseEvent* pEvent)
{
if(pEvent->buttons() & Qt::LeftButton)
if(mMouse_Transformation.Position_Pressed_Valid)
{
GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_LMB.x()) / mGLView->width();
GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_LMB.y()) / mGLView->height();
if(pEvent->buttons() & Qt::LeftButton)
{
GLfloat dx = 180 * GLfloat(pEvent->x() - mMouse_Transformation.Position_Pressed_LMB.x()) / mGLView->width();
GLfloat dy = 180 * GLfloat(pEvent->y() - mMouse_Transformation.Position_Pressed_LMB.y()) / mGLView->height();
if(pEvent->modifiers() & Qt::ShiftModifier)
mGLView->Camera_RotateScene(dy, 0, dx);// Rotate around oX and oZ axises.
else
mGLView->Camera_RotateScene(dy, dx, 0);// Rotate around oX and oY axises.
if(pEvent->modifiers() & Qt::ShiftModifier)
mGLView->Camera_RotateScene(dy, 0, dx, &mMouse_Transformation.Rotation_Scene);// Rotate around oX and oZ axises.
else
mGLView->Camera_RotateScene(dy, dx, 0, &mMouse_Transformation.Rotation_Scene);// Rotate around oX and oY axises.
mGLView->updateGL();
mPosition_Pressed_LMB = pEvent->pos();
}
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
if(pEvent->buttons() & Qt::RightButton)
{
GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_RMB.x()) / mGLView->width();
GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_RMB.y()) / mGLView->height();
if(pEvent->buttons() & Qt::RightButton)
{
GLfloat dx = 180 * GLfloat(pEvent->x() - mMouse_Transformation.Position_Pressed_RMB.x()) / mGLView->width();
GLfloat dy = 180 * GLfloat(pEvent->y() - mMouse_Transformation.Position_Pressed_RMB.y()) / mGLView->height();
if(pEvent->modifiers() & Qt::ShiftModifier)
mGLView->Camera_Rotate(dy, 0, dx);// Rotate around oX and oZ axises.
else
mGLView->Camera_Rotate(dy, dx, 0);// Rotate around oX and oY axises.
if(pEvent->modifiers() & Qt::ShiftModifier)
mGLView->Camera_Rotate(dy, 0, dx, &mMouse_Transformation.Rotation_AroundCamera);// Rotate around oX and oZ axises.
else
mGLView->Camera_Rotate(dy, dx, 0, &mMouse_Transformation.Rotation_AroundCamera);// Rotate around oX and oY axises.
mGLView->updateGL();
mPosition_Pressed_RMB = pEvent->pos();
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
}
}
@ -189,19 +227,16 @@ GLfloat step;
else if(pEvent->key() == Qt::Key_Down)
mGLView->Camera_Translate(0, 0, step);
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
bool MainWindow::event(QEvent *e)
{
if (e->type() == QEvent::WindowActivate && this->mGLView->mReloadTexturesEnabled == true) {
qInfo() << "Window Activated";
}
return QWidget::event(e);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow),
@ -209,6 +244,9 @@ MainWindow::MainWindow(QWidget *parent)
{
using namespace Assimp;
// other variables
mMouse_Transformation.Position_Pressed_Valid = false;
ui->setupUi(this);
// Create OpenGL widget
mGLView = new CGLView(this);
@ -281,7 +319,6 @@ QString filename, filter;
if(!filename.isEmpty()) ImportFile(filename);
}
void MainWindow::on_butExport_clicked()
{
using namespace Assimp;
@ -301,7 +338,7 @@ QMap<QString, const aiExportFormatDesc*> exportersMap;
return;
}
for (int i = 0; i < exporter.GetExportFormatCount(); ++i)
for (size_t i = 0; i < exporter.GetExportFormatCount(); ++i)
{
const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(i);
exportersList.push_back(desc->id + QString(": ") + desc->description);
@ -345,7 +382,11 @@ void MainWindow::on_cbxLighting_clicked(bool pChecked)
else
mGLView->Lighting_Disable();
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
void MainWindow::on_lstLight_itemSelectionChanged()
@ -357,35 +398,49 @@ bool selected = ui->lstLight->isItemSelected(ui->lstLight->currentItem());
else
mGLView->Lighting_DisableSource(ui->lstLight->currentRow());
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
void MainWindow::on_lstCamera_clicked( const QModelIndex &)
{
mGLView->Camera_Set(ui->lstLight->currentRow());
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
void MainWindow::on_cbxBBox_clicked(bool checked)
{
mGLView->Enable_SceneBBox(checked);
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
void MainWindow::on_cbxDrawAxes_clicked(bool checked)
{
mGLView->Enable_Axes(checked);
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
}
void MainWindow::on_cbxReloadTextures_clicked(bool checked)
{
mGLView->Enable_Reload_Textures(checked);
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}
void MainWindow::on_cbxTextures_clicked(bool checked)
{
mGLView->Enable_Textures(checked);
#if ASSIMP_QT4_VIEWER
mGLView->updateGL();
#else
mGLView->update();
#endif // ASSIMP_QT4_VIEWER
}

View File

@ -6,7 +6,11 @@
#pragma once
// Header files, Qt.
#include <QtWidgets>
#if ASSIMP_QT4_VIEWER
# include <QMainWindow>
#else
# include <QtWidgets>
#endif
// Header files, project.
#include "glview.hpp"
@ -36,8 +40,17 @@ private:
CLoggerView* mLoggerView;///< Pointer to logging object.
Assimp::Importer mImporter;///< Assimp importer.
const aiScene* mScene;///< Pointer to loaded scene (\ref aiScene).
QPoint mPosition_Pressed_LMB;///< Position where was pressed left mouse button.
QPoint mPosition_Pressed_RMB;///< Position where was pressed right mouse button.
/// \struct SMouse_Transformation
/// Holds data about transformation of the scene/camera when mouse us used.
struct SMouse_Transformation
{
bool Position_Pressed_Valid;///< Mouse button pressed on GLView.
QPoint Position_Pressed_LMB;///< Position where was pressed left mouse button.
QPoint Position_Pressed_RMB;///< Position where was pressed right mouse button.
aiMatrix4x4 Rotation_AroundCamera;///< Rotation matrix which set rotation angles of the scene around camera.
aiMatrix4x4 Rotation_Scene;///< Rotation matrix which set rotation angles of the scene around own center.
} mMouse_Transformation;
/**********************************/
/************ Functions ***********/
@ -80,6 +93,11 @@ protected:
/// \param [in] pEvent - pointer to event data.
void mousePressEvent(QMouseEvent* pEvent) override;
/// \fn void mouseReleaseEvent(QMouseEvent *pEvent) override
/// Override function which handles mouse event "button released".
/// \param [in] pEvent - pointer to event data.
void mouseReleaseEvent(QMouseEvent *pEvent) override;
/// \fn void mouseMoveEvent(QMouseEvent* pEvent) override
/// Override function which handles mouse event "move".
/// \param [in] pEvent - pointer to event data.
@ -90,7 +108,6 @@ protected:
/// \param [in] pEvent - pointer to event data.
void keyPressEvent(QKeyEvent* pEvent) override;
bool event(QEvent*);
public:
/********************************************************************/
@ -134,5 +151,4 @@ private slots:
void on_cbxBBox_clicked(bool checked);
void on_cbxTextures_clicked(bool checked);
void on_cbxDrawAxes_clicked(bool checked);
void on_cbxReloadTextures_clicked(bool checked);
};

View File

@ -302,6 +302,9 @@
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
@ -312,6 +315,9 @@
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
@ -325,6 +331,9 @@
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
@ -335,6 +344,9 @@
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="8" column="0">
@ -349,6 +361,9 @@
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
@ -511,13 +526,6 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="cbxReloadTextures">
<property name="text">
<string>Live Reload Textures</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2015, assimp team
Copyright (c) 2006-2018, assimp team
All rights reserved.
@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "assimp_view.h"
#include <tuple>
using namespace AssimpView;

View File

@ -96,8 +96,9 @@ D3DXVECTOR4 g_aclNormalColors[14] =
void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
{
*piCnt = *piCnt+1;
for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
GetNodeCount(pcNode->mChildren[i],piCnt);
for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) {
GetNodeCount(pcNode->mChildren[i], piCnt);
}
}
//-------------------------------------------------------------------------------
@ -1042,16 +1043,23 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
switch (pcNew->eOp)
{
case aiTextureOp_Add:
szOp = "add";break;
szOp = "add";
break;
case aiTextureOp_Subtract:
szOp = "sub";break;
szOp = "sub";
break;
case aiTextureOp_Divide:
szOp = "div";break;
szOp = "div";
break;
case aiTextureOp_SignedAdd:
szOp = "addsign";break;
szOp = "addsign";
break;
case aiTextureOp_SmoothAdd:
szOp = "addsmooth";break;
default: szOp = "mul";
szOp = "addsmooth";
break;
default:
szOp = "mul";
break;
};
SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp);
@ -2251,7 +2259,7 @@ int CDisplay::RenderTextureView()
const float ny = (float)sRect.bottom;
const float x = (float)sDesc.Width;
const float y = (float)sDesc.Height;
float f = min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f);
float f = std::min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f);
float fHalfX = (nx - (f * x)) / 2.0f;
float fHalfY = (ny - (f * y)) / 2.0f;

View File

@ -275,7 +275,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
for (unsigned int i = 0; i < iSizeFound;++i)
info.cFileName[i] = (CHAR)tolower(info.cFileName[i]);
if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize)))
if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize)))
{
// we have it. Build the full path ...
char* sz = strrchr(szTempB,'*');

View File

@ -45,7 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <windowsx.h>
#include <commdlg.h>
#ifdef __MINGW32__
#include <mmsystem.h>
#else
#include <timeapi.h>
#endif
namespace AssimpView {
@ -80,8 +85,7 @@ void SaveHistory();
// File associations are registered in HKCU\Software\Classes. They might
// be overwritten by global file associations.
//-------------------------------------------------------------------------------
void MakeFileAssociations()
{
void MakeFileAssociations() {
char szTemp2[MAX_PATH];
char szTemp[MAX_PATH + 10];
@ -1050,9 +1054,9 @@ void DoExport(size_t formatId)
ai_assert(strlen(szFileName) <= MAX_PATH);
// invent a nice default file name
char* sz = max(strrchr(szFileName,'\\'),strrchr(szFileName,'/'));
char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/'));
if (sz) {
strncpy(sz,max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH);
strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH);
}
}
else {
@ -1399,7 +1403,7 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
g_hDlg = hwndDlg;
// load the state of the usr interface
// load the state of the user interface
InitUI();
// load the file history
@ -1643,11 +1647,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
xPos = xPos2 = sPoint.x;
yPos = yPos2 = sPoint.y;
/* xPos -= 10;
yPos -= 10;
xPos2 = xPos-3;
yPos2 = yPos-5;*/
RECT sRect;
GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
sRect.right -= sRect.left;
@ -1830,7 +1829,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg,
return TRUE;
case WM_COMMAND:
HMENU hMenu = GetMenu(g_hDlg);
if (ID_VIEWER_QUIT == LOWORD(wParam))
{
@ -2361,7 +2359,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
@ -2371,14 +2369,13 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
// load windows common controls library to get XP style
InitCommonControls();
// intiailize the IDirect3D9 interface
// initialize the IDirect3D9 interface
g_hInstance = hInstance;
if (0 == InitD3D())
{
if (0 == InitD3D()) {
MessageBox(NULL,"Failed to initialize Direct3D 9",
"ASSIMP ModelViewer",MB_OK);
return -6;
}
}
// create the main dialog
HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN),
@ -2395,12 +2392,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
Assimp::DefaultLogger::Debugging | Assimp::DefaultLogger::Info |
Assimp::DefaultLogger::Err | Assimp::DefaultLogger::Warn);
if (NULL == hDlg)
{
if (NULL == hDlg) {
MessageBox(NULL,"Failed to create dialog from resource",
"ASSIMP ModelViewer",MB_OK);
return -5;
}
}
// display the window
g_hDlg = hDlg;
@ -2410,12 +2406,12 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
UpdateWindow( hDlg );
// create the D3D device object
if (0 == CreateDevice(g_sOptions.bMultiSample,false,true))
{
if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) {
MessageBox(NULL,"Failed to initialize Direct3D 9 (2)",
"ASSIMP ModelViewer",MB_OK);
return -4;
}
}
CLogDisplay::Instance().AddEntry("[OK] Here we go!");
// create the log window

View File

@ -43,10 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "assimp_view.h"
#include <timeapi.h>
#include <assimp/StringUtils.h>
#include <map>
#ifdef __MINGW32__
#include <mmsystem.h>
#else
#include <timeapi.h>
#endif
using namespace std;
namespace AssimpView {
@ -143,7 +148,7 @@ float g_fLoadTime = 0.0f;
//-------------------------------------------------------------------------------
// Entry point for the loader thread
// The laoder thread loads the asset while the progress dialog displays the
// The loader thread loads the asset while the progress dialog displays the
// smart progress bar
//-------------------------------------------------------------------------------
DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
@ -200,9 +205,9 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
// load the current asset
// THe path to the asset is specified in the global path variable
//-------------------------------------------------------------------------------
int LoadAsset(void)
int LoadAsset()
{
// set the world and world rotation matrices to the identuty
// set the world and world rotation matrices to the identity
g_mWorldRotate = aiMatrix4x4();
g_mWorld = aiMatrix4x4();
@ -1130,8 +1135,6 @@ int GetProjectionMatrix (aiMatrix4x4& p_mOut)
return 1;
}
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut)
{

View File

@ -46,6 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_SHADER_COMPILE_FLAGS D3DXSHADER_USE_LEGACY_D3DX9_31_DLL
// Because Dx headers include windef.h with min/max redefinition
#define NOMINMAX
// include resource definitions
#include "resource.h"
@ -177,7 +180,7 @@ type clamp(intype in)
{
// for unsigned types only ...
intype mask = (0x1u << (sizeof(type)*8))-1;
return (type)max((intype)0,min(in,mask));
return (type)std::max((intype)0,std::min(in,mask));
}

Some files were not shown because too many files have changed in this diff Show More