Merge branch 'master' into coverity_scan

pull/1007/head
Kim Kulling 2016-09-02 10:25:36 +02:00
commit 91f24db739
67 changed files with 3117 additions and 618 deletions

View File

@ -39,7 +39,50 @@ SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
cmake_minimum_required( VERSION 2.8 ) cmake_minimum_required( VERSION 2.8 )
PROJECT( Assimp ) PROJECT( Assimp )
OPTION(BUILD_SHARED_LIBS "Build package with shared libraries." ON) # All supported options ###############################################
OPTION( BUILD_SHARED_LIBS
"Build package with shared libraries."
ON
)
OPTION( ASSIMP_DOUBLE_PRECISION
"Set to ON to enable double precision processing"
OFF
)
OPTION( ASSIMP_OPT_BUILD_PACKAGES
"Set to ON to generate CPack configuration files and packaging targets"
OFF
)
OPTION( ASSIMP_ANDROID_JNIIOSYSTEM
"Android JNI IOSystem support is active"
OFF
)
OPTION( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality."
OFF
)
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
OFF
)
option( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library."
ON
)
option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
OFF
)
OPTION ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library."
ON
)
IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON
)
ENDIF(MSVC)
IF(NOT BUILD_SHARED_LIBS) IF(NOT BUILD_SHARED_LIBS)
SET(LINK_SEARCH_START_STATIC TRUE) SET(LINK_SEARCH_START_STATIC TRUE)
ENDIF(NOT BUILD_SHARED_LIBS) ENDIF(NOT BUILD_SHARED_LIBS)
@ -80,18 +123,12 @@ IF(NOT GIT_COMMIT_HASH)
SET(GIT_COMMIT_HASH 0) SET(GIT_COMMIT_HASH 0)
ENDIF(NOT GIT_COMMIT_HASH) ENDIF(NOT GIT_COMMIT_HASH)
OPTION(ASSIMP_DOUBLE_PRECISION
"Set to ON to enable double precision processing"
OFF
)
IF(ASSIMP_DOUBLE_PRECISION) IF(ASSIMP_DOUBLE_PRECISION)
ADD_DEFINITIONS(-DAI_DOUBLE_PRECISION) ADD_DEFINITIONS(-DAI_DOUBLE_PRECISION)
ENDIF(ASSIMP_DOUBLE_PRECISION) ENDIF(ASSIMP_DOUBLE_PRECISION)
configure_file( configure_file(
${CMAKE_CURRENT_LIST_DIR}/revision.h.in ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
# ${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h ${CMAKE_CURRENT_BINARY_DIR}/revision.h
) )
@ -106,23 +143,28 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include
) )
OPTION(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
SET(LIBASSIMP_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" ) SET(LIBASSIMP_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" ) SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev) SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
OPTION(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF)
# Workaround to be able to deal with compiler bug "Too many sections" with mingw. # Workaround to be able to deal with compiler bug "Too many sections" with mingw.
IF( CMAKE_COMPILER_IS_MINGW ) IF( CMAKE_COMPILER_IS_MINGW )
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_IFC_IMPORTER ) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_IFC_IMPORTER )
ENDIF() ENDIF()
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
IF( UNIX )
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF()
ENDIF()
IF((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) IF((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW)
IF (BUILD_SHARED_LIBS AND CMAKE_SIZEOF_VOID_P EQUAL 8) # -fPIC is only required for shared libs on 64 bit IF (BUILD_SHARED_LIBS AND CMAKE_SIZEOF_VOID_P EQUAL 8) # -fPIC is only required for shared libs on 64 bit
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ENDIF() ENDIF()
# hide all not-exported symbols # hide all not-exported symbols
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -std=c++0x" ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -std=c++0x" )
@ -171,8 +213,6 @@ IF (NOT TARGET uninstall)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF() ENDIF()
# cmake configuration files # cmake configuration files
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
@ -180,22 +220,12 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${C
FIND_PACKAGE( DirectX ) FIND_PACKAGE( DirectX )
OPTION ( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality."
OFF
)
IF( CMAKE_COMPILER_IS_GNUCXX ) IF( CMAKE_COMPILER_IS_GNUCXX )
SET(LIBSTDC++_LIBRARIES -lstdc++) SET(LIBSTDC++_LIBRARIES -lstdc++)
ENDIF( CMAKE_COMPILER_IS_GNUCXX ) ENDIF( CMAKE_COMPILER_IS_GNUCXX )
# Search for external dependencies, and build them from source if not found # Search for external dependencies, and build them from source if not found
# Search for zlib # Search for zlib
OPTION(ASSIMP_BUILD_ZLIB
"Build your own zlib"
OFF
)
IF ( NOT ASSIMP_BUILD_ZLIB ) IF ( NOT ASSIMP_BUILD_ZLIB )
find_package(ZLIB) find_package(ZLIB)
ENDIF( NOT ASSIMP_BUILD_ZLIB ) ENDIF( NOT ASSIMP_BUILD_ZLIB )
@ -293,10 +323,6 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
option ( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library."
ON
)
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 ) IF ( WIN32 )
option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
@ -306,12 +332,34 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ENDIF ( WIN32 ) ENDIF ( WIN32 )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) 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(Qt4 QUIET)
FIND_PACKAGE(DevIL QUIET)
FIND_PACKAGE(OpenGL QUIET)
IF ( Qt4_FOUND AND IL_FOUND AND OPENGL_FOUND)
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
ELSE()
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
IF (NOT Qt4_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt4")
ENDIF (NOT Qt4_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 ( Qt4_FOUND AND IL_FOUND AND OPENGL_FOUND)
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
OFF
)
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)
IF ( WIN32 ) IF ( WIN32 )
@ -320,22 +368,10 @@ IF ( ASSIMP_BUILD_SAMPLES)
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
ENDIF ( ASSIMP_BUILD_SAMPLES ) ENDIF ( ASSIMP_BUILD_SAMPLES )
OPTION ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library."
ON
)
IF ( ASSIMP_BUILD_TESTS ) IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ ) ADD_SUBDIRECTORY( test/ )
ENDIF ( ASSIMP_BUILD_TESTS ) ENDIF ( ASSIMP_BUILD_TESTS )
IF(MSVC)
OPTION ( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON
)
ENDIF(MSVC)
# Generate a pkg-config .pc for the Assimp library. # Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY ) CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT}) INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})

View File

@ -7,13 +7,13 @@ The following is a non-exhaustive list of all constributors over the years.
If you think your name should be listed here, drop us a line and we'll add you. If you think your name should be listed here, drop us a line and we'll add you.
- Alexander Gessler, - Alexander Gessler,
3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Admin and Design). 3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Design).
- Thomas Schulze, - Thomas Schulze,
X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation. X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
- Kim Kulling, - Kim Kulling,
Obj-Loader, Logging system, Scons-build environment, CMake build environment, Linux build. Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
- R.Schmidt, - R.Schmidt,
Linux build, eclipse support. Linux build, eclipse support.

View File

@ -14,7 +14,6 @@ Coverity<a href="https://scan.coverity.com/projects/5607">
<img alt="Coverity Scan Build Status" <img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/> src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a> </a>
Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<br> <br>
__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__ __[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
@ -117,8 +116,7 @@ For development discussions, there is also a (very low-volume) mailing list, _as
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
> /join #assetimporterlib
### Contributing ### ### Contributing ###
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit Contributions to assimp are highly appreciated. The easiest way to get involved is to submit

View File

@ -25,8 +25,8 @@ conditions are met:
derived from this software without specific prior derived from this software without specific prior
written permission of the assimp team. written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@ -1463,30 +1463,29 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
continue; continue;
} }
// another mesh UV channel ... // another mesh UV channel ...
if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) {
{ unsigned int iIndex( 0 );
unsigned int iIndex = 0;
ParseLV4MeshLong(iIndex); ParseLV4MeshLong(iIndex);
if ( 0 == iIndex ) {
if (iIndex < 2) LogWarning( "Mapping channel has an invalid index. Skipping UV channel" );
{
LogWarning("Mapping channel has an invalid index. Skipping UV channel");
// skip it ... // skip it ...
SkipSection(); SkipSection();
} else {
if ( iIndex < 2 ) {
LogWarning( "Mapping channel has an invalid index. Skipping UV channel" );
// skip it ...
SkipSection();
}
if ( iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS ) {
LogWarning( "Too many UV channels specified. Skipping channel .." );
// skip it ...
SkipSection();
} else {
// parse the mapping channel
ParseLV3MappingChannel( iIndex - 1, mesh );
}
continue;
} }
if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
{
LogWarning("Too many UV channels specified. Skipping channel ..");
// skip it ...
SkipSection();
}
else
{
// parse the mapping channel
ParseLV3MappingChannel(iIndex-1,mesh);
}
continue;
} }
// mesh animation keyframe. Not supported // mesh animation keyframe. Not supported
if (TokenMatch(filePtr,"MESH_ANIMATION" ,14)) if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))

View File

@ -61,15 +61,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// #define ASSIMP_BUILD_BLENDER_NO_STATS // #define ASSIMP_BUILD_BLENDER_NO_STATS
namespace Assimp { namespace Assimp {
template <bool,bool> class StreamReader;
typedef StreamReader<true,true> StreamReaderAny;
namespace Blender { template <bool,bool> class StreamReader;
class FileDatabase; typedef StreamReader<true,true> StreamReaderAny;
struct FileBlockHead;
template <template <typename> class TOUT> namespace Blender {
class ObjectCache;
class FileDatabase;
struct FileBlockHead;
template <template <typename> class TOUT>
class ObjectCache;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Exception class used by the blender loader to selectively catch exceptions /** Exception class used by the blender loader to selectively catch exceptions
@ -78,20 +80,21 @@ namespace Assimp {
* the loader itself, it will still be caught by Assimp due to its * the loader itself, it will still be caught by Assimp due to its
* ancestry. */ * ancestry. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Error : DeadlyImportError struct Error : DeadlyImportError {
{
Error (const std::string& s) Error (const std::string& s)
: DeadlyImportError(s) : DeadlyImportError(s) {
{} // empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** The only purpose of this structure is to feed a virtual dtor into its /** The only purpose of this structure is to feed a virtual dtor into its
* descendents. It serves as base class for all data structure fields. */ * descendents. It serves as base class for all data structure fields. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ElemBase struct ElemBase {
{ virtual ~ElemBase() {
virtual ~ElemBase() {} // empty
}
/** Type name of the element. The type /** Type name of the element. The type
* string points is the `c_str` of the `name` attribute of the * string points is the `c_str` of the `name` attribute of the
@ -103,25 +106,28 @@ struct ElemBase
const char* dna_type; const char* dna_type;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a generic pointer to a memory location, which can be either 32 /** Represents a generic pointer to a memory location, which can be either 32
* or 64 bits. These pointers are loaded from the BLEND file and finally * or 64 bits. These pointers are loaded from the BLEND file and finally
* fixed to point to the real, converted representation of the objects * fixed to point to the real, converted representation of the objects
* they used to point to.*/ * they used to point to.*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Pointer struct Pointer {
{ Pointer()
Pointer() : val() {} : val() {
// empty
}
uint64_t val; uint64_t val;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */ /** Represents a generic offset within a BLEND file */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct FileOffset struct FileOffset {
{ FileOffset()
FileOffset() : val() {} : val() {
// empty
}
uint64_t val; uint64_t val;
}; };
@ -132,8 +138,7 @@ struct FileOffset
* functions of shared_ptr */ * functions of shared_ptr */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
template <typename T> template <typename T>
class vector : public std::vector<T> class vector : public std::vector<T> {
{
public: public:
using std::vector<T>::resize; using std::vector<T>::resize;
using std::vector<T>::empty; using std::vector<T>::empty;
@ -150,8 +155,7 @@ public:
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Mixed flags for use in #Field */ /** Mixed flags for use in #Field */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
enum FieldFlags enum FieldFlags {
{
FieldFlag_Pointer = 0x1, FieldFlag_Pointer = 0x1,
FieldFlag_Array = 0x2 FieldFlag_Array = 0x2
}; };
@ -159,8 +163,7 @@ enum FieldFlags
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a single member of a data structure in a BLEND file */ /** Represents a single member of a data structure in a BLEND file */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Field struct Field {
{
std::string name; std::string name;
std::string type; std::string type;
@ -180,8 +183,7 @@ struct Field
* mission critical so we need them, while others can silently be default * mission critical so we need them, while others can silently be default
* initialized and no animations are harmed. */ * initialized and no animations are harmed. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
enum ErrorPolicy enum ErrorPolicy {
{
/** Substitute default value and ignore */ /** Substitute default value and ignore */
ErrorPolicy_Igno, ErrorPolicy_Igno,
/** Substitute default value and write to log */ /** Substitute default value and write to log */
@ -202,15 +204,14 @@ enum ErrorPolicy
* binary `blob` read from the file to such a structure instance with * binary `blob` read from the file to such a structure instance with
* meaningful contents. */ * meaningful contents. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class Structure class Structure {
{
template <template <typename> class> friend class ObjectCache; template <template <typename> class> friend class ObjectCache;
public: public:
Structure() Structure()
: cache_idx(static_cast<size_t>(-1) ) : cache_idx(static_cast<size_t>(-1) ){
{} // empty
}
public: public:
@ -709,8 +710,6 @@ class FileDatabase
template <template <typename> class TOUT> friend class ObjectCache; template <template <typename> class TOUT> friend class ObjectCache;
public: public:
FileDatabase() FileDatabase()
: _cacheArrays(*this) : _cacheArrays(*this)
, _cache(*this) , _cache(*this)
@ -718,7 +717,6 @@ public:
{} {}
public: public:
// publicly accessible fields // publicly accessible fields
bool i64bit; bool i64bit;
bool little; bool little;

View File

@ -532,7 +532,7 @@ template <typename T> struct signless;
template <> struct signless<char> {typedef unsigned char type;}; template <> struct signless<char> {typedef unsigned char type;};
template <> struct signless<short> {typedef unsigned short type;}; template <> struct signless<short> {typedef unsigned short type;};
template <> struct signless<int> {typedef unsigned int type;}; template <> struct signless<int> {typedef unsigned int type;};
template <> struct signless<unsigned char> { typedef unsigned char type; };
template <typename T> template <typename T>
struct static_cast_silent { struct static_cast_silent {
template <typename V> template <typename V>
@ -614,6 +614,22 @@ template <> inline void Structure :: Convert<char> (char& dest,const FileDatab
ConvertDispatcher(dest,*this,db); ConvertDispatcher(dest,*this,db);
} }
// ------------------------------------------------------------------------------------------------
template <> inline void Structure::Convert<unsigned char>(unsigned char& dest, const FileDatabase& db) const
{
// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
if (name == "float") {
dest = static_cast<unsigned char>(db.reader->GetF4() * 255.f);
return;
}
else if (name == "double") {
dest = static_cast<unsigned char>(db.reader->GetF8() * 255.f);
return;
}
ConvertDispatcher(dest, *this, db);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const
{ {

View File

@ -123,7 +123,8 @@ namespace Blender {
struct ObjectCompare { struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const { bool operator() (const Object* left, const Object* right) const {
return strcmp(left->id.name, right->id.name) == -1; printf( "left: %s, right: %s\n", left->id.name, right->id.name );
return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
} }
}; };
@ -144,7 +145,8 @@ namespace Blender {
struct ObjectCompare { struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const { bool operator() (const Object* left, const Object* right) const {
return strcmp(left->id.name, right->id.name) == -1; printf( "left: %s, right: %s\n", left->id.name, right->id.name );
return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
} }
}; };

View File

@ -1118,12 +1118,13 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++]; const aiFace& f = out->mFaces[out->mNumFaces++];
aiColor4D* vo = &out->mColors[0][out->mNumVertices]; aiColor4D* vo = &out->mColors[0][out->mNumVertices];
const ai_real scaleZeroToOne = 1.f/255.f;
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
const MLoopCol& col = mesh->mloopcol[v.loopstart + j]; const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
vo->r = col.r; vo->r = ai_real(col.r) * scaleZeroToOne;
vo->g = col.g; vo->g = ai_real(col.g) * scaleZeroToOne;
vo->b = col.b; vo->b = ai_real(col.b) * scaleZeroToOne;
vo->a = col.a; vo->a = ai_real(col.a) * scaleZeroToOne;
} }
} }

View File

@ -175,7 +175,7 @@ struct MLoopUV : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol // Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase { struct MLoopCol : ElemBase {
char r, g, b, a; unsigned char r, g, b, a;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------

View File

@ -722,6 +722,7 @@ if (UNZIP_FOUND)
SET (unzip_compile_SRCS "") SET (unzip_compile_SRCS "")
else (UNZIP_FOUND) else (UNZIP_FOUND)
SET (unzip_compile_SRCS ${unzip_SRCS}) SET (unzip_compile_SRCS ${unzip_SRCS})
INCLUDE_DIRECTORIES( "../contrib/unzip/" )
endif (UNZIP_FOUND) endif (UNZIP_FOUND)
MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}") MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")

View File

@ -55,6 +55,7 @@ DefaultIOStream::~DefaultIOStream()
{ {
if (mFile) { if (mFile) {
::fclose(mFile); ::fclose(mFile);
mFile = nullptr;
} }
} }
@ -109,9 +110,9 @@ size_t DefaultIOStream::FileSize() const
return 0; return 0;
} }
if (SIZE_MAX == cachedSize) { if (SIZE_MAX == mCachedSize ) {
// Although fseek/ftell would allow us to reuse the exising file handle here, // Although fseek/ftell would allow us to reuse the existing file handle here,
// it is generally unsafe because: // it is generally unsafe because:
// - For binary streams, it is not technically well-defined // - For binary streams, it is not technically well-defined
// - For text files the results are meaningless // - For text files the results are meaningless
@ -124,16 +125,19 @@ size_t DefaultIOStream::FileSize() const
int err = _stat64( mFilename.c_str(), &fileStat ); int err = _stat64( mFilename.c_str(), &fileStat );
if (0 != err) if (0 != err)
return 0; return 0;
cachedSize = (size_t) (fileStat.st_size); mCachedSize = (size_t) (fileStat.st_size);
#else #elif defined __gnu_linux__ || defined __APPLE__ || defined __MACH__
struct stat fileStat; struct stat fileStat;
int err = stat(mFilename.c_str(), &fileStat ); int err = stat(mFilename.c_str(), &fileStat );
if (0 != err) if (0 != err)
return 0; return 0;
cachedSize = (size_t) (fileStat.st_size); const unsigned long long cachedSize = fileStat.st_size;
mCachedSize = static_cast< size_t >( cachedSize );
#else
# error "Unknown platform"
#endif #endif
} }
return cachedSize; return mCachedSize;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -59,11 +59,11 @@ class ASSIMP_API DefaultIOStream : public IOStream
{ {
friend class DefaultIOSystem; friend class DefaultIOSystem;
#if __ANDROID__ #if __ANDROID__
#if __ANDROID_API__ > 9 # if __ANDROID_API__ > 9
#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) # if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
friend class AndroidJNIIOSystem; friend class AndroidJNIIOSystem;
#endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) # endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
#endif // __ANDROID_API__ > 9 # endif // __ANDROID_API__ > 9
#endif // __ANDROID__ #endif // __ANDROID__
protected: protected:
@ -111,7 +111,7 @@ private:
std::string mFilename; std::string mFilename;
// Cached file size // Cached file size
mutable size_t cachedSize; mutable size_t mCachedSize;
}; };
@ -119,7 +119,7 @@ private:
inline DefaultIOStream::DefaultIOStream () : inline DefaultIOStream::DefaultIOStream () :
mFile (NULL), mFile (NULL),
mFilename (""), mFilename (""),
cachedSize (SIZE_MAX) mCachedSize(SIZE_MAX)
{ {
// empty // empty
} }
@ -130,7 +130,7 @@ inline DefaultIOStream::DefaultIOStream (FILE* pFile,
const std::string &strFilename) : const std::string &strFilename) :
mFile(pFile), mFile(pFile),
mFilename(strFilename), mFilename(strFilename),
cachedSize (SIZE_MAX) mCachedSize(SIZE_MAX)
{ {
// empty // empty
} }

View File

@ -1916,57 +1916,92 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
return; return;
} }
const Texture* const tex = ( *it ).second->getTexture(); int texCount = (*it).second->textureCount();
// Set the blend mode for layered textures
int blendmode= (*it).second->GetBlendMode();
out_mat->AddProperty(&blendmode,1,_AI_MATKEY_TEXOP_BASE,target,0);
aiString path; for(int texIndex = 0; texIndex < texCount; texIndex++){
path.Set( tex->RelativeFilename() );
const Texture* const tex = ( *it ).second->getTexture(texIndex);
out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); aiString path;
path.Set( tex->RelativeFilename() );
aiUVTransform uvTrafo; out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
// XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation();
out_mat->AddProperty( &uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0 );
const PropertyTable& props = tex->Props(); aiUVTransform uvTrafo;
// XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation();
out_mat->AddProperty( &uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex );
int uvIndex = 0; const PropertyTable& props = tex->Props();
bool ok; int uvIndex = 0;
const std::string& uvSet = PropertyGet<std::string>( props, "UVSet", ok );
if ( ok ) {
// "default" is the name which usually appears in the FbxFileTexture template
if ( uvSet != "default" && uvSet.length() ) {
// this is a bit awkward - we need to find a mesh that uses this
// material and scan its UV channels for the given UV name because
// assimp references UV channels by index, not by name.
// XXX: the case that UV channels may appear in different orders bool ok;
// in meshes is unhandled. A possible solution would be to sort const std::string& uvSet = PropertyGet<std::string>( props, "UVSet", ok );
// the UV channels alphabetically, but this would have the side if ( ok ) {
// effect that the primary (first) UV channel would sometimes // "default" is the name which usually appears in the FbxFileTexture template
// be moved, causing trouble when users read only the first if ( uvSet != "default" && uvSet.length() ) {
// UV channel and ignore UV channel assignments altogether. // this is a bit awkward - we need to find a mesh that uses this
// material and scan its UV channels for the given UV name because
// assimp references UV channels by index, not by name.
const unsigned int matIndex = static_cast<unsigned int>( std::distance( materials.begin(), // XXX: the case that UV channels may appear in different orders
std::find( materials.begin(), materials.end(), out_mat ) // in meshes is unhandled. A possible solution would be to sort
) ); // the UV channels alphabetically, but this would have the side
// effect that the primary (first) UV channel would sometimes
// be moved, causing trouble when users read only the first
// UV channel and ignore UV channel assignments altogether.
uvIndex = -1; const unsigned int matIndex = static_cast<unsigned int>( std::distance( materials.begin(),
if ( !mesh ) std::find( materials.begin(), materials.end(), out_mat )
{ ) );
for( const MeshMap::value_type& v : meshes_converted ) {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> ( v.first ); uvIndex = -1;
if ( !mesh ) { if ( !mesh )
continue; {
for( const MeshMap::value_type& v : meshes_converted ) {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> ( v.first );
if ( !mesh ) {
continue;
}
const MatIndexArray& mats = mesh->GetMaterialIndices();
if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) {
continue;
}
int index = -1;
for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
if ( mesh->GetTextureCoords( i ).empty() ) {
break;
}
const std::string& name = mesh->GetTextureCoordChannelName( i );
if ( name == uvSet ) {
index = static_cast<int>( i );
break;
}
}
if ( index == -1 ) {
FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" );
continue;
}
if ( uvIndex == -1 ) {
uvIndex = index;
}
else {
FBXImporter::LogWarn( "the UV channel named " + uvSet +
" appears at different positions in meshes, results will be wrong" );
}
} }
}
const MatIndexArray& mats = mesh->GetMaterialIndices(); else
if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) { {
continue;
}
int index = -1; int index = -1;
for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
if ( mesh->GetTextureCoords( i ).empty() ) { if ( mesh->GetTextureCoords( i ).empty() ) {
@ -1980,48 +2015,22 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
} }
if ( index == -1 ) { if ( index == -1 ) {
FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" ); FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" );
continue;
} }
if ( uvIndex == -1 ) { if ( uvIndex == -1 ) {
uvIndex = index; uvIndex = index;
} }
else {
FBXImporter::LogWarn( "the UV channel named " + uvSet +
" appears at different positions in meshes, results will be wrong" );
}
}
}
else
{
int index = -1;
for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
if ( mesh->GetTextureCoords( i ).empty() ) {
break;
}
const std::string& name = mesh->GetTextureCoordChannelName( i );
if ( name == uvSet ) {
index = static_cast<int>( i );
break;
}
}
if ( index == -1 ) {
FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" );
} }
if ( uvIndex == -1 ) { if ( uvIndex == -1 ) {
uvIndex = index; FBXImporter::LogWarn( "failed to resolve UV channel " + uvSet + ", using first UV channel" );
uvIndex = 0;
} }
} }
if ( uvIndex == -1 ) {
FBXImporter::LogWarn( "failed to resolve UV channel " + uvSet + ", using first UV channel" );
uvIndex = 0;
}
} }
}
out_mat->AddProperty( &uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0 ); out_mat->AddProperty( &uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex );
}
} }
void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh ) void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh )
@ -2030,6 +2039,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& tex
TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh ); TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh );
TrySetTextureProperties( out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh ); TrySetTextureProperties( out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh );
TrySetTextureProperties( out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh ); TrySetTextureProperties( out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh );
TrySetTextureProperties( out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
TrySetTextureProperties( out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh ); TrySetTextureProperties( out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh );
TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh );
@ -2044,6 +2054,7 @@ void Converter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureM
TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
TrySetTextureProperties( out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh );
TrySetTextureProperties( out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh );

View File

@ -594,23 +594,24 @@ public:
BlendMode_BlendModeCount BlendMode_BlendModeCount
}; };
const Texture* getTexture() const const Texture* getTexture(int index=0) const
{ {
return texture; return textures[index];
}
BlendMode GetBlendMode() }
const int textureCount() const {
return textures.size();
}
const BlendMode GetBlendMode() const
{ {
return blendMode; return blendMode;
} }
float Alpha() float Alpha()
{ {
return alpha; return alpha;
} }
private: private:
const Texture* texture; std::vector<const Texture*> textures;
BlendMode blendMode; BlendMode blendMode;
float alpha; float alpha;
}; };

View File

@ -227,7 +227,6 @@ Texture::~Texture()
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
: Object(id,element,name) : Object(id,element,name)
,texture(0)
,blendMode(BlendMode_Modulate) ,blendMode(BlendMode_Modulate)
,alpha(1) ,alpha(1)
{ {
@ -249,7 +248,7 @@ LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Docume
LayeredTexture::~LayeredTexture() LayeredTexture::~LayeredTexture()
{ {
} }
void LayeredTexture::fillTexture(const Document& doc) void LayeredTexture::fillTexture(const Document& doc)
@ -267,7 +266,7 @@ void LayeredTexture::fillTexture(const Document& doc)
const Texture* const tex = dynamic_cast<const Texture*>(ob); const Texture* const tex = dynamic_cast<const Texture*>(ob);
texture = tex; textures.push_back(tex);
} }
} }

View File

@ -282,7 +282,7 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
const size_t next = (i+1)%size; const size_t next = (i+1)%size;
result.vertcnt.push_back(4); result.vertcnt.push_back(4);
const IfcVector3& base_0 = out[base+i*4+3],base_1 = out[base+next*4+3]; const IfcVector3 base_0 = out[base+i*4+3],base_1 = out[base+next*4+3];
out.push_back(base_0); out.push_back(base_0);
out.push_back(base_1); out.push_back(base_1);

View File

@ -731,6 +731,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
} }
VALIDATE_FILE_SIZE(szCurrent); VALIDATE_FILE_SIZE(szCurrent);
*szCurrentOut = szCurrent; *szCurrentOut = szCurrent;
if ( nullptr != pcNew ) {
delete pcNew;
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -171,7 +171,7 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
// build output vertex weights // build output vertex weights
for (unsigned int i = 0;i < pcMesh->mNumBones;++i) for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
{ {
delete pcMesh->mBones[i]->mWeights; delete [] pcMesh->mBones[i]->mWeights;
if (!newWeights[i].empty()) { if (!newWeights[i].empty()) {
pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()]; pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
aiVertexWeight *weightToCopy = &( newWeights[i][0] ); aiVertexWeight *weightToCopy = &( newWeights[i][0] );

View File

@ -39,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "DefaultIOSystem.h" #include "DefaultIOSystem.h"
@ -52,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Wavefront Object Importer", "Wavefront Object Importer",
"", "",

View File

@ -696,6 +696,8 @@ void ObjFileParser::getGroupName()
{ {
std::string strGroupName; std::string strGroupName;
// here we skip 'g ' from line
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName); m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) { if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
return; return;
@ -832,7 +834,11 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName )
bool newMat = false; bool newMat = false;
int matIdx = getMaterialIndex( materialName ); int matIdx = getMaterialIndex( materialName );
int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx ) if ( curMatIdx != int(ObjFile::Mesh::NoMaterial)
&& curMatIdx != matIdx
// no need create a new mesh if no faces in current
// lets say 'usemtl' goes straight after 'g'
&& m_pModel->m_pCurrentMesh->m_Faces.size() > 0 )
{ {
// New material -> only one material per mesh, so we need to create a new // New material -> only one material per mesh, so we need to create a new
// material // material

View File

@ -56,11 +56,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//using namespace Assimp; //using namespace Assimp;
namespace Assimp { namespace Assimp {
// make sure typeof returns consistent output across different platforms // make sure type_of returns consistent output across different platforms
// also consider using: typeid(VAR).name() // also consider using: typeid(VAR).name()
template <typename T> const char* typeof(T&) { return "unknown"; } template <typename T> const char* type_of(T&) { return "unknown"; }
template<> const char* typeof(float&) { return "float"; } template<> const char* type_of(float&) { return "float"; }
template<> const char* typeof(double&) { return "double"; } template<> const char* type_of(double&) { return "double"; }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
@ -146,7 +146,7 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina
// definitely not good to always write float even if we might have double precision // definitely not good to always write float even if we might have double precision
ai_real tmp = 0.0; ai_real tmp = 0.0;
const char * typeName = typeof(tmp); const char * typeName = type_of(tmp);
mOutput << "element vertex " << vertices << endl; mOutput << "element vertex " << vertices << endl;
mOutput << "property " << typeName << " x" << endl; mOutput << "property " << typeName << " x" << endl;

View File

@ -102,12 +102,16 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
XGLImporter::XGLImporter() XGLImporter::XGLImporter()
{} : m_reader( nullptr )
, m_scene( nullptr ) {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
XGLImporter::~XGLImporter() XGLImporter::~XGLImporter() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
@ -149,7 +153,7 @@ void XGLImporter::InternReadFile( const std::string& pFile,
free_it free_it_really(dest); free_it free_it_really(dest);
#endif #endif
scene = pScene; m_scene = pScene;
std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb")); std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
// check whether we can read from the file // check whether we can read from the file
@ -211,14 +215,13 @@ void XGLImporter::InternReadFile( const std::string& pFile,
// construct the irrXML parser // construct the irrXML parser
CIrrXML_IOStreamReader st(stream.get()); CIrrXML_IOStreamReader st(stream.get());
std::unique_ptr<IrrXMLReader> read( createIrrXMLReader((IFileReadCallBack*) &st) ); m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );
reader = read.get();
// parse the XML file // parse the XML file
TempScope scope; TempScope scope;
while (ReadElement()) { while (ReadElement()) {
if (!ASSIMP_stricmp(reader->getNodeName(),"world")) { if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) {
ReadWorld(scope); ReadWorld(scope);
} }
} }
@ -231,21 +234,21 @@ void XGLImporter::InternReadFile( const std::string& pFile,
} }
// copy meshes // copy meshes
scene->mNumMeshes = static_cast<unsigned int>(meshes.size()); m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
scene->mMeshes = new aiMesh*[scene->mNumMeshes](); m_scene->mMeshes = new aiMesh*[m_scene->mNumMeshes]();
std::copy(meshes.begin(),meshes.end(),scene->mMeshes); std::copy(meshes.begin(),meshes.end(),m_scene->mMeshes);
// copy materials // copy materials
scene->mNumMaterials = static_cast<unsigned int>(materials.size()); m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
scene->mMaterials = new aiMaterial*[scene->mNumMaterials](); m_scene->mMaterials = new aiMaterial*[m_scene->mNumMaterials]();
std::copy(materials.begin(),materials.end(),scene->mMaterials); std::copy(materials.begin(),materials.end(),m_scene->mMaterials);
if (scope.light) { if (scope.light) {
scene->mNumLights = 1; m_scene->mNumLights = 1;
scene->mLights = new aiLight*[1]; m_scene->mLights = new aiLight*[1];
scene->mLights[0] = scope.light; m_scene->mLights[0] = scope.light;
scope.light->mName = scene->mRootNode->mName; scope.light->mName = m_scene->mRootNode->mName;
} }
scope.dismiss(); scope.dismiss();
@ -254,8 +257,8 @@ void XGLImporter::InternReadFile( const std::string& pFile,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElement() bool XGLImporter::ReadElement()
{ {
while(reader->read()) { while(m_reader->read()) {
if (reader->getNodeType() == EXN_ELEMENT) { if (m_reader->getNodeType() == EXN_ELEMENT) {
return true; return true;
} }
} }
@ -265,11 +268,11 @@ bool XGLImporter::ReadElement()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElementUpToClosing(const char* closetag) bool XGLImporter::ReadElementUpToClosing(const char* closetag)
{ {
while(reader->read()) { while(m_reader->read()) {
if (reader->getNodeType() == EXN_ELEMENT) { if (m_reader->getNodeType() == EXN_ELEMENT) {
return true; return true;
} }
else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),closetag)) { else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(),closetag)) {
return false; return false;
} }
} }
@ -280,11 +283,11 @@ bool XGLImporter::ReadElementUpToClosing(const char* closetag)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool XGLImporter::SkipToText() bool XGLImporter::SkipToText()
{ {
while(reader->read()) { while(m_reader->read()) {
if (reader->getNodeType() == EXN_TEXT) { if (m_reader->getNodeType() == EXN_TEXT) {
return true; return true;
} }
else if (reader->getNodeType() == EXN_ELEMENT || reader->getNodeType() == EXN_ELEMENT_END) { else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
ThrowException("expected text contents but found another element (or element end)"); ThrowException("expected text contents but found another element (or element end)");
} }
} }
@ -294,7 +297,7 @@ bool XGLImporter::SkipToText()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string XGLImporter::GetElementName() std::string XGLImporter::GetElementName()
{ {
const char* s = reader->getNodeName(); const char* s = m_reader->getNodeName();
size_t len = strlen(s); size_t len = strlen(s);
std::string ret; std::string ret;
@ -328,7 +331,7 @@ void XGLImporter::ReadWorld(TempScope& scope)
nd->mName.Set("WORLD"); nd->mName.Set("WORLD");
} }
scene->mRootNode = nd; m_scene->mRootNode = nd;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -586,29 +589,29 @@ bool XGLImporter::ReadMesh(TempScope& scope)
ReadMaterial(scope); ReadMaterial(scope);
} }
else if (s == "p") { else if (s == "p") {
if (!reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <p>, ignoring"); LogWarn("no ID attribute on <p>, ignoring");
} }
else { else {
int id = reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.points[id] = ReadVec3(); t.points[id] = ReadVec3();
} }
} }
else if (s == "n") { else if (s == "n") {
if (!reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <n>, ignoring"); LogWarn("no ID attribute on <n>, ignoring");
} }
else { else {
int id = reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.normals[id] = ReadVec3(); t.normals[id] = ReadVec3();
} }
} }
else if (s == "tc") { else if (s == "tc") {
if (!reader->getAttributeValue("ID")) { if (!m_reader->getAttributeValue("ID")) {
LogWarn("no ID attribute on <tc>, ignoring"); LogWarn("no ID attribute on <tc>, ignoring");
} }
else { else {
int id = reader->getAttributeValueAsInt("ID"); int id = m_reader->getAttributeValueAsInt("ID");
t.uvs[id] = ReadVec2(); t.uvs[id] = ReadVec2();
} }
} }
@ -828,10 +831,10 @@ void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIDAttr() unsigned int XGLImporter::ReadIDAttr()
{ {
for(int i = 0, e = reader->getAttributeCount(); i < e; ++i) { for(int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
if(!ASSIMP_stricmp(reader->getAttributeName(i),"id")) { if(!ASSIMP_stricmp(m_reader->getAttributeName(i),"id")) {
return reader->getAttributeValueAsInt(i); return m_reader->getAttributeValueAsInt(i);
} }
} }
return ~0u; return ~0u;
@ -844,7 +847,7 @@ float XGLImporter::ReadFloat()
LogError("unexpected EOF reading float element contents"); LogError("unexpected EOF reading float element contents");
return 0.f; return 0.f;
} }
const char* s = reader->getNodeData(), *se; const char* s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) { if(!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse float"); LogError("unexpected EOL, failed to parse float");
@ -869,7 +872,7 @@ unsigned int XGLImporter::ReadIndexFromText()
LogError("unexpected EOF reading index element contents"); LogError("unexpected EOF reading index element contents");
return ~0u; return ~0u;
} }
const char* s = reader->getNodeData(), *se; const char* s = m_reader->getNodeData(), *se;
if(!SkipSpaces(&s)) { if(!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse index element"); LogError("unexpected EOL, failed to parse index element");
return ~0u; return ~0u;
@ -894,7 +897,7 @@ aiVector2D XGLImporter::ReadVec2()
LogError("unexpected EOF reading vec2 contents"); LogError("unexpected EOF reading vec2 contents");
return vec; return vec;
} }
const char* s = reader->getNodeData(); const char* s = m_reader->getNodeData();
for(int i = 0; i < 2; ++i) { for(int i = 0; i < 2; ++i) {
if(!SkipSpaces(&s)) { if(!SkipSpaces(&s)) {
@ -923,7 +926,7 @@ aiVector3D XGLImporter::ReadVec3()
LogError("unexpected EOF reading vec3 contents"); LogError("unexpected EOF reading vec3 contents");
return vec; return vec;
} }
const char* s = reader->getNodeData(); const char* s = m_reader->getNodeData();
for(int i = 0; i < 3; ++i) { for(int i = 0; i < 3; ++i) {
if(!SkipSpaces(&s)) { if(!SkipSpaces(&s)) {

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/light.h> #include <assimp/light.h>
#include <memory>
struct aiNode; struct aiNode;
@ -203,12 +204,8 @@ private:
unsigned int ResolveMaterialRef(TempScope& scope); unsigned int ResolveMaterialRef(TempScope& scope);
private: private:
std::shared_ptr<irr::io::IrrXMLReader> m_reader;
aiScene* m_scene;
private:
irr::io::IrrXMLReader* reader;
aiScene* scene;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -40,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringUtils.h" #include "StringUtils.h"
using namespace Assimp;
namespace glTF { namespace glTF {
namespace { namespace {

View File

@ -105,7 +105,7 @@ namespace glTF {
type = "arraybuffer"; type = "arraybuffer";
} }
obj.AddMember("byteLength", b.byteLength, w.mAl); obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl);
obj.AddMember("type", StringRef(type), w.mAl); obj.AddMember("type", StringRef(type), w.mAl);
obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl); obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl);
} }
@ -113,8 +113,8 @@ namespace glTF {
inline void Write(Value& obj, BufferView& bv, AssetWriter& w) inline void Write(Value& obj, BufferView& bv, AssetWriter& w)
{ {
obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl); obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl);
obj.AddMember("byteOffset", bv.byteOffset, w.mAl); obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
obj.AddMember("byteLength", bv.byteLength, w.mAl); obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
obj.AddMember("target", int(bv.target), w.mAl); obj.AddMember("target", int(bv.target), w.mAl);
} }

View File

@ -93,11 +93,11 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc
, mScene(pScene) , mScene(pScene)
, mProperties(pProperties) , mProperties(pProperties)
{ {
std::unique_ptr<Asset> asset(new glTF::Asset(pIOSystem)); std::unique_ptr<Asset> asset();
mAsset = asset.get(); mAsset.reset( new glTF::Asset( pIOSystem ) );
if (isBinary) { if (isBinary) {
asset->SetAsBinary(); mAsset->SetAsBinary();
} }
ExportMetadata(); ExportMetadata();

View File

@ -46,13 +46,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/types.h> #include <assimp/types.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <memory> #include <memory>
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
struct aiMaterial; struct aiMaterial;
@ -89,7 +88,7 @@ namespace Assimp
std::map<std::string, unsigned int> mTexturesByPath; std::map<std::string, unsigned int> mTexturesByPath;
glTF::Asset* mAsset; std::shared_ptr<glTF::Asset> mAsset;
std::vector<unsigned char> mBodyData; std::vector<unsigned char> mBodyData;

View File

@ -303,7 +303,7 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
attr.normal[0]->ExtractData(aim->mNormals); attr.normal[0]->ExtractData(aim->mNormals);
} }
for (size_t tc = 0; tc < attr.texcoord.size() && tc <= AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();

View File

@ -280,7 +280,7 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std:
statement += "["; statement += "[";
char buffer[ 256 ]; char buffer[ 256 ];
::memset( buffer, '\0', 256 * sizeof( char ) ); ::memset( buffer, '\0', 256 * sizeof( char ) );
sprintf( buffer, "%d", numItems ); sprintf( buffer, "%d", int(numItems) );
statement += buffer; statement += buffer;
statement += "]"; statement += "]";
} }

View File

@ -181,7 +181,7 @@ public:
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
chunkHead_->size += size; chunkHead_->size += size;
return buffer; return buffer;
} }
@ -199,7 +199,7 @@ public:
return originalPtr; return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space // Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize); size_t increment = static_cast<size_t>(newSize - originalSize);
increment = RAPIDJSON_ALIGN(increment); increment = RAPIDJSON_ALIGN(increment);
if (chunkHead_->size + increment <= chunkHead_->capacity) { if (chunkHead_->size + increment <= chunkHead_->capacity) {
@ -231,7 +231,7 @@ private:
void AddChunk(size_t capacity) { void AddChunk(size_t capacity) {
if (!baseAllocator_) if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity)); ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
chunk->capacity = capacity; chunk->capacity = capacity;
chunk->size = 0; chunk->size = 0;
chunk->next = chunkHead_; chunk->next = chunkHead_;

View File

@ -69,9 +69,6 @@ RAPIDJSON_NAMESPACE_BEGIN
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericValue; class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
//! Name-value pair in a JSON object value. //! Name-value pair in a JSON object value.
/*! /*!
This class was internal to GenericValue. It used to be a inner struct. This class was internal to GenericValue. It used to be a inner struct.
@ -449,16 +446,6 @@ private:
//! Copy constructor is not permitted. //! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs); GenericValue(const GenericValue& rhs);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Moving from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
//! Move assignment from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
#endif
public: public:
//! Constructor with JSON value type. //! Constructor with JSON value type.
@ -545,28 +532,6 @@ public:
flags_ |= kIntFlag; flags_ |= kIntFlag;
} }
#if defined(__APPLE__)
//! Constructor for unsigned long value.
explicit GenericValue(unsigned long u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
data_.n.u64 = u64;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
flags_ |= kInt64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
flags_ |= kUintFlag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
flags_ |= kIntFlag;
}
#if !defined(__x86_64__) && !defined(__arm64__)
//! Constructor for size_t value.
explicit GenericValue( size_t u ) RAPIDJSON_NOEXCEPT : data_(), flags_( kNumberUintFlag ) {
data_.n.u64 = u;
if ( !( u&0x80000000 ) )
flags_ |= kIntFlag|kInt64Flag;
}
#endif
#endif
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
@ -695,20 +660,6 @@ public:
return *this; return *this;
} }
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Prepare Value for move semantics //! Prepare Value for move semantics
/*! \return *this */ /*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
@ -1262,31 +1213,6 @@ public:
return pos; return pos;
} }
//! Erase a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note Linear time complexity.
*/
bool EraseMember(const Ch* name) {
GenericValue n(StringRef(name));
return EraseMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
EraseMember(m);
return true;
}
else
return false;
}
//@} //@}
//!@name Array //!@name Array
@ -1798,22 +1724,7 @@ public:
typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor //! Constructor
/*! Creates an empty document of specified type. /*! \param allocator Optional allocator for allocating memory.
\param type Mandatory type of object to create.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
//! Constructor
/*! Creates an empty document which type is Null.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes. \param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack. \param stackAllocator Optional allocator for allocating memory for stack.
*/ */
@ -1827,7 +1738,7 @@ public:
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11 //! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
: ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document : ValueType(std::move(rhs)),
allocator_(rhs.allocator_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)), stack_(std::move(rhs.stack_)),
@ -1867,35 +1778,6 @@ public:
} }
#endif #endif
//! Exchange the contents of this document with those of another.
/*!
\param other Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//!@name Parse from stream //!@name Parse from stream
//!@{ //!@{
@ -1908,13 +1790,13 @@ public:
*/ */
template <unsigned parseFlags, typename SourceEncoding, typename InputStream> template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
GenericDocument& ParseStream(InputStream& is) { GenericDocument& ParseStream(InputStream& is) {
GenericReader<SourceEncoding, Encoding, StackAllocator> reader( ValueType::SetNull(); // Remove existing root if exist
stack_.HasAllocator() ? &stack_.GetAllocator() : 0); GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.GetAllocator());
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
parseResult_ = reader.template Parse<parseFlags>(is, *this); parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) { if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
} }
return *this; return *this;
} }
@ -2011,10 +1893,7 @@ public:
//!@} //!@}
//! Get the allocator of this document. //! Get the allocator of this document.
Allocator& GetAllocator() { Allocator& GetAllocator() { return *allocator_; }
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
//! Get the capacity of stack in bytes. //! Get the capacity of stack in bytes.
size_t GetStackCapacity() const { return stack_.GetCapacity(); } size_t GetStackCapacity() const { return stack_.GetCapacity(); }
@ -2123,7 +2002,6 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
default: // kNumberType, kTrueType, kFalseType, kNullType default: // kNumberType, kTrueType, kFalseType, kNullType
flags_ = rhs.flags_; flags_ = rhs.flags_;
data_ = *reinterpret_cast<const Data*>(&rhs.data_); data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
} }
} }

View File

@ -77,8 +77,8 @@ public:
void Flush() { os_.Flush(); } void Flush() { os_.Flush(); }
// Not implemented // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} Ch Peek() const { RAPIDJSON_ASSERT(false); }
Ch Take() { RAPIDJSON_ASSERT(false); return 0;} Ch Take() { RAPIDJSON_ASSERT(false); }
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
@ -146,7 +146,7 @@ private:
if (!c) if (!c)
return; return;
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
hasBOM_ = false; hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
@ -227,8 +227,8 @@ public:
void Flush() { os_->Flush(); } void Flush() { os_->Flush(); }
// Not implemented // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} Ch Peek() const { RAPIDJSON_ASSERT(false); }
Ch Take() { RAPIDJSON_ASSERT(false); return 0;} Ch Take() { RAPIDJSON_ASSERT(false); }
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }

View File

@ -57,11 +57,7 @@ public:
void Flush() { void Flush() {
if (current_ != buffer_) { if (current_ != buffer_) {
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_); fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
if (result < static_cast<size_t>(current_ - buffer_)) {
// failure deliberately ignored at this time
// added to avoid warn_unused_result build errors
}
current_ = buffer_; current_ = buffer_;
} }
} }

View File

@ -19,7 +19,6 @@
#if defined(_MSC_VER) && defined(_M_AMD64) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128 #include <intrin.h> // for _umul128
#pragma intrinsic(_umul128)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -51,16 +50,7 @@ public:
if (length > 0) if (length > 0)
AppendDecimal64(decimals + i, decimals + i + length); AppendDecimal64(decimals + i, decimals + i + length);
} }
BigInteger& operator=(const BigInteger &rhs)
{
if (this != &rhs) {
count_ = rhs.count_;
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
}
return *this;
}
BigInteger& operator=(uint64_t u) { BigInteger& operator=(uint64_t u) {
digits_[0] = u; digits_[0] = u;
count_ = 1; count_ = 1;
@ -240,7 +230,7 @@ private:
uint64_t r = 0; uint64_t r = 0;
for (const char* p = begin; p != end; ++p) { for (const char* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
r = r * 10u + (unsigned)(*p - '0'); r = r * 10 + (*p - '0');
} }
return r; return r;
} }

View File

@ -24,7 +24,6 @@
#if defined(_MSC_VER) && defined(_M_AMD64) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -233,8 +232,8 @@ inline DiyFp GetCachedPower(int e, int* K) {
} }
inline DiyFp GetCachedPower10(int exp, int *outExp) { inline DiyFp GetCachedPower10(int exp, int *outExp) {
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u; unsigned index = (exp + 348) / 8;
*outExp = -348 + static_cast<int>(index) * 8; *outExp = -348 + index * 8;
return GetCachedPowerByIndex(index); return GetCachedPowerByIndex(index);
} }

View File

@ -62,7 +62,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
const DiyFp wp_w = Mp - W; const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1); uint64_t p2 = Mp.f & (one.f - 1);
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0; *len = 0;
while (kappa > 0) { while (kappa > 0) {
@ -101,7 +101,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--; kappa--;
if (p2 < delta) { if (p2 < delta) {
*K += kappa; *K += kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast<int>(kappa)]); GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
return; return;
} }
} }
@ -158,14 +158,14 @@ inline char* Prettify(char* buffer, int length, int k) {
} }
else if (0 < kk && kk <= 21) { else if (0 < kk && kk <= 21) {
// 1234e-2 -> 12.34 // 1234e-2 -> 12.34
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk)); std::memmove(&buffer[kk + 1], &buffer[kk], length - kk);
buffer[kk] = '.'; buffer[kk] = '.';
return &buffer[length + 1]; return &buffer[length + 1];
} }
else if (-6 < kk && kk <= 0) { else if (-6 < kk && kk <= 0) {
// 1234e-6 -> 0.001234 // 1234e-6 -> 0.001234
const int offset = 2 - kk; const int offset = 2 - kk;
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length)); std::memmove(&buffer[offset], &buffer[0], length);
buffer[0] = '0'; buffer[0] = '0';
buffer[1] = '.'; buffer[1] = '.';
for (int i = 2; i < offset; i++) for (int i = 2; i < offset; i++)
@ -179,7 +179,7 @@ inline char* Prettify(char* buffer, int length, int k) {
} }
else { else {
// 1234e30 -> 1.234e33 // 1234e30 -> 1.234e33
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1)); std::memmove(&buffer[2], &buffer[1], length - 1);
buffer[1] = '.'; buffer[1] = '.';
buffer[length + 1] = 'e'; buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]); return WriteExponent(kk - 1, &buffer[0 + length + 2]);

View File

@ -53,7 +53,7 @@ public:
else if (order <= -1074) else if (order <= -1074)
return 0; return 0;
else else
return (unsigned)order + 1074; return order + 1074;
} }
private: private:

View File

@ -16,7 +16,6 @@
#define RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_
#include "../rapidjson.h" #include "../rapidjson.h"
#include "swap.h"
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
@ -82,15 +81,6 @@ public:
} }
#endif #endif
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(stack_, rhs.stack_);
internal::Swap(stackTop_, rhs.stackTop_);
internal::Swap(stackEnd_, rhs.stackEnd_);
internal::Swap(initialCapacity_, rhs.initialCapacity_);
}
void Clear() { stackTop_ = stack_; } void Clear() { stackTop_ = stack_; }
void ShrinkToFit() { void ShrinkToFit() {
@ -134,14 +124,7 @@ public:
template<typename T> template<typename T>
T* Bottom() { return (T*)stack_; } T* Bottom() { return (T*)stack_; }
bool HasAllocator() const { Allocator& GetAllocator() { return *allocator_; }
return allocator_ != 0;
}
Allocator& GetAllocator() {
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
bool Empty() const { return stackTop_ == stack_; } bool Empty() const { return stackTop_ == stack_; }
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }

View File

@ -95,13 +95,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
hS_Exp2 -= common_Exp2; hS_Exp2 -= common_Exp2;
BigInteger dS = d; BigInteger dS = d;
dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2); dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2;
BigInteger bS(bInt); BigInteger bS(bInt);
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2); bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
BigInteger hS(1); BigInteger hS(1);
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2); hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
BigInteger delta(0); BigInteger delta(0);
dS.Difference(bS, &delta); dS.Difference(bS, &delta);
@ -134,7 +134,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
break; break;
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); significand = significand * 10 + (decimals[i] - '0');
} }
if (i < length && decimals[i] >= '5') // Rounding if (i < length && decimals[i] >= '5') // Rounding
@ -163,10 +163,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
}; };
int adjustment = dExp - actualExp - 1; int adjustment = dExp - actualExp - 1;
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment]; v = v * kPow10[adjustment];
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit if (length + adjustment > 19) // has more digits than decimal digits in 64-bit
error += kUlp / 2; error += kUlp / 2;
} }
@ -184,14 +184,14 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
unsigned scaleExp = (precisionSize + kUlpShift) - 63; unsigned scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp; v.f >>= scaleExp;
v.e += scaleExp; v.e += scaleExp;
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp); error = (error >> scaleExp) + 1 + kUlp;
precisionSize -= scaleExp; precisionSize -= scaleExp;
} }
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize)); DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
if (precisionBits >= halfWay + static_cast<unsigned>(error)) { if (precisionBits >= halfWay + error) {
rounded.f++; rounded.f++;
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
rounded.f >>= 1; rounded.f >>= 1;
@ -201,7 +201,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
*result = rounded.ToDouble(); *result = rounded.ToDouble();
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); return halfWay - error >= precisionBits || precisionBits >= halfWay + error;
} }
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
@ -249,7 +249,7 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
if ((int)length > kMaxDecimalDigit) { if ((int)length > kMaxDecimalDigit) {
int delta = (int(length) - kMaxDecimalDigit); int delta = (int(length) - kMaxDecimalDigit);
exp += delta; exp += delta;
decimalPosition -= static_cast<unsigned>(delta); decimalPosition -= delta;
length = kMaxDecimalDigit; length = kMaxDecimalDigit;
} }

View File

@ -223,7 +223,7 @@
//! Whether using 64-bit architecture //! Whether using 64-bit architecture
#ifndef RAPIDJSON_64BIT #ifndef RAPIDJSON_64BIT
#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__) #if defined(__LP64__) || defined(_WIN64)
#define RAPIDJSON_64BIT 1 #define RAPIDJSON_64BIT 1
#else #else
#define RAPIDJSON_64BIT 0 #define RAPIDJSON_64BIT 0
@ -238,13 +238,13 @@
\param x pointer to align \param x pointer to align
Some machines require strict data alignment. Currently the default uses 4 bytes Some machines require strict data alignment. Currently the default uses 4 bytes
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro. alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.,
*/ */
#ifndef RAPIDJSON_ALIGN #ifndef RAPIDJSON_ALIGN
#if RAPIDJSON_64BIT == 1 #if RAPIDJSON_64BIT == 1
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u)) #define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u)
#else #else
#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) #define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
#endif #endif
#endif #endif

View File

@ -140,7 +140,6 @@ enum ParseFlag {
kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
}; };
@ -272,7 +271,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
// The rest of string using SIMD // The rest of string using SIMD
static const char whitespace[16] = " \n\r\t"; static const char whitespace[16] = " \n\r\t";
const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128((const __m128i *)p); const __m128i s = _mm_load_si128((const __m128i *)p);
@ -399,8 +398,7 @@ public:
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
if (is.Peek() == '\0') { if (is.Peek() == '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
@ -411,8 +409,7 @@ public:
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
if (!(parseFlags & kParseStopWhenDoneFlag)) { if (!(parseFlags & kParseStopWhenDoneFlag)) {
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
if (is.Peek() != '\0') { if (is.Peek() != '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
@ -465,40 +462,6 @@ private:
ClearStackOnExit& operator=(const ClearStackOnExit&); ClearStackOnExit& operator=(const ClearStackOnExit&);
}; };
template<unsigned parseFlags, typename InputStream>
void SkipWhitespaceAndComments(InputStream& is) {
SkipWhitespace(is);
if (parseFlags & kParseCommentsFlag) {
while (is.Peek() == '/') {
is.Take();
if (is.Peek() == '*') {
is.Take();
while (true) {
if (is.Peek() == '\0')
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
if (is.Take() == '*') {
if (is.Peek() == '\0')
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
if (is.Take() == '/')
break;
}
}
} else if (is.Peek() == '/') {
is.Take();
while (is.Peek() != '\0' && is.Take() != '\n') { }
} else {
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
}
SkipWhitespace(is);
}
}
}
// Parse object: { string : value, ... } // Parse object: { string : value, ... }
template<unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseObject(InputStream& is, Handler& handler) { void ParseObject(InputStream& is, Handler& handler) {
@ -508,8 +471,7 @@ private:
if (!handler.StartObject()) if (!handler.StartObject())
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Peek() == '}') { if (is.Peek() == '}') {
is.Take(); is.Take();
@ -525,35 +487,27 @@ private:
ParseString<parseFlags>(is, handler, true); ParseString<parseFlags>(is, handler, true);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Take() != ':') if (is.Take() != ':')
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
ParseValue<parseFlags>(is, handler); ParseValue<parseFlags>(is, handler);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
++memberCount; ++memberCount;
switch (is.Take()) { switch (is.Take()) {
case ',': case ',': SkipWhitespace(is); break;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
break;
case '}': case '}':
if (!handler.EndObject(memberCount)) if (!handler.EndObject(memberCount))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
default: default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
break;
} }
} }
} }
@ -567,8 +521,7 @@ private:
if (!handler.StartArray()) if (!handler.StartArray())
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (is.Peek() == ']') { if (is.Peek() == ']') {
is.Take(); is.Take();
@ -582,21 +535,15 @@ private:
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
++elementCount; ++elementCount;
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
switch (is.Take()) { switch (is.Take()) {
case ',': case ',': SkipWhitespace(is); break;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
break;
case ']': case ']':
if (!handler.EndArray(elementCount)) if (!handler.EndArray(elementCount))
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
default: default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
break;
} }
} }
} }
@ -1020,13 +967,13 @@ private:
else { else {
if (use64bit) { if (use64bit) {
if (minus) if (minus)
cont = handler.Int64(static_cast<int64_t>(~i64 + 1)); cont = handler.Int64(-(int64_t)i64);
else else
cont = handler.Uint64(i64); cont = handler.Uint64(i64);
} }
else { else {
if (minus) if (minus)
cont = handler.Int(static_cast<int32_t>(~i + 1)); cont = handler.Int(-(int)i);
else else
cont = handler.Uint(i); cont = handler.Uint(i);
} }
@ -1045,10 +992,7 @@ private:
case '"': ParseString<parseFlags>(is, handler); break; case '"': ParseString<parseFlags>(is, handler); break;
case '{': ParseObject<parseFlags>(is, handler); break; case '{': ParseObject<parseFlags>(is, handler); break;
case '[': ParseArray <parseFlags>(is, handler); break; case '[': ParseArray <parseFlags>(is, handler); break;
default : default : ParseNumber<parseFlags>(is, handler);
ParseNumber<parseFlags>(is, handler);
break;
} }
} }
@ -1443,14 +1387,14 @@ private:
} }
switch (src) { switch (src) {
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
case IterativeParsingObjectInitialState: case IterativeParsingObjectInitialState:
case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
} }
} }
@ -1460,8 +1404,7 @@ private:
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
IterativeParsingState state = IterativeParsingStartState; IterativeParsingState state = IterativeParsingStartState;
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
while (is.Peek() != '\0') { while (is.Peek() != '\0') {
Token t = Tokenize(is.Peek()); Token t = Tokenize(is.Peek());
IterativeParsingState n = Predict(state, t); IterativeParsingState n = Predict(state, t);
@ -1478,8 +1421,7 @@ private:
if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
break; break;
SkipWhitespaceAndComments<parseFlags>(is); SkipWhitespace(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
} }
// Handle the end of file. // Handle the end of file.

View File

@ -350,7 +350,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt(int i) { inline bool Writer<StringBuffer>::WriteInt(int i) {
char *buffer = os_->Push(11); char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer); const char* end = internal::i32toa(i, buffer);
os_->Pop(static_cast<size_t>(11 - (end - buffer))); os_->Pop(11 - (end - buffer));
return true; return true;
} }
@ -358,7 +358,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint(unsigned u) { inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
char *buffer = os_->Push(10); char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer); const char* end = internal::u32toa(u, buffer);
os_->Pop(static_cast<size_t>(10 - (end - buffer))); os_->Pop(10 - (end - buffer));
return true; return true;
} }
@ -366,7 +366,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21); char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer); const char* end = internal::i64toa(i64, buffer);
os_->Pop(static_cast<size_t>(21 - (end - buffer))); os_->Pop(21 - (end - buffer));
return true; return true;
} }
@ -374,7 +374,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20); char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer); const char* end = internal::u64toa(u, buffer);
os_->Pop(static_cast<size_t>(20 - (end - buffer))); os_->Pop(20 - (end - buffer));
return true; return true;
} }
@ -382,7 +382,7 @@ template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) { inline bool Writer<StringBuffer>::WriteDouble(double d) {
char *buffer = os_->Push(25); char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer); char* end = internal::dtoa(d, buffer);
os_->Pop(static_cast<size_t>(25 - (end - buffer))); os_->Pop(25 - (end - buffer));
return true; return true;
} }

View File

@ -3,7 +3,7 @@ Tencent is pleased to support the open source community by making RapidJSON avai
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License.
If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON.
A copy of the MIT License is included in this file. A copy of the MIT License is included in this file.
Other dependencies and licenses: Other dependencies and licenses:

View File

@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/)
* RapidJSON Documentation * RapidJSON Documentation
* [English](http://rapidjson.org/) * [English](http://miloyip.github.io/rapidjson/)
* [简体中文](http://rapidjson.org/zh-cn/) * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference.
## Build status ## Build status
@ -31,15 +31,15 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/).
* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. * RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code.
* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. * RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration.
* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL. * RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL.
* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. * RapidJSON is memory friendly. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing.
* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). * RapidJSON is Unicode friendly. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character).
More features can be read [here](doc/features.md). More features can be read [here](doc/features.md).

View File

@ -211,14 +211,14 @@ the dump is written to <tt>&lt;model&gt;-dump.txt</tt>
<p> <p>
<tt>-b<br> <tt>-b<br>
</tt><br> </tt><br>
Optional. If this switch is specified, the dumb is written in binary format. Optional. If this switch is specified, the dump is written in binary format.
The long form of this parameter is <tt>--binary</tt>. The long form of this parameter is <tt>--binary</tt>.
</p> </p>
<p> <p>
<tt>-s&lt;n&gt;<br> <tt>-s&lt;n&gt;<br>
</tt><br> </tt><br>
Optional. If this switch is specified, the dumb is shortened to include only Optional. If this switch is specified, the dump is shortened to include only
min/max values for all vertex components and animation channels. The resulting min/max values for all vertex components and animation channels. The resulting
file is much smaller, but the original model can't be reconstructed from it. This is file is much smaller, but the original model can't be reconstructed from it. This is
used by Assimp's regression test suite, comparing those minidumps provides used by Assimp's regression test suite, comparing those minidumps provides
@ -368,7 +368,6 @@ of all supported steps along with short descriptions of what they're doing. <br>
more information can be found in the <tt>aiPostProcess.h</tt> header. more information can be found in the <tt>aiPostProcess.h</tt> header.
<table border="1"> <table border="1">
<tr> <tr>
<th>Parameter</th> <th>Parameter</th>
<th>Long parameter</th> <th>Long parameter</th>
@ -432,13 +431,13 @@ more information can be found in the <tt>aiPostProcess.h</tt> header.
<td>Improve the cache locality of the vertex buffer by reordering the index buffer <td>Improve the cache locality of the vertex buffer by reordering the index buffer
to achieve a lower ACMR (average post-transform vertex cache miss ratio)</td> to achieve a lower ACMR (average post-transform vertex cache miss ratio)</td>
</tr> </tr>
<tr> <tr>
<td><tt>-sbpt</tt></td> <td><tt>-sbpt</tt></td>
<td><tt>--sort-by-ptype</tt></td> <td><tt>--sort-by-ptype</tt></td>
<td>Splits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up) <td>Splits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up)
in 'clean' submeshes. </td> in 'clean' submeshes. </td>
</tr> </tr>
<tr> <tr>
<td><tt>-lh</tt></td> <td><tt>-lh</tt></td>
<td><tt>--convert-to-lh</tt></td> <td><tt>--convert-to-lh</tt></td>
<td>Converts the imported data to left-handed coordinate space</td> <td>Converts the imported data to left-handed coordinate space</td>
@ -479,19 +478,47 @@ more information can be found in the <tt>aiPostProcess.h</tt> header.
<td>Search the data structure for instanced meshes and replace them by references. This can <td>Search the data structure for instanced meshes and replace them by references. This can
reduce vertex/face counts but the postprocessing-step takes some time.</td> reduce vertex/face counts but the postprocessing-step takes some time.</td>
</tr> </tr>
<tr>
<tr>
<td><tt>-og</tt></td> <td><tt>-og</tt></td>
<td><tt>--optimize-graph</tt></td> <td><tt>--optimize-graph</tt></td>
<td>Simplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost. <td>Simplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost.
Animations remain untouched. </td> Animations remain untouched. </td>
</tr> </tr>
<tr>
<tr>
<td><tt>-om</tt></td> <td><tt>-om</tt></td>
<td><tt>--optimize-mesh</tt></td> <td><tt>--optimize-meshes</tt></td>
<td>Optimize mesh usage. Meshes are merged, if possible. Very effective in combination with <tt>--optimize-graph</tt></td> <td>Optimize mesh usage. Meshes are merged, if possible. Very effective in combination with <tt>--optimize-graph</tt></td>
</tr> </tr>
<tr>
<td><tt>-tuv</tt></td>
<td><tt>--transform-uv-coords</tt></td>
<td>Will transform uv-coordinates if possible.</td>
</tr>
<tr>
<td><tt>-guv</tt></td>
<td><tt>--gen-uvcoords</tt></td>
<td>Will generate uv-coordinates for textures if possible.</td>
</tr>
<tr>
<td><tt>-fid</tt></td>
<td><tt>--find-invalid-data</tt></td>
<td>Will look for invalid data in the imported model structure.</td>
</tr>
<tr>
<td><tt>-fixn</tt></td>
<td><tt>--fix normals</tt></td>
<td>Imported normal vector will be fixed.</td>
</tr>
<tr>
<td><tt>-db</tt></td>
<td><tt>--debone</tt></td>
<td>Removes nearly losslessly or according to a configured threshold bones from the model.</td>
</tr>
<tr>
<td><tt>-sbc</tt></td>
<td><tt>--split-by-bone-count</tt></td>
<td>Split meshes with too many bones. Necessary for our (limited) hardware skinning shader.</td>
</tr>
</table> </table>
For convenience some default postprocessing configurations are provided. For convenience some default postprocessing configurations are provided.

View File

@ -714,30 +714,33 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Helper function to get all parameters pertaining to a /** Helper function to get all parameters pertaining to a
* particular texture slot from a material. * particular texture slot from a material.
* *
* This function is provided just for convenience, you could also * This function is provided just for convenience, you could also
* read the single material properties manually. * read the single material properties manually.
* @param type Specifies the type of the texture to be retrieved ( * @param type Specifies the type of the texture to be retrieved (
* e.g. diffuse, specular, height map ...) * e.g. diffuse, specular, height map ...)
* @param index Index of the texture to be retrieved. The function fails * @param index Index of the texture to be retrieved. The function fails
* if there is no texture of that type with this index. * if there is no texture of that type with this index.
* #GetTextureCount() can be used to determine the number of textures * #GetTextureCount() can be used to determine the number of textures
* per texture type. * per texture type.
* @param path Receives the path to the texture. * @param path Receives the path to the texture.
* NULL is a valid value. * If the texture is embedded, receives a '*' followed by the id of
* @param mapping The texture mapping. * the texture (for the textures stored in the corresponding scene) which
* NULL is allowed as value. * can be converted to an int using a function like atoi.
* @param uvindex Receives the UV index of the texture. * NULL is a valid value.
* NULL is a valid value. * @param mapping The texture mapping.
* @param blend Receives the blend factor for the texture * NULL is allowed as value.
* NULL is a valid value. * @param uvindex Receives the UV index of the texture.
* @param op Receives the texture operation to be performed between * NULL is a valid value.
* this texture and the previous texture. NULL is allowed as value. * @param blend Receives the blend factor for the texture
* @param mapmode Receives the mapping modes to be used for the texture. * NULL is a valid value.
* The parameter may be NULL but if it is a valid pointer it MUST * @param op Receives the texture operation to be performed between
* point to an array of 3 aiTextureMapMode's (one for each * this texture and the previous texture. NULL is allowed as value.
* axis: UVW order (=XYZ)). * @param mapmode Receives the mapping modes to be used for the texture.
*/ * The parameter may be NULL but if it is a valid pointer it MUST
* point to an array of 3 aiTextureMapMode's (one for each
* axis: UVW order (=XYZ)).
*/
// ------------------------------------------------------------------- // -------------------------------------------------------------------
aiReturn GetTexture(aiTextureType type, aiReturn GetTexture(aiTextureType type,
unsigned int index, unsigned int index,
@ -1506,7 +1509,10 @@ ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMa
* #aiGetMaterialTextureCount() can be used to determine the number of * #aiGetMaterialTextureCount() can be used to determine the number of
* textures in a particular texture stack. * textures in a particular texture stack.
* @param[out] path Receives the output path * @param[out] path Receives the output path
* This parameter must be non-null. * If the texture is embedded, receives a '*' followed by the id of
* the texture (for the textures stored in the corresponding scene) which
* can be converted to an int using a function like atoi.
* This parameter must be non-null.
* @param mapping The texture mapping mode to be used. * @param mapping The texture mapping mode to be used.
* Pass NULL if you're not interested in this information. * Pass NULL if you're not interested in this information.
* @param[out] uvindex For UV-mapped textures: receives the index of the UV * @param[out] uvindex For UV-mapped textures: receives the index of the UV

View File

@ -216,7 +216,7 @@ struct aiColor3D
/** Check whether a color is black */ /** Check whether a color is black */
bool IsBlack() const { bool IsBlack() const {
static const ai_real epsilon = 10e-3; static const ai_real epsilon = ai_real(10e-3);
return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon; return std::fabs( r ) < epsilon && std::fabs( g ) < epsilon && std::fabs( b ) < epsilon;
} }

View File

@ -54,6 +54,7 @@ SOURCE_GROUP( unit FILES
SET( TEST_SRCS SET( TEST_SRCS
unit/AssimpAPITest.cpp unit/AssimpAPITest.cpp
unit/utBlenderIntermediate.cpp
unit/utBlendImportAreaLight.cpp unit/utBlendImportAreaLight.cpp
unit/utBlendImportMaterials.cpp unit/utBlendImportMaterials.cpp
unit/utColladaExportCamera.cpp unit/utColladaExportCamera.cpp

View File

@ -63,7 +63,7 @@ def log( sev, msg ):
logEntry = logEntry + "[WARN]: " logEntry = logEntry + "[WARN]: "
elif sev == 2: elif sev == 2:
logEntry = logEntry + "[ERR] : " logEntry = logEntry + "[ERR] : "
logEntry = logEntry + msg logEntry = logEntry + str( msg )
print( logEntry ) print( logEntry )
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------

Binary file not shown.

View File

@ -0,0 +1,67 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include "BlenderIntermediate.h"
using namespace ::Assimp;
using namespace ::Assimp::Blender;
class BlenderIntermediateTest : public ::testing::Test {
// empty
};
TEST_F( BlenderIntermediateTest,ConversionData_ObjectCompareTest ) {
Object obj1, obj2;
strncpy( obj1.id.name, "name1", 5 );
strncpy( obj2.id.name, "name2", 5 );
Blender::ObjectCompare cmp_false;
bool res( cmp_false( &obj1, &obj2 ) );
EXPECT_FALSE( res );
Blender::ObjectCompare cmp_true;
res = cmp_true( &obj1, &obj1 );
EXPECT_TRUE( res );
}

View File

@ -48,7 +48,12 @@ class utDefaultIOStream : public ::testing::Test {
class TestDefaultIOStream : public DefaultIOStream { class TestDefaultIOStream : public DefaultIOStream {
public: public:
TestDefaultIOStream() TestDefaultIOStream()
: DefaultIOStream() { : DefaultIOStream() {
// empty
}
TestDefaultIOStream( FILE* pFile, const std::string &strFilename )
: DefaultIOStream( pFile, strFilename ) {
// empty // empty
} }
@ -58,7 +63,14 @@ public:
}; };
TEST_F( utDefaultIOStream, FileSizeTest ) { TEST_F( utDefaultIOStream, FileSizeTest ) {
TestDefaultIOStream myStream; char buffer[ L_tmpnam ];
tmpnam( buffer );
std::FILE *fs( std::fopen( buffer, "w+" ) );
size_t written( std::fwrite( buffer, 1, sizeof( char ) * L_tmpnam, fs ) );
std::fflush( fs );
TestDefaultIOStream myStream( fs, buffer );
size_t size = myStream.FileSize(); size_t size = myStream.FileSize();
EXPECT_EQ( size, 0 ); EXPECT_EQ( size, sizeof( char ) * L_tmpnam );
remove( buffer );
} }

View File

@ -378,7 +378,6 @@ int ProcessStandardArguments(
// -fixn --fix normals // -fixn --fix normals
// -tri --triangulate // -tri --triangulate
// -fi --find-instances // -fi --find-instances
// -fi --find-instances
// -og --optimize-graph // -og --optimize-graph
// -om --optimize-meshes // -om --optimize-meshes
// -db --debone // -db --debone

View File

@ -0,0 +1,44 @@
project(assimp_qt_viewer)
set(PROJECT_VERSION "")
cmake_minimum_required(VERSION 2.6)
find_package(Qt4 REQUIRED)
find_package(DevIL REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(
${QT_INCLUDES}
${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)
qt4_wrap_ui(UISrcs mainwindow.ui)
qt4_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
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)
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})

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,382 @@
/// \file glview.hpp
/// \brief OpenGL visualisation.
/// \author smal.root@gmail.com
/// \date 2016
#pragma once
// Header files, Qt.
#include <QtOpenGL>
// Header files Assimp
#include <assimp/scene.h>
/// \class CGLView
/// Class which hold and render scene.
class CGLView : public QGLWidget
{
Q_OBJECT
/**********************************/
/************* Types **************/
/**********************************/
private:
/// \struct SBBox
/// Bounding box for object.
struct SBBox
{
aiVector3D Minimum;///< Minimum values of coordinates.
aiVector3D Maximum;///< Maximum values of coordinates.
};
/// \struct SHelper_Mesh
/// Helper object for fast rendering of mesh (\ref aiMesh).
struct SHelper_Mesh
{
const size_t Quantity_Point;///< Quantity of points.
const size_t Quantity_Line;///< Quantity of lines.
const size_t Quantity_Triangle;///< Quantity of triangles.
GLuint* Index_Point;///< Array of indices for drawing points.
GLuint* Index_Line;///< Array of indices for drawing lines.
GLuint* Index_Triangle;///< Array of indices for drawing triangles.
const SBBox BBox;///< BBox of mesh.
/// \fn explicit SHelper_Mesh(const size_t pQuantity_Point, const size_t pQuantity_Line, const size_t pQuantity_Triangle, const SBBox& pBBox = {{0, 0, 0}, {0, 0, 0}})
/// Constructor.
/// \param [in] pQuantity_Point - quantity of points.
/// \param [in] pQuantity_Line - quantity of lines.
/// \param [in] pQuantity_Triangle - quantity of triangles.
/// \param [in] pBBox - BBox of mesh.
explicit SHelper_Mesh(const size_t pQuantity_Point, const size_t pQuantity_Line, const size_t pQuantity_Triangle, const SBBox& pBBox = {{0, 0, 0}, {0, 0, 0}});
/// \fn ~SHelper_Mesh()
/// Destructor.
~SHelper_Mesh();
};
/// \struct SHelper_Camera
/// Information about position of the camera in space.
struct SHelper_Camera
{
aiVector3D Position;///< Coordinates of the camera.
aiVector3D Target;///< Target point of the camera.
// Transformation path:
// set Camera -> Rotation_AroundCamera -> Translation_ToScene -> Rotation_Scene -> draw Scene
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.
aiVector3D Translation_ToScene;///< Translation vector from camera to the scene.
/// \fn void SetDefault()
/// Set default parameters of camera.
void SetDefault();
};
public:
/// \enum ELightType
/// Type of light source.
enum class ELightType { Directional, Point, Spot };
/// \struct SLightParameters
/// Parameters of light source.
struct SLightParameters
{
aiLightSourceType Type;///< Type of light source.
aiColor4D Ambient;///< Ambient RGBA intensity of the light.
aiColor4D Diffuse;///< Diffuse RGBA intensity of the light.
aiColor4D Specular;///< Specular RGBA intensity of the light.
union UFor
{
/// \struct SDirectional
/// Parameters of directional light source.
struct SDirectional
{
aiVector3D Direction;
SDirectional() {}
} Directional;
/// \struct SPoint
/// Parameters of point light source.
struct SPoint
{
aiVector3D Position;
GLfloat Attenuation_Constant;
GLfloat Attenuation_Linear;
GLfloat Attenuation_Quadratic;
SPoint() {}
} Point;
/// \struct SSpot
/// Parameters of spot light source.
struct SSpot
{
aiVector3D Position;
GLfloat Attenuation_Constant;
GLfloat Attenuation_Linear;
GLfloat Attenuation_Quadratic;
aiVector3D Direction;
GLfloat CutOff;
SSpot() {}
} Spot;
UFor() {}
} For;
SLightParameters() {}
};
/**********************************/
/************ Variables ***********/
/**********************************/
private:
// 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.
// 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.
// Cameras
SHelper_Camera mHelper_Camera;///< Information about current camera placing in space.
SHelper_Camera mHelper_CameraDefault;///< Information about default camera initial placing in space.
bool mCamera_DefaultAdded = true;///< If true then scene has no defined cameras and default was added, if false - scene has defined cameras.
GLdouble mCamera_FOVY = 45.0;///< Specifies the field of view angle, in degrees, in the y direction.
GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
// Lighting
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
// Textures
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
/**********************************/
/************ Functions ***********/
/**********************************/
private:
// Why in some cases pointers are used? Because: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
template<typename TArg> void AssignIfLesser(TArg* pBaseValue, const TArg pTestValue) { if(pTestValue < *pBaseValue) *pBaseValue = pTestValue; }
template<typename TArg> void AssignIfGreater(TArg* pBaseValue, const TArg pTestValue) { if(pTestValue > *pBaseValue) *pBaseValue = pTestValue; }
template<typename TArg> void AssignIfLesser(TArg& pBaseValue, const TArg pTestValue) { if(pTestValue < pBaseValue) pBaseValue = pTestValue; }
template<typename TArg> void AssignIfGreater(TArg& pBaseValue, const TArg pTestValue) { if(pTestValue > pBaseValue) pBaseValue = pTestValue; }
/// \fn void Material_Apply(const aiMaterial* pMaterial)
/// Enable pointed material.
/// \param [in] pMaterial - pointer to material which must be used.
void Material_Apply(const aiMaterial* pMaterial);
/// \fn void Matrix_NodeToRoot(const aiNode* pNode, aiMatrix4x4& pOutMatrix)
/// Calculate matrix for transforming coordinates from pointed node to root node (read as "global coordinate system").
/// \param [in] pNode - pointer initial node from which relative coordintaes will be taken,
/// \param [out] pOutMatrix - matrix for transform relative coordinates in \ref pNode to coordinates in root node (\ref aiScene::mRootNode).
void Matrix_NodeToRoot(const aiNode* pNode, aiMatrix4x4& pOutMatrix);
/// \fn void ImportTextures()
/// Import textures.
/// \param [in] pScenePath - path to the file of the scene.
void ImportTextures(const QString& pScenePath);
/// \fn void BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParentNode_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign)
/// Calculate BBox for pointed node. Function walk thru child nodes and apply all transformations.
/// \param [in] pNode - reference to node for which needed BBox.
/// \param [in] pParent_TransformationMatrix - reference to parent (parent for pNode) transformation matrix.
/// \param [in,out] pNodeBBox - reference to where pNode BBox will be placed. It will expanded by child nodes BBoxes.
/// \param [in] pFirstAssign - means that pNodeBBox not contain valid BBox at now and assign ('=') will used for setting new value, If
/// false then \ref BBox_Extend will be used for setting new BBox.
void BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParent_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign);
/// \fn void BBox_Extend(const SBBox& pChild, SBBox& pParent)
/// Check and if need - extend current node BBox with BBox of child node.
/// \param [in] pChild - reference to BBox which used for extend parent BBox.
/// \param [in.out] pParent - BBox which will be extended using child BBox.
void BBox_Extend(const SBBox& pChild, SBBox& pParent);
/// \fn void BBox_GetVertices(const SBBox& pBBox, aiVector3D pVertices[8])
/// Get vertices of a parallelepiped which is described by BBox.
/// \param [in] pBBox - input BBox.
/// \param [out] pVertices - array of vertices.
void BBox_GetVertices(const SBBox& pBBox, aiVector3D pVertices[8]);
/// \fn void BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVerticesQuantity, SBBox& pBBox)
/// Calculate BBox for vertices array.
/// \param [in] pVertices - vertices array.
/// \param [in] pVerticesQuantity - quantity of vertices in array. If 0 then pBBox will be assigned with {{0, 0, 0}, {0, 0, 0}}.
/// \param [out] pBBox - calculated BBox.
void BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVerticesQuantity, SBBox& pBBox);
/********************************************************************/
/************************ Logging functions *************************/
/********************************************************************/
/// \fn void LogInfo(const QString& pMessage)
/// Add message with severity "Warning" to log.
void LogInfo(const QString& pMessage);
/// \fn void LogError(const QString& pMessage)
/// Add message with severity "Error" to log.
void LogError(const QString& pMessage);
/********************************************************************/
/************************** Draw functions **************************/
/********************************************************************/
/// \fn void Draw_Node(const aiNode* pNode)
/// Apply node transformation and draw meshes assigned to this node.
/// \param [in] pNode - pointer to node for drawing (\ref aiNode).
void Draw_Node(const aiNode* pNode);
/// \fn void Draw_Mesh(const size_t pMesh_Index)
/// Draw mesh.
/// \param [in] pMesh_Index - index of mesh which must be drawn. Index point to mesh in \ref mHelper_Mesh.
void Draw_Mesh(const size_t pMesh_Index);
/// \fn void Draw_BBox(const SBBox& pBBox)
/// Draw bounding box using lines.
/// \param [in] pBBox - bounding box for drawing.
void Draw_BBox(const SBBox& pBBox);
/********************************************************************/
/*********************** Overrided functions ************************/
/********************************************************************/
protected:
/// \fn void initializeGL() override
/// Overrided function for initialise OpenGL.
void initializeGL() override;
/// \fn void resizeGL(int pWidth, int pHeight) override
/// \param [in] pWidth - new width of viewport.
/// \param [in] pHeight - new height of viewport.
void resizeGL(int pWidth, int pHeight) override;
/// \fn void paintGL() override
/// Overrided function for rendering.
void paintGL() override;
public:
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
/// \fn explicit CGLView(QWidget* pParent)
/// Constructor.
/// \param [in] pParent - parent widget.
explicit CGLView(QWidget* pParent);
/// \fn virtual ~CGLView()
/// Destructor.
virtual ~CGLView();
/********************************************************************/
/********************* Scene control functions **********************/
/********************************************************************/
/// \fn void FreeScene()
/// Free all helper objects data.
void FreeScene();
/// \fn void SetScene(const aiScene* pScene)
/// Set scene for rendering.
/// \param [in] pScene - pointer to scene.
/// \param [in] pScenePath - path to the file of the scene.
void SetScene(const aiScene* pScene, const QString& pScenePath);
/// \fn void Enable_SceneBBox(const bool pEnable)
/// Enable drawing scene bounding box.
/// \param [in] pEnable - if true then bbox will be drawing, if false - will not be drawing.
void Enable_SceneBBox(const bool pEnable) { mScene_DrawBBox = pEnable; }
/// \fn void Enable_Textures(const bool pEnable)
/// Control textures drawing.
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Textures(const bool pEnable);
/********************************************************************/
/******************** Lighting control functions ********************/
/********************************************************************/
/// \fn void Lighting_Enable()
/// Enable OpenGL lighting.
void Lighting_Enable();
/// \fn void Lighting_Disable()
/// Disable OpenGL lighting.
void Lighting_Disable();
/// \fn void Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters)
/// Edit light source properties.
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
/// \param [in] pLightParameters - light source parameters.
void Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters);///TODO: function set
/// \fn void Lighting_EnableSource(const size_t pLightNumber)
/// Enable light source.
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
void Lighting_EnableSource(const size_t pLightNumber);
///void Lighting_DisableSource(const size_t pLightNumber)
/// Disable light source,
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
void Lighting_DisableSource(const size_t pLightNumber);
/********************************************************************/
/******************** Cameras control functions *********************/
/********************************************************************/
/// \fn void Camera_Set(const size_t pCameraNumber)
/// Set view from pointed camera.
/// \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)
/// 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);
/// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
/// 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);
/// \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.
/// \param [in] pTranslate_X - specifies the X coordinate of translation vector.
/// \param [in] pTranslate_Y - specifies the Y coordinate of translation vector.
/// \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);
signals:
/// \fn void Paint_Finished(const size_t pPaintTime, const GLfloat pDistance)
///< Signal. Emits when execution of \ref paintGL is end.
/// \param [out] pPaintTime_ms - time spent for rendering, in milliseconds.
/// \param [out] pDistance - distance between current camera and center of the scene. \sa SHelper_Camera::Translation_ToScene.
void Paint_Finished(const size_t pPaintTime_ms, const GLfloat pDistance);
/// \fn void SceneObject_Camera(const QString& pName)
/// Signal. Emit for every camera found in scene. Also for default camera.
/// \param [out] pName - name of the camera.
void SceneObject_Camera(const QString& pName);
/// \fn void SceneObject_LightSource(const QString& pName)
/// Signal. Emit for every light source found in scene. Also for default light source.
/// \param [out] pName - name of the light source.
void SceneObject_LightSource(const QString& pName);
};// class CGLView

View File

@ -0,0 +1,19 @@
/// \file loggerview.cpp
/// \brief Stream for Assimp logging subsystem.
/// \author smal.root@gmail.com
/// \date 2016
#include "loggerview.hpp"
// Header files, Qt.
#include <QTime>
CLoggerView::CLoggerView(QTextBrowser* pOutputWidget)
: mOutputWidget(pOutputWidget)
{
}
void CLoggerView::write(const char *pMessage)
{
mOutputWidget->insertPlainText(QString("[%1] %2").arg(QTime::currentTime().toString()).arg(pMessage));
}

View File

@ -0,0 +1,33 @@
/// \file loggerview.hpp
/// \brief Stream for Assimp logging subsystem.
/// \author smal.root@gmail.com
/// \date 2016
#pragma once
// Header files, Qt.
#include <QTextBrowser>
// Header files, Assimp.
#include <assimp/DefaultLogger.hpp>
/// \class CLoggerView
/// GUI-stream for Assimp logging subsytem. Get data for logging and write it to output widget.
class CLoggerView final : public Assimp::LogStream
{
private:
QTextBrowser* mOutputWidget;///< Widget for displaying messages.
public:
/// \fn explicit CLoggerView(QTextBrowser* pOutputWidget)
/// Constructor.
/// \param [in] pOutputWidget - pointer to output widget.
explicit CLoggerView(QTextBrowser* pOutputWidget);
/// \fn virtual void write(const char *pMessage)
/// Write message to output widget. Used by Assimp.
/// \param [in] pMessage - message for displaying.
virtual void write(const char *pMessage);
};

View File

@ -0,0 +1,21 @@
/// \file main.cpp
/// \brief Start-up file which contain function "main".
/// \author smal.root@gmail.com
/// \date 2016
// Thanks to acorn89 for support.
// Header files, project.
#include "mainwindow.hpp"
// Header files, Qt.
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

View File

@ -0,0 +1,344 @@
/// \file mainwindow.hpp
/// \brief Main window and algorhytms.
/// \author smal.root@gmail.com
/// \date 2016
#include "mainwindow.hpp"
#include "ui_mainwindow.h"
// Header files, Assimp.
#include <assimp/Exporter.hpp>
#include <assimp/postprocess.h>
#ifndef __unused
#define __unused __attribute__((unused))
#endif // __unused
/**********************************/
/************ Functions ***********/
/**********************************/
/********************************************************************/
/********************* Import/Export functions **********************/
/********************************************************************/
void MainWindow::ImportFile(const QString &pFileName)
{
using namespace Assimp;
QTime time_begin = QTime::currentTime();
if(mScene != nullptr)
{
mImporter.FreeScene();
mGLView->FreeScene();
}
// Try to import scene.
mScene = mImporter.ReadFile(pFileName.toStdString(), aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_ValidateDataStructure | \
aiProcess_GenUVCoords | aiProcess_TransformUVCoords | aiProcess_FlipUVs);
if(mScene != nullptr)
{
ui->lblLoadTime->setText(QString("%1").arg(time_begin.secsTo(QTime::currentTime())));
LogInfo("Import done: " + pFileName);
// Prepare widgets for new scene.
ui->leFileName->setText(pFileName.right(pFileName.length() - pFileName.lastIndexOf('/') - 1));
ui->lstLight->clear();
ui->lstCamera->clear();
ui->cbxLighting->setChecked(true), mGLView->Lighting_Enable();
ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
ui->cbxTextures->setChecked(true), mGLView->Enable_Textures(true);
//
// Fill info labels
//
// Cameras
ui->lblCameraCount->setText(QString("%1").arg(mScene->mNumCameras));
// Lights
ui->lblLightCount->setText(QString("%1").arg(mScene->mNumLights));
// Meshes, faces, vertices.
size_t qty_face = 0;
size_t qty_vert = 0;
for(size_t idx_mesh = 0; idx_mesh < mScene->mNumMeshes; idx_mesh++)
{
qty_face += mScene->mMeshes[idx_mesh]->mNumFaces;
qty_vert += mScene->mMeshes[idx_mesh]->mNumVertices;
}
ui->lblMeshCount->setText(QString("%1").arg(mScene->mNumMeshes));
ui->lblFaceCount->setText(QString("%1").arg(qty_face));
ui->lblVertexCount->setText(QString("%1").arg(qty_vert));
// Animation
if(mScene->mNumAnimations)
ui->lblHasAnimation->setText("yes");
else
ui->lblHasAnimation->setText("no");
//
// Set scene for GL viewer.
//
mGLView->SetScene(mScene, pFileName);
// Select first camera
ui->lstCamera->setCurrentRow(0);
mGLView->Camera_Set(0);
// Scene is loaded, do first rendering.
LogInfo("Scene is ready for rendering.");
mGLView->updateGL();
}
else
{
ui->lblLoadTime->clear();
LogError(QString("Error parsing \'%1\' : \'%2\'").arg(pFileName).arg(mImporter.GetErrorString()));
}// if(mScene != nullptr)
}
/********************************************************************/
/************************ Logging functions *************************/
/********************************************************************/
void MainWindow::LogInfo(const QString& pMessage)
{
Assimp::DefaultLogger::get()->info(pMessage.toStdString());
}
void MainWindow::LogError(const QString& pMessage)
{
Assimp::DefaultLogger::get()->error(pMessage.toStdString());
}
/********************************************************************/
/*********************** Overrided functions ************************/
/********************************************************************/
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();
}
void MainWindow::mouseMoveEvent(QMouseEvent* pEvent)
{
if(pEvent->buttons() & Qt::LeftButton)
{
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->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.
mGLView->updateGL();
mPosition_Pressed_LMB = pEvent->pos();
}
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->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.
mGLView->updateGL();
mPosition_Pressed_RMB = pEvent->pos();
}
}
void MainWindow::keyPressEvent(QKeyEvent* pEvent)
{
GLfloat step;
if(pEvent->modifiers() & Qt::ControlModifier)
step = 10;
else if(pEvent->modifiers() & Qt::AltModifier)
step = 100;
else
step = 1;
if(pEvent->key() == Qt::Key_A)
mGLView->Camera_Translate(-step, 0, 0);
else if(pEvent->key() == Qt::Key_D)
mGLView->Camera_Translate(step, 0, 0);
else if(pEvent->key() == Qt::Key_W)
mGLView->Camera_Translate(0, step, 0);
else if(pEvent->key() == Qt::Key_S)
mGLView->Camera_Translate(0, -step, 0);
else if(pEvent->key() == Qt::Key_Up)
mGLView->Camera_Translate(0, 0, -step);
else if(pEvent->key() == Qt::Key_Down)
mGLView->Camera_Translate(0, 0, step);
mGLView->updateGL();
}
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow),
mScene(nullptr)
{
using namespace Assimp;
ui->setupUi(this);
// Create OpenGL widget
mGLView = new CGLView(this);
mGLView->setMinimumSize(800, 600);
mGLView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
mGLView->setFocusPolicy(Qt::StrongFocus);
// Connect to GLView signals.
connect(mGLView, SIGNAL(Paint_Finished(size_t, GLfloat)), SLOT(Paint_Finished(size_t, GLfloat)));
connect(mGLView, SIGNAL(SceneObject_Camera(QString)), SLOT(SceneObject_Camera(QString)));
connect(mGLView, SIGNAL(SceneObject_LightSource(QString)), SLOT(SceneObject_LightSource(QString)));
// and add it to layout
ui->hlMainView->insertWidget(0, mGLView, 4);
// Create logger
mLoggerView = new CLoggerView(ui->tbLog);
DefaultLogger::create("", Logger::VERBOSE);
DefaultLogger::get()->attachStream(mLoggerView, DefaultLogger::Debugging | DefaultLogger::Info | DefaultLogger::Err | DefaultLogger::Warn);
}
MainWindow::~MainWindow()
{
using namespace Assimp;
DefaultLogger::get()->detatchStream(mLoggerView, DefaultLogger::Debugging | DefaultLogger::Info | DefaultLogger::Err | DefaultLogger::Warn);
DefaultLogger::kill();
if(mScene != nullptr) mImporter.FreeScene();
if(mLoggerView != nullptr) delete mLoggerView;
if(mGLView != nullptr) delete mGLView;
delete ui;
}
/********************************************************************/
/****************************** Slots *******************************/
/********************************************************************/
void MainWindow::Paint_Finished(const size_t pPaintTime_ms, const GLfloat pDistance)
{
ui->lblRenderTime->setText(QString("%1").arg(pPaintTime_ms));
ui->lblDistance->setText(QString("%1").arg(pDistance));
}
void MainWindow::SceneObject_Camera(const QString& pName)
{
ui->lstCamera->addItem(pName);
}
void MainWindow::SceneObject_LightSource(const QString& pName)
{
ui->lstLight->addItem(pName);
// After item added "currentRow" is still contain old value (even '-1' if first item added). Because "currentRow"/"currentItem" is changed by user interaction,
// not by "addItem". So, "currentRow" must be set manually.
ui->lstLight->setCurrentRow(ui->lstLight->count() - 1);
// And after "selectAll" handler of "signal itemSelectionChanged" will get right "currentItem" and "currentRow" values.
ui->lstLight->selectAll();
}
void MainWindow::on_butOpenFile_clicked()
{
aiString filter_temp;
QString filename, filter;
mImporter.GetExtensionList(filter_temp);
filter = filter_temp.C_Str();
filter.replace(';', ' ');
filter.append(" ;; All (*.*)");
filename = QFileDialog::getOpenFileName(this, "Choose the file", "", filter);
if(!filename.isEmpty()) ImportFile(filename);
}
void MainWindow::on_butExport_clicked()
{
using namespace Assimp;
QString filename, filter, format_id;
Exporter exporter;
QTime time_begin;
aiReturn rv;
if(mScene == nullptr)
{
QMessageBox::critical(this, "Export error", "Scene is empty");
return;
}
// build filter
{
aiString filter_temp;
mImporter.GetExtensionList(filter_temp);
filter = filter_temp.C_Str();
filter.replace(';', ' ');
}
// get file path
filename = QFileDialog::getSaveFileName(this, "Set file name", "", filter);
// extract format ID
format_id = filename.right(filename.length() - filename.lastIndexOf('.') - 1);
if(format_id.isEmpty())
{
QMessageBox::critical(this, "Export error", "File name must has extension.");
return;
}
// begin export
time_begin = QTime::currentTime();
rv = exporter.Export(mScene, format_id.toLocal8Bit(), filename.toLocal8Bit());
ui->lblExportTime->setText(QString("%1").arg(time_begin.secsTo(QTime::currentTime())));
if(rv == aiReturn_SUCCESS)
LogInfo("Export done: " + filename);
else
LogError("Export failed: " + filename);
}
void MainWindow::on_cbxLighting_clicked(bool pChecked)
{
if(pChecked)
mGLView->Lighting_Enable();
else
mGLView->Lighting_Disable();
mGLView->updateGL();
}
void MainWindow::on_lstLight_itemSelectionChanged()
{
bool selected = ui->lstLight->isItemSelected(ui->lstLight->currentItem());
if(selected)
mGLView->Lighting_EnableSource(ui->lstLight->currentRow());
else
mGLView->Lighting_DisableSource(ui->lstLight->currentRow());
mGLView->updateGL();
}
void MainWindow::on_lstCamera_clicked(__unused const QModelIndex &index)
{
mGLView->Camera_Set(ui->lstLight->currentRow());
mGLView->updateGL();
}
void MainWindow::on_cbxBBox_clicked(bool checked)
{
mGLView->Enable_SceneBBox(checked);
mGLView->updateGL();
}
void MainWindow::on_cbxTextures_clicked(bool checked)
{
mGLView->Enable_Textures(checked);
mGLView->updateGL();
}

View File

@ -0,0 +1,131 @@
/// \file mainwindow.hpp
/// \brief Main window and algorhytms.
/// \author smal.root@gmail.com
/// \date 2016
#pragma once
// Header files, Qt.
#include <QMainWindow>
// Header files, project.
#include "glview.hpp"
#include "loggerview.hpp"
// Header files, Assimp.
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
namespace Ui { class MainWindow; }
/// \class MainWindow
/// Main window and algorhytms.
class MainWindow : public QMainWindow
{
Q_OBJECT
/**********************************/
/************ Variables ***********/
/**********************************/
private:
Ui::MainWindow *ui;
CGLView* mGLView;///< Pointer to OpenGL render.
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.
/**********************************/
/************ Functions ***********/
/**********************************/
/********************************************************************/
/********************* Import/Export functions **********************/
/********************************************************************/
/// \fn void ImportFile(const QString& pFileName)
/// Import scene from file.
/// \param [in] pFileName - path and name of the file.
void ImportFile(const QString& pFileName);
/********************************************************************/
/************************ Logging functions *************************/
/********************************************************************/
/// \fn void LogInfo(const QString& pMessage)
/// Add message with severity "Warning" to log.
void LogInfo(const QString& pMessage);
/// \fn void LogError(const QString& pMessage)
/// Add message with severity "Error" to log.
void LogError(const QString& pMessage);
/********************************************************************/
/*********************** Overrided functions ************************/
/********************************************************************/
protected:
/// \fn void mousePressEvent(QMouseEvent* pEvent) override
/// Overrided function which handle mouse event "button pressed".
/// \param [in] pEvent - pointer to event data.
void mousePressEvent(QMouseEvent* pEvent) override;
/// \fn void mouseMoveEvent(QMouseEvent* pEvent) override
/// Overrided function which handle mouse event "move".
/// \param [in] pEvent - pointer to event data.
void mouseMoveEvent(QMouseEvent* pEvent) override;
/// \fn void keyPressEvent(QKeyEvent* pEvent) override
/// Overrided function which handle key event "key pressed".
/// \param [in] pEvent - pointer to event data.
void keyPressEvent(QKeyEvent* pEvent) override;
public:
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
/// \fn explicit MainWindow(QWidget* pParent = 0)
/// \param [in] pParent - pointer to parent widget.
explicit MainWindow(QWidget* pParent = 0);
/// \fn ~MainWindow()
/// Destructor.
~MainWindow();
/********************************************************************/
/****************************** Slots *******************************/
/********************************************************************/
private slots:
/// \fn void Paint_Finished(const int pPaintTime)
/// Show paint/render time and distance between camera and center of the scene.
/// \param [in] pPaintTime_ms - paint time in milliseconds.
void Paint_Finished(const size_t pPaintTime_ms, const GLfloat pDistance);
/// \fn void SceneObject_Camera(const QString& pName)
/// Add camera name to list.
/// \param [in] pName - name of the camera.
void SceneObject_Camera(const QString& pName);
/// \fn void SceneObject_LightSource(const QString& pName)
/// Add lighting source name to list.
/// \param [in] pName - name of the light source,
void SceneObject_LightSource(const QString& pName);
void on_butOpenFile_clicked();
void on_butExport_clicked();
void on_cbxLighting_clicked(bool pChecked);
void on_lstLight_itemSelectionChanged();
void on_lstCamera_clicked(const QModelIndex &index);
void on_cbxBBox_clicked(bool checked);
void on_cbxTextures_clicked(bool checked);
};

View File

@ -0,0 +1,516 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>641</width>
<height>734</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="5,1">
<item>
<layout class="QHBoxLayout" name="hlMainView" stretch="0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="grpFile">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="title">
<string>File</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QPushButton" name="butOpenFile">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Open file</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblFileName_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>File name</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leFileName">
<property name="maximumSize">
<size>
<width>160</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblLoadTime_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Load time, s</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lblLoadTime">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="Line" name="line">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QPushButton" name="butExport">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Export</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblExportTime_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Export time, s</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lblExportTime">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="grpInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="title">
<string>Info</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="lblRenderTime_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Render time, ms</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblRenderTime">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblMeshCount_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Meshes</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblFaceCount_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Faces</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblMeshCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lblFaceCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblVertexCount_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Vertices</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="lblVertexCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblLightCount_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Lights</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lblCameraCount_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Cameras</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lblHasAnimation_Label">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Animation</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblShaderCount_Label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Shaders</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="lblLightCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="lblCameraCount">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lblShaderCount">
<property name="enabled">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="lblHasAnimation">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="lblDistance_Label">
<property name="text">
<string>Distance</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="lblDistance">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="grpDynamics">
<property name="enabled">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="title">
<string>Dynamics</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="butAnimationStart">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Animation start</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="butAnimationStop">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>Animation stop</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabInfoAndControl">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Log</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTextBrowser" name="tbLog">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Lights and cameras</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="lstLight">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Light sources of the scene</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::SelectedClicked</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="lstCamera">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>Cameras of the scene</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Control</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QCheckBox" name="cbxLighting">
<property name="toolTip">
<string>Enable/Disable OpenGL lighting</string>
</property>
<property name="text">
<string>Lighting</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="cbxBBox">
<property name="text">
<string>Scene BBox</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="cbxTextures">
<property name="text">
<string>Textures</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -62,6 +62,7 @@ ADD_EXECUTABLE( assimp_viewer WIN32
Normals.cpp Normals.cpp
SceneAnimator.cpp SceneAnimator.cpp
Shaders.cpp Shaders.cpp
assimp_view.h
assimp_view.cpp assimp_view.cpp
stdafx.cpp stdafx.cpp
assimp_view.rc assimp_view.rc

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2015, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -160,7 +160,6 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
// Call ASSIMPs C-API to load the file // Call ASSIMPs C-API to load the file
g_pcAsset->pcScene = (aiScene*)aiImportFileExWithProperties(g_szFileName, g_pcAsset->pcScene = (aiScene*)aiImportFileExWithProperties(g_szFileName,
ppsteps | /* configurable pp steps */ ppsteps | /* configurable pp steps */
aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing
aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -71,14 +71,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../code/MaterialSystem.h" // aiMaterial class #include "../../code/MaterialSystem.h" // aiMaterial class
#include "../../code/StringComparison.h" // ASSIMP_stricmp and ASSIMP_strincmp #include "../../code/StringComparison.h" // ASSIMP_stricmp and ASSIMP_strincmp
// in order for std::min and std::max to behave properly
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif // max
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif // min
#include <time.h> #include <time.h>
// default movement speed // default movement speed